首页 > 解决方案 > 有什么方法可以在 Oracle 表中找到更新的列

问题描述

我有一个包含近 800 列和 500k 数据的 oracle 表。我有一个要求,我只需要获取记录的更新列,而不是更新记录的 800 列。有没有办法只提取记录中更新的列?感谢你的帮助。

谢谢,迪亚

标签: oracle

解决方案


800 列有点疯狂,但是,我不知道......我想这样的表可能存在。

你可以从触发器开始。在触发器中,您可以比较 ":new.col_name" 与 ":old.col_name",但写 800 个比较麻烦。可以使用“IF UPDATING("COL_NAME")";但是,即使值没有改变,这也会返回 true。UPDATING 函数用于测试该列是否是更新语句的一部分(它可能包含也可能不包含与旧值不同的值)。

因此,要测试是否实际更改,您必须使用 :new 和 :old 对象并进行比较。Oracle 没有提供一种巧妙的反射方式来将这些作为一个集合进行比较,因此必须使用良好的 ol brute force。

你可以做的是用代码生成代码。使用针对 all_tab_columns 的 select 语句编写脚本,该脚本将生成每列所需的比较语句和其他代码行,然后将输出转储到触发器中。使用 dbms_output.put_line 吐出你想要的代码。

像这样写一个光标选择(这就是袖手旁观,你必须完成编码):

SELECT 
  'IF (:new.'||column_name||' <> :old.'||atc.column_name||') THEN' as my_ifstmt 
FROM
  all_tab_columns atc
WHERE
  atc.owner = 'MYSCHEMA'
  AND atc.table_name = 'MY_TABLE'

使用 dbms_output.put_line 转储结果以及将结果插入审计表或您想要执行的任何操作的语句:

dbms_output.put_line(my_cursor.my_ifstmt);
dbms_output.put_line('INSERT INTO my_audit_table... bla bla bla');
dbms_output.put_line("END IF;")

将所有内容放在光标循环中。不,该代码还不完整,也没有功能,但鉴于您的需求描述有限,我可能会使用这种方法。试着把其中的一些放在一起,我可以添加更多。


推荐阅读