【问题标题】:Oracle Triggers not showing in DBA_SOURCEOracle 触发器未显示在 DBA_SOURCE 中
【发布时间】:2012-01-09 21:36:46
【问题描述】:

在我们的应用程序中,只有大约 25% 的数据库触发器出现在 DBA_SOURCE 中。我知道如果我进行实际修改(例如添加和删除空格)然后重新编译触发器,我可以强制其他人出现,但我有大约 400 个触发器要修改(这是一个相当大的应用程序)。只是用alter trigger <triggername> compile; 重新编译触发器并没有完成任何事情。

如果触发器不在 DBA_SOURCE 中,我们就无法对触发器代码进行文本搜索。

有没有更简单的方法来完成这个?有没有办法防止以后出现这个问题?

我们使用的是 Oracle 10.2.0.5.0。

【问题讨论】:

  • 也许我应该补充一点,这是在我们的开发环境中,所以无论我做什么都不会搞砸生产。
  • 触发器是在源代码管理中,还是只是在数据库中?如果有源代码控制(它们应该在哪里),那么您应该能够对存储触发器的文件进行文本搜索。我承认搜索数据库通常更容易,但关键是数据库不应该成为代码的“主副本”,即使在 dev 上也是如此——多年前,当错误的 dev 数据库被错误地删除时,我学到了这个教训!
  • 不幸的是,它们不在任何源代码管理中,只是在数据库中。希望我能以其他方式说服团队的其他成员,但事实就是如此(我在这里已经 7 年了,我仍然是这里的新手)。也许我可以以此为动力!
  • 不幸的是,我看到一个又一个项目,你的情况一遍又一遍地重复!至少你似乎接受它并不理想。受此启发,我一直致力于开发一种构建工具,以帮助团队更好地管理数据库中的代码。有兴趣的可以看看dbgeni.com关于触发器,我一直在all_source中找到触发器源,只要我去寻找它。

标签: oracle triggers


【解决方案1】:

谁拥有触发器?

当然,你试过了

选择所有者,对象名称 来自 all_objects 其中 object_type = 'TRIGGER' 和所有者在 ('schema1','schema2')

【讨论】:

  • 触发器都在同一个模式中,它也有所有的表、存储过程/函数/包等。我可以直接登录到那个模式,所以这不是问题。如果解决方案需要 DBA 权限,我们的 DBA 就在我隔壁的隔间。
【解决方案2】:

相信你可以在 all_triggers 中找到源代码。不幸的是,数据在一个 LONG 变量中(Oracle 的例子是我说的,而不是我做的)。所以,最简单的方法是创建一个临时表来使用,用转换为 CLOB 的数据填充它,然后搜索:

CREATE TABLE tr (trigger_name VARCHAR2(32), trigger_body CLOB);

INSERT INTO tr 
 (SELECT trigger_name, TO_LOB(trigger_body)
    FROM all_triggers
   WHERE owner = 'xxx');

SELECT trigger_name
  FROM tr
 WHERE trigger_body LIKE '%something%';

我不确定为什么 dba_source 视图只为触发器填充稀疏。我的 10.2.0.4 数据库也是这样。

编辑:

这是一个简短的脚本,您可以使用它来重新创建所有触发器,此时它们应该都在 dba_source 中:

CREATE TABLE temp_sql (sql1 CLOB, sql2 CLOB);

INSERT INTO temp_sql (sql1, sql2) (
SELECT 'CREATE OR REPLACE TRIGGER '||
       DESCRIPTION||' '||CASE WHEN when_clause IS NULL THEN NULL ELSE 'WHEN('||when_clause||')' END sql1,
       to_lob(trigger_body) sql2
  FROM all_triggers
 WHERE table_owner = 'theowner');

DECLARE
  v_sql VARCHAR2(32760); 

BEGIN
  FOR R IN (SELECT sql1||' '||sql2 S FROM temp_sql) LOOP
    v_sql := R.s;
    EXECUTE IMMEDIATE v_sql;
  END LOOP;
END;
/

【讨论】:

  • 这作为一种解决方法是可以的,但是整个开发团队中的每个人都必须记住在处理它们时向该表添加新的或修改的触发器。
  • 或者您可以在需要搜索数据时简单地重新创建数据。在事物的方案中,400 个触发器并不是那么多数据。事实上,把它做成一个全局临时表,每次需要搜索的时候都构建它。
  • 您还可以查询 dba_objects 以确定对触发器执行最后一次 DDL 的时间,以了解您是否需要更新它。
【解决方案3】:

我们遇到了同样的问题。这是旧版本 Oracle 的迁移问题。

在早期版本(8?、9i?)中,触发器未包含在 DBA_SOURCE 中,并且在迁移到较新版本时未添加到 DBA_SOURCE。重新编译并没有将它们放入 DBA_SOURCE。但如果您删除并重新创建触发器,它们将包含在 DBA_SOURCE 中。

所以我猜你有一些旧的触发器,并且已经将数据库迁移到新版本。

【讨论】:

  • 吉姆,我想你可能一针见血。数据库已经存在10多年了,自从我来到这里以来,它已经从9i升级了。我不知道它最初是什么版本。不知道升级到 11g 能不能解决这个问题?我们计划在明年某个时候进行升级(我想是明年初)。
  • 在我们迁移到 11g 后我从未检查过,主要是因为我认为我们已经重新加载了所有触发器。而且我无权执行诸如“select * from dba_triggers t where not exists (select 1 from dba_source s where S.TYPE = 'TRIGGER' and s.name = t.trigger_name);”之类的权利。对不起。
  • 谢谢,吉姆。我接受了你的回答,不是因为你直接回答了我的问题,而是因为你解释了问题。也没有其他人回答这个问题。
猜你喜欢
  • 2013-03-26
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多