我在Oracle 10g中有一个查找表,其中包含一个触发器,用于在插入,更新和删除时填充历史表。我希望能够通过触发器从历史记录表中的ColdFusion应用程序中捕获用户ID。
我发现这样做的一种可能方法是使用Oracle会话变量: 在coldfusion代码中,我在插入,更新和删除代码之前将用户ID传递给Oracle会话:
CALL dbms_session.set_identifier(12345);
在触发器中,我读取了client_identifier var,交换了" 0"如果为null。
SELECT sys_context('USERENV','CLIENT_IDENTIFIER') INTO USER_ID FROM DUAL;
IF USER_ID IS NULL THEN
USER_ID := 0;
END IF;
在单用户测试中,这很好用,但由于我不知道CF应用服务器的数据库连接如何与Oracle会话相关,所以我担心oracle session var中的值多个同时用户将不可靠。
从Web应用程序设置Oracle会话变量是将Web应用程序中的值传递给触发器的可靠方法吗?
答案 0 :(得分:1)
假设您没有执行上面概述的内容(我认为这样做不可行),您可以在查找表中添加一列(让我们称之为MY_LOOKUP_TABLE
)在其中存储进行更新(或插入)的用户的用户ID:
ALTER TABLE my_lookup_table
ADD update_user_id NUMBER DEFAULT 0 NOT NULL;
(假设您的查找表不是很大,并且您不介意为每个现有行设置默认值。)
当你需要从查找表中删除一行时出现困难...你如何记录删除它的用户的ID?在这种情况下,您还需要一个列来记录该行已删除,可能是DELETE_FLAG
:
ALTER TABLE my_lookup_table
ADD delete_flag CHAR(1) DEFAULT 'N' NOT NULL;
然后,在您的更新触发器中,不要记录DELETE_FLAG = 'Y'
:
CREATE OR REPLACE TRIGGER record_update
AFTER UPDATE OF my_lookup_table
FOR EACH ROW
WHEN (new.delete_flag <> 'Y')
当您的应用删除时,您实际上需要更新后删除:
<cftransaction>
<cfquery name="update_before_delete_lookup">
UPDATE my_lookup_table
SET update_user_id = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#user_id#" />
, delete_flag = 'Y'
WHERE <conditions>
</cfquery>
<cfquery name="delete_lookup">
DELETE FROM my_lookup_table
WHERE <conditions>
</cfquery>
</cftransaction>