从 Web 应用程序设置 Oracle 会话变量是将值从 Web 应用程序传递到触发器的可靠方法吗?

Is setting an Oracle session variable from a web app a reliable way to pass a value from a web app to a trigger?

我在 Oracle 10g 中进行了查找 table,其中的触发器在插入、更新和删除时填充了历史记录 table。我希望能够通过触发器从历史记录 table 中的 ColdFusion 应用程序捕获用户 ID。

我发现一种可能的方法是使用 Oracle 会话变量: 在 coldfusion 代码中,我在插入、更新和删除代码之前将用户 ID 传递给 Oracle 会话:

CALL dbms_session.set_identifier(12345);

在触发器中,我读取了 client_identifier 变量,如果为空则换成“0”。

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 会话 var 中的值在多个同时发生时不可靠用户。

从 Web 应用程序设置 Oracle 会话变量是否是将值从 Web 应用程序传递到触发器的可靠方法?

假设您没有执行上面概述的操作(我认为这是行不通的),而是在查找 table(我们称之为 MY_LOOKUP_TABLE)中添加一列,其中您将进行更新(或插入)的用户的用户 ID 存储到 table:

ALTER TABLE my_lookup_table
  ADD update_user_id NUMBER DEFAULT 0 NOT NULL;

(假设您的查找 table 不是很大,并且您不介意为每个现有行设置默认值。)

当您需要从查找中删除一行时,困难就来了 table ...您如何记录删除它的用户的 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>