【问题标题】:Is it possible to use a variable to reference a column in an Oracle trigger?是否可以使用变量来引用 Oracle 触发器中的列?
【发布时间】:2021-01-26 18:17:40
【问题描述】:

我在旧版 Oracle 9 数据库中有一个表。我正在尝试编写一个触发器,如果​​对该表中的行进行更新,它将循环遍历表列,并为每一列 C 检查是否:old[C] = :new[C]

是否可以通过这种方式引用:old:new 的列数据,使用一些变量作为我们想要查看其数据的列名?

【问题讨论】:

  • Oracle 9 早已不复存在,现在是 Oracle 19c。是什么阻止你升级它?
  • 我们正试图将客户端移出的遗留基础架构,此触发器是移出客户端过程中的一种支持机制。我很清楚 Oracle 9 已尘埃落定,但请向我客户的工程部门提出,看看它能让你走多远.....
  • 回答你的问题,不清楚。请输入一些您尝试过的代码。并解释你到底想要什么。
  • @Ranagal 我的问题很清楚。是否可以使用语法:old[C]:new[C] 来引用绑定变量:old:new 上的列,其中C 是来自(例如)SELECT column_name FROM User_Tab_Columns WHERE Upper(Table_Name) = 'ACDB_AC_TYPES'; 的变量

标签: sql oracle triggers oracle9i


【解决方案1】:

首先您无法使用此查询找到所有表列:

SELECT *
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'my_table';

其次,为了遍历这些列并测试新旧值,您可以使用以下命令编写查询:EXECUTE IMMEDIATE ('<my query>'); like:

CREATE OR REPLACE TRIGGER [...]
    l_cnt NUMBER;
BEGIN
    EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM DUAL WHERE '||:old.C||' = '||:new.C INTO l_cnt;
END;

更新 1:

您也可以“手动”完成并像这样手动测试每一列:

CREATE OR REPLACE TRIGGER BEFORE UPDATE OF [...]
BEGIN
    IF :old.A != :new.A THEN
        --field A has changed
    ELSIF :old.B != :new.B THEN
        --field B has changed
    ELSIF :old.C != :new.C THEN
        --field C has changed
--continue with other fields
    END IF;
END;

编辑:将 ALL_TAB_COLUMNS 更改为 USER_TAB_COLUMNS

【讨论】:

  • 您还需要在所有者列上过滤ALL_TAB_COLUMNS,否则您会发现您正在从不同架构中的其他同名表中提取列。
  • 对,我忘了他的那个。或使用USER_TAB_COLUMNS。我会更新我的答案。
  • 嗨@SuperPoney,感谢您的回复。您能否为您提到的execute immediate 查询提供更多上下文?你是如何在 for 循环中使用它的?我已经围绕它编写了一个 for 循环,但是 [C] 的第一个实例 - 即 :old[C] 给了我一个带有意外标记的语法错误 [
  • 我已更新我的答案并将:old[C] 更改为正确的语法:old.CEXECUTE IMMEDIATEstatement 允许您从字符串执行查询。也许我误解了你的要求。如果你想测试每一列的新旧值,你需要知道它们的数据类型以便比较它们(为此你需要检查 USER_TAB_COLUMNS)。最简单的方法是逐个字段检查(假设您的表没有数百列)。请检查我的更新答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 2023-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多