您可以使用Oracle CONTEXT來存儲試圖在FOO表中插入/更新/刪除的Oracle用戶的名稱。當Oracle用戶提交或回滾時,通過使用我的存儲過程USER_LOCK和USER_UNLOCK清空(手動)Oracle CONTEXT。通過這種方式,您可以避免多個Oracle用戶同時訪問/更新和刪除操作,因爲您一次只能向一個Oracle用戶授予訪問權限。
通過USER_LOCK(name_of_the_user)過程,您可以在Oracle上下文中添加Oracle用戶的名稱。使用USER_UNLOCK(name_of_the_user)過程,您可以在Oracle上下文中刪除Oracle用戶的名稱。使用視圖locked_users,您可以確定Oracle用戶是否被鎖定,因爲如果它被鎖定,其名稱將出現在視圖中。以下代碼創建所有Oracle結構以實現所有目標:
CREATE OR REPLACE PACKAGE my_pkg
IS
PROCEDURE set_session_id (p_session_id NUMBER);
PROCEDURE set_ctx (p_name VARCHAR2, p_value VARCHAR2);
PROCEDURE close_session (p_session_id NUMBER);
END;
/
CREATE OR REPLACE PACKAGE BODY my_pkg
IS
g_session_id NUMBER;
PROCEDURE set_session_id (p_session_id NUMBER)
IS
BEGIN
g_session_id := p_session_id;
DBMS_SESSION.set_identifier (p_session_id);
END set_session_id;
--===============================================
PROCEDURE set_ctx (p_name VARCHAR2, p_value VARCHAR2)
IS
BEGIN
DBMS_SESSION.set_context ('App_Ctx',
p_name,
p_value,
USER,
g_session_id);
END set_ctx;
--===============================================
PROCEDURE close_session (p_session_id NUMBER)
IS
BEGIN
DBMS_SESSION.set_identifier (p_session_id);
DBMS_SESSION.clear_identifier;
END close_session;
--===============================================
END;
/
CREATE OR REPLACE CONTEXT APP_CTX
USING MY_PKG
ACCESSED GLOBALLY
/
CREATE OR REPLACE TYPE test_type AS TABLE OF VARCHAR2 (30);
/
CREATE OR REPLACE FUNCTION f_convert2 (p_list IN VARCHAR2)
RETURN test_type
PIPELINED
AS
--l_string LONG := p_list || ',';
l_string VARCHAR2 (4000) := p_list || ',';
l_comma_index PLS_INTEGER;
l_index PLS_INTEGER := 1;
BEGIN
LOOP
l_comma_index := INSTR (l_string, ',', l_index);
EXIT WHEN l_comma_index = 0;
PIPE ROW (SUBSTR (l_string, l_index, l_comma_index - l_index));
l_index := l_comma_index + 1;
END LOOP;
RETURN;
END f_convert2;
/
CREATE OR REPLACE FORCE VIEW locked_users (utente)
AS
SELECT COLUMN_VALUE utente
FROM TABLE (
f_convert2 (
REPLACE (
LTRIM (RTRIM (SYS_CONTEXT ('app_ctx', 'Var1', 4000), '*'),
'*'),
'**',
',')))
ORDER BY 1 ASC
/
CREATE OR REPLACE PROCEDURE user_lock (ne_user IN VARCHAR2)
IS
BEGIN
DECLARE
indice NUMBER;
appoggio_variabile1 VARCHAR2 (250);
BEGIN
-- my_pkg.close_session(1234);
my_pkg.set_session_id (1234);
appoggio_variabile1 := SYS_CONTEXT ('app_ctx', 'var1');
DBMS_OUTPUT.put_line (appoggio_variabile1);
IF INSTR (appoggio_variabile1, ne_user) >= 1
THEN
BEGIN
DBMS_OUTPUT.
put_line ('The user ' || ne_user || ' is already locked!');
END;
ELSE
BEGIN
my_pkg.
set_ctx ('Var1', appoggio_variabile1 || '*' || ne_user || '*');
DBMS_OUTPUT.
put_line ('The user ' || ne_user || ' is now locked.');
END;
END IF;
END;
END user_lock;
/
CREATE OR REPLACE PROCEDURE user_unlock (ne_user IN VARCHAR2)
IS
BEGIN
DECLARE
indice NUMBER;
appoggio_variabile1 VARCHAR2 (250);
BEGIN
-- my_pkg.close_session(1234);
my_pkg.set_session_id (1234);
appoggio_variabile1 := SYS_CONTEXT ('app_ctx', 'var1');
DBMS_OUTPUT.put_line (appoggio_variabile1);
IF INSTR (appoggio_variabile1, ne_user) = 0
OR appoggio_variabile1 IS NULL
THEN
BEGIN
DBMS_OUTPUT.
put_line ('The user ' || ne_user || ' is already unlocked!');
END;
ELSE
BEGIN
my_pkg.
set_ctx ('Var1',
REPLACE (appoggio_variabile1, '*' || ne_user || '*'));
DBMS_OUTPUT.
put_line ('The user ' || ne_user || ' is now unlocked.');
END;
END IF;
END;
END user_unlock;
/
謝謝......你的解釋幫助我理解了鎖本身給了我什麼。但是具有分析函數(count)的這個查詢是否鎖定了它的值構成的所有行? 'count(*)... for update'會鎖定並鎖定符合'where'條件的記錄嗎? – 2010-06-18 15:43:50
您的查詢將只鎖定在WHERE子句中指定的行。 – 2010-06-21 08:56:10