oracle - 按名称获取 Oracle PL/SQl 变量属性(PL/SQL 中的反射)

标签 oracle reflection plsql audit

我需要对更新行进行一些审核。

所以我有一个函数,它接收 some_table%ROWTYPE 类型的参数,其中包含要为该行保存的新值。

我还需要在历史表中保存一些有关更改的列值的信息。我正在考虑从 all_tab_columns 获取 some_table 的列名称,然后迭代这些列名称以比较新旧值并查看它是否已更改。问题是一旦我有了列名,我不知道如何访问 ROWTYPE 变量中的值。类似于 var.getProperty(columnName)。

我想这样做是为了避免有一堆 IF,每个字段一个,而且它也可以直接在表中添加新列。

而且我也不能使用触发器,因为上级说“没有触发器!”。 (如果这确实是唯一的办法,我可以尝试再次与他们讨论此事)。

最佳答案

也许值得找出为什么有“无触发器”规则。

有很多反对触发器的好论据 - 特别是关于将业务规则放入触发器 - 但日志记录通常被认为是使用触发器的一个很好的案例。

Oracle 的内置表版本控制(每次更新记录一行)也值得一看 - 这使历史记录的形状与当前表的形状保持一致。 它不会为您提供“更改内容”历史记录,但最好在查看历史记录时立即执行“更改内容”,而不是在每次更新时增加成本。

我发现做类似你想要的事情的唯一方法 - 动态访问 %ROWTYPE 的属性,是将一个变量放在包头上(因此它是公开可见的),然后执行动态 PL/SQL。您可以封装行变量,只要动态 pl/sql block 在每次检查之前包含本地副本即可。即,将其想象为立即执行的模板。

DECLARE
     lNew myTab%ROWTYPE;
     lOld myTab%ROWTYPE;
     lReturn PLS_INTEGER := 0;
BEGIN
    lNew := pStatefulPackage.NewRow;
    lOld := pStatefulPackage.OldRow;
    IF NVL(lNew.<variable>,'~') != NVL(lOld..<variable>,'~') THEN
        :lReturn := 1;
    END IF;
END;

解决无法在动态 SQL 中绑定(bind)记录变量或 bool 值这一事实会带来很多麻烦。

它还增加了每列的大量开销。

最后,我发现 ALL_TAB_COLUMNS 太慢,无法用于此类事情 - 您需要将元数据缓存在本地 pl/sql 内存中。

关于oracle - 按名称获取 Oracle PL/SQl 变量属性(PL/SQL 中的反射),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3707940/

相关文章:

oracle - 批量收集动态sql

java - Spring Data JDBC是否支持自定义类型转换器

sql - Access 和 ODBC/Oracle 都能理解的通用 SQL

C# EF 必需属性无法识别

mysql - 使用 SQL 为二进制系统插入新行

plsql - PL/SQL 错误 - 无效文件 ID

java - Oracle驱动在PreparedStatement中setFetchSize时出现OutOfMemoryError

c# - 为什么可以使用反射更改只读字段的值而不是 const 的值?

Java 反射。运行外部 jar 并引用它的类?

java - 将存储过程 PL/SQL 转换为 Java