动态评估Oracle触发器中的伪记录(:旧,:新)

动态评估Oracle触发器中的伪记录(:旧,:新),oracle,Oracle,问题:我有一个表,客户可以向其中添加列。此表可能有数百列不同的数据类型,具体取决于客户的疯狂程度。我需要对此表部署一个更新后触发器,以便在另一个表中为每个已更改的列值插入一行 示例: 表A第1行:键值=1,Col1=123,Col2=“foo”…Coln=“bar” 变为 表B第1行:键值=1,ColName=“Col1”,ColValue=123 表B,第2行:Key_Value=1,ColName=“Col2”,ColValue=“foo” 表B第3行:键值=1,ColName=“Coln

问题:我有一个表,客户可以向其中添加列。此表可能有数百列不同的数据类型,具体取决于客户的疯狂程度。我需要对此表部署一个更新后触发器,以便在另一个表中为每个已更改的列值插入一行

示例:

  • 表A第1行:键值=1,Col1=123,Col2=“foo”…Coln=“bar”
  • 变为
  • 表B第1行:键值=1,ColName=“Col1”,ColValue=123
  • 表B,第2行:Key_Value=1,ColName=“Col2”,ColValue=“foo”
  • 表B第3行:键值=1,ColName=“Coln”,ColValue=“bar”
由于我不知道它们可能会创建哪些列,并且此触发器必须与应用程序一起部署,因此我需要动态评估新旧伪记录(
if:NEW.columns[1]!=:OLD.columns[1],然后…
),以查看发生了哪些更改,并只记录更改的列。我能找到的唯一示例需要显式引用伪记录中的列(
if:new.col1!=:old.col1 then…

问题:在Oracle中有这样做的方法吗

注意事项:不,这不是为了审计目的,因此我不能使用Oracle的内置审计功能。不,我们不会重写我们的应用程序,因为你知道如何做得更好,这是它需要做得更好或更糟的方式


欢迎提出任何有用的意见。所有斯内基DBA的废话都不是。提前感谢。

否。您不能动态引用
:new
:old
伪记录中的列


最接近的方法是编写代码,通过查询数据字典并对伪记录中的列进行静态引用,动态生成整个触发器体。但是,每次在表中添加或删除列时都需要运行该代码。通常,这将作为正常发布管理的一部分进行。如果您说人们在不经过发布过程的情况下在此表中添加和删除列,那么您可以编写一个DDL触发器,该触发器通过调用重建触发器的过程的
dbms_job
提交作业。这将是一个非常复杂的问题,当不可避免地出现问题时,进行故障排除将是一件痛苦的事情,但是如果您不愿意采用其他方法实现功能,那么您将不得不忍受这种复杂性。

不。您不能动态引用
:new
:old
伪记录中的列


最接近的方法是编写代码,通过查询数据字典并对伪记录中的列进行静态引用,动态生成整个触发器体。但是,每次在表中添加或删除列时都需要运行该代码。通常,这将作为正常发布管理的一部分进行。如果您说人们在不经过发布过程的情况下在此表中添加和删除列,那么您可以编写一个DDL触发器,该触发器通过调用重建触发器的过程的
dbms_job
提交作业。这将是一个不断变化的过程,当不可避免地出现问题时,进行故障排除将是一件痛苦的事情,但如果您不愿意采用其他实现功能的方法,那么您将不得不忍受这种复杂性。

在添加每一列后,能否通过模式DDL触发器重新生成触发器?然后可以从数据字典生成一次检查和插入。如果不可能,这就是我的“计划B”。是实施计划B的时候了,那么*8-)在添加每个列后,能否通过架构DDL触发器重新生成触发器?然后可以从数据字典生成一次检查和插入。如果不可能,这就是我的“计划B”。是时候实施计划B了,那么*8-)我可以使用EXECUTE IMMEDIATE直接在DDL触发器中运行触发器“创建或替换”吗?我意识到这可能不是一个理想的情况,但我们对这些环境没有太多的控制权,我不知道是否可以确定我们的用户是否有创建作业的权限,@reluctantdba-否。您不能在触发器中提交(或回滚)。所以不能从触发器发出DDL。此外,您需要在DDL完成后运行
create或replace触发器
,以便数据字典反映新列。请注意,除了拥有触发器的用户需要调用
dbms\u作业
dbms\u调度程序
)的权限外(由于提交作业提交,因此在此处无法工作),数据库还需要允许足够数量的后台作业运行,以确保您提交的作业实际运行。非常感谢您的帮助。非常感谢!我可以使用executeimmediate直接在DDL触发器中运行触发器“create或replace”吗?我意识到这可能不是一个理想的情况,但我们对这些环境没有太多的控制权,我不知道是否可以确定我们的用户是否有创建作业的权限,@reluctantdba-否。您不能在触发器中提交(或回滚)。所以不能从触发器发出DDL。此外,您需要在DDL完成后运行
create或replace触发器
,以便数据字典反映新列。请注意,除了拥有触发器的用户需要调用
dbms\u作业
dbms\u调度程序
)的权限外(由于提交作业提交,因此在此处无法工作),数据库还需要允许足够数量的后台作业运行,以确保您提交的作业实际运行。非常感谢您的帮助。非常感谢!