2011-11-30 78 views
4

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

没有触发器在DBA_SOURCE中,我们不能在触发器代码上进行文本搜索。

有没有一些简单的方法来完成这个?有什么方法可以防止未来的问题?

我们在Oracle 10.2.0.5.0上。

+0

也许我应该补充说这是在我们的开发环境中,所以不管我做什么都不会搞乱生产。 – AndyDan

+1

源代码管理中的触发器,还是仅仅在数据库中?如果在源代码控制中(它们应该在那里),那么你应该能够对存储触发器的文件进行文本搜索。我承认搜索数据库通常更容易,但关键是数据库不应该成为代码的“主副本”,即使是开发者 - 我也从多年前的错误教训中学到了错误的开发数据库时的难题! –

+0

不幸的是,它们不在任何源代码控制中,只是在数据库中。希望我能说服团队其他人,否则就是这样(我在这里已经有7年了,我仍然是这里的新手)。也许我可以用它来推动这一点! – AndyDan

回答

2

我们有同样的问题。这是来自旧版本Oracle的迁移问题。

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

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

+0

我想你可能会用这个钉在头上,吉姆。这个数据库已经存在了10多年,自从我来到这里以来,它已经从9i升级到了。我不知道它原来是什么版本。你知道升级到11g是否解决了这个问题?我们计划在明年某个时候进行升级(我认为明年初)。 – AndyDan

+0

我们在移动到11g后从未检查过,主要是因为我认为我们已经重新加载了所有触发器。我没有权利做类似“select * from dba_triggers t where where not exists(从dba_source s中选择1,其中S.TYPE ='TRIGGER'和s.name = t.trigger_name);”抱歉。 –

+0

谢谢,吉姆。我接受了你的答案,不是因为你直接回答了我的问题,而是因为你解释了这个问题。无人也回答了这个问题。 – AndyDan

0

谁拥有触发器?

,当然,你试过

选择所有者,从ALL_OBJECTS 其中OBJECT_TYPE =在( 'schema1', 'SCHEMA2')

+0

触发器都在同一个模式中,它也包含所有表,存储过程/函数/包等。我可以直接登录到该模式,所以这不是问题。如果解决方案需要DBA权限,我们的DBA位于下一排隔间。 – AndyDan

3

'TRIGGER' 和老板,我相信你能OBJECT_NAME 在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; 
/
+0

这可以作为一种解决方法,但是随后整个开发团队中的每个人都必须记住,无论何时他们使用新的或修改的触发器,都可以在该表中添加新的或修改的触发器。 – AndyDan

+0

或者您可以在需要搜索时简单地重新创建数据。在事物的计划中400触发器并不是那么多的数据。实际上,使其成为全球临时表,并在您每次需要搜索时进行构建。 – DCookie

+0

您还可以查询dba_objects以确定何时在触发器上执行最后一个DDL,以确定是否需要更新它。 – DCookie