Oracle DBMS_会话集_上下文不存储值
我试图在Oracle中生成一个系统,其中上下文存储一个值;如果在任何会话中更新了表(更新/插入/删除),则应增加该值。我遇到的问题是,即使我确定我已经正确设置了它,它似乎不起作用-上下文似乎没有实际存储值。我正在使用Oracle 11.2.0.1.0 对于最低可能的示例: 我有一个上下文(ACCESSED GLOBALLY子句应使其能够在所有Oracle会话中访问这些值,这正是我想要的): 我有一个调试表:Oracle DBMS_会话集_上下文不存储值,oracle,session,global-variables,Oracle,Session,Global Variables,我试图在Oracle中生成一个系统,其中上下文存储一个值;如果在任何会话中更新了表(更新/插入/删除),则应增加该值。我遇到的问题是,即使我确定我已经正确设置了它,它似乎不起作用-上下文似乎没有实际存储值。我正在使用Oracle 11.2.0.1.0 对于最低可能的示例: 我有一个上下文(ACCESSED GLOBALLY子句应使其能够在所有Oracle会话中访问这些值,这正是我想要的): 我有一个调试表: CREATE TABLE DATALOG ( DATALOG_SEQ NUMBER,
CREATE TABLE DATALOG (
DATALOG_SEQ NUMBER,
AT_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
MESSAGE VARCHAR2(4000)
);
我有一个序列来支持DATALOG
表:
CREATE SEQUENCE SQ_DATALOG;
现在需要PCKG_TESTGLOBALS包,它可以访问MM_上下文
上下文,并可以更新其中的元素:
CREATE OR REPLACE PACKAGE PCKG_TESTGLOBALS IS
PROCEDURE Log(FunctionName IN VARCHAR2, Msg IN VARCHAR2);
PROCEDURE SetParameter(p_name IN VARCHAR2, p_value IN VARCHAR2);
FUNCTION GetTABLEID RETURN NUMBER;
END PCKG_TESTGLOBALS;
/
CREATE OR REPLACE PACKAGE BODY PCKG_TESTGLOBALS IS
CONTEXT_NAME CONSTANT VARCHAR2(100) := 'MM_CONTEXT';
PROCEDURE Log(FunctionName IN VARCHAR2, Msg IN VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO DATALOG(DATALOG_SEQ, MESSAGE) VALUES (SQ_DATALOG.NEXTVAL, FunctionName || ':' || Msg);
COMMIT;
END;
PROCEDURE SetParameter(p_name IN VARCHAR2, p_value IN VARCHAR2) IS
ActualValue VARCHAR2(10000);
BEGIN
Log('SetParameter', 'ENTERED');
Log('SetParameter', 'SETTING "' || p_name || '" TO "' || p_value || '"');
DBMS_SESSION.SET_CONTEXT(CONTEXT_NAME, p_name, p_value);
ActualValue := SYS_CONTEXT(CONTEXT_NAME, p_name);
Log('SetParameter', 'READ "' || p_name || '" AS "' || ActualValue || '"');
Log('SetParameter', 'EXITED');
END;
PROCEDURE Initialise IS
iTmp NUMBER;
BEGIN
Log('Initialise', 'ENTERED');
IF SYS_CONTEXT(CONTEXT_NAME, 'LOWNID') IS NULL THEN
iTmp := DBMS_RANDOM.RANDOM;
Log('Initialise', '"LOWNID" has no value, writing "' || iTmp || '"');
PCKG_TESTGLOBALS.SetParameter('LOWNID', iTmp);
END IF;
Log('Initialise', 'EXITED');
END;
FUNCTION GetTABLEID RETURN NUMBER IS
ReadValue VARCHAR2(32767);
BEGIN
Log('GetTABLEID', 'ENTERED');
ReadValue := SYS_CONTEXT(CONTEXT_NAME, 'LOWNID');
Log('GetTABLEID', 'READ VALUE OF "LOWNID" AS "' || ReadValue || '"');
Log('GetTABLEID', 'EXITED');
RETURN TO_NUMBER(ReadValue);
END;
BEGIN
Initialise;
END PCKG_TESTGLOBALS;
/
因此,要解释PCKG_TESTGLOBALS中的函数,请执行以下操作:
Log
-出于调试原因记录消息
SetParameter
-获取名称/值对,并使用DBMS\u会话将其存储。在MM\u上下文中设置上下文
Initialise
-对于会话变量LOWNID
,它检查变量是否为空,如果为空,则使用SetParameter
将其设置为随机值<代码>初始化
在会话中首次使用包时调用
GetTABLEID
-返回会话变量LOWNID
中存储的值
最后,还有一个名为TR_ONDML\u TL_LOWN
的触发器,它位于表LOWN
上,它的结构在这里并不重要,任何表都可以,并且在任何DML、INSERT、UPDATE或DELETE之后触发
CREATE OR REPLACE TRIGGER TR_ONDML_TL_LOWN
AFTER INSERT OR UPDATE OR DELETE ON LOWN
DECLARE
iTmp NUMBER;
BEGIN
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'ENTERED');
iTmp := PCKG_TESTGLOBALS.GetTABLEID;
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'Read Value "' || iTmp || '"');
iTmp := NVL(iTmp, 1) + 1;
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'Updated Value "' || iTmp || '"');
PCKG_TESTGLOBALS.SetParameter('LOWNID', iTmp);
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'EXITED');
END TR_ONDML_TL_LOWN;
/
因此,此触发器的目的是:每当更新表LOWN
时,会话变量LOWNID
的值将被读回,并将1添加到其中,然后被写回
如果在新会话中,我对LOWN
表进行了几次连续更新,我会在调试表中得到这些结果(SELECT MESSAGE FROM DATALOG ORDER BY DATALOG_SEQ
)
从示例中可以看出,它将值正确地传递给了
DBMS\u SESSION.SET\u CONTEXT
,但它似乎根本没有存储该值。我做错了什么?谢谢。对于要查看全局可访问上下文的值的会话,其客户端标识符
(根据SYS\u上下文('userenv','client\u identifier')
)必须与调用DBMS\u会话时使用的client\u id
参数匹配
如果您的set_context
调用未设置client_id
它默认为NULL;在这种情况下,只有当会话的client\u标识符
也为空时,会话才会看到新值
如果会话为client\u identifier
获取任何特定值,则必须在调用set\u context
时使用相同的值
在您的情况下,您需要一个所有会话都可以访问的全局变量;如果您的会话为客户机\u标识符获取随机值,您可能需要在运行代码之前将其设置为NULL,然后(可能)在将控制权返回给调用方之前恢复其值。奇怪的是,我尝试了这个方法,但仅在pl/sql块中调用了触发器代码,它对我有效。看起来不错。@old程序员我也觉得不错!非常令人沮丧!这是一个全局可访问的上下文,因此需要设置client\u id
以匹配会话的client\u标识符。如果它们不匹配,上下文将无法检索存储的值。检查会话中的客户端\u标识符。首先,我认为我说必须设置客户端id或用户是不正确的,这只适用于您希望使上下文为各个客户端会话保留单独的值的情况。我认为您应该不设置用户名,但请注意,如果客户端标识符(SYS\u CONTEXT('userenv','client\u identifier')
)发生更改,会话将看不到值。换句话说,如果会话1碰巧有client\u identifier=123,并且将上下文设置为没有客户端id,它将看不到上下文值。
CREATE OR REPLACE TRIGGER TR_ONDML_TL_LOWN
AFTER INSERT OR UPDATE OR DELETE ON LOWN
DECLARE
iTmp NUMBER;
BEGIN
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'ENTERED');
iTmp := PCKG_TESTGLOBALS.GetTABLEID;
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'Read Value "' || iTmp || '"');
iTmp := NVL(iTmp, 1) + 1;
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'Updated Value "' || iTmp || '"');
PCKG_TESTGLOBALS.SetParameter('LOWNID', iTmp);
PCKG_TESTGLOBALS.Log('TR_ONDML_TL_LOWN', 'EXITED');
END TR_ONDML_TL_LOWN;
/
Initialise:ENTERED
Initialise:"LOWNID" has no value, writing "805223597"
SetParameter:ENTERED
SetParameter:SETTING "LOWNID" TO "805223597"
SetParameter:READ "LOWNID" AS ""
SetParameter:EXITED
Initialise:EXITED
TR_ONDML_TL_LOWN:ENTERED
GetTABLEID:ENTERED
GetTABLEID:READ VALUE OF "LOWNID" AS ""
GetTABLEID:EXITED
TR_ONDML_TL_LOWN:Read Value ""
TR_ONDML_TL_LOWN:Updated Value "2"
SetParameter:ENTERED
SetParameter:SETTING "LOWNID" TO "2"
SetParameter:READ "LOWNID" AS ""
SetParameter:EXITED
TR_ONDML_TL_LOWN:EXITED
TR_ONDML_TL_LOWN:ENTERED
GetTABLEID:ENTERED
GetTABLEID:READ VALUE OF "LOWNID" AS ""
GetTABLEID:EXITED
TR_ONDML_TL_LOWN:Read Value ""
TR_ONDML_TL_LOWN:Updated Value "2"
SetParameter:ENTERED
SetParameter:SETTING "LOWNID" TO "2"
SetParameter:READ "LOWNID" AS ""
SetParameter:EXITED
TR_ONDML_TL_LOWN:EXITED