2

我的任务涉及更新许多完全相同的查询但应用于多个不同表的触发器。有没有办法使用 FOR 或类似的语句来更新所有这些触发器?实际上我需要做的是修改所有这些触发器的 WHEN 子句。

4

2 回答 2

3

您可以为此使用 dbms_metadat。

例如:

declare
  type arr_tab is table of varchar2(30);
  v_arr arr_tab;
  v_trig  clob;
begin
  dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM, 
                    'SQLTERMINATOR', FALSE );

  v_arr := arr_tab('TEST_TRIG', 'TEST2_TRIG'); -- change these triggers.
  for idx in 1..v_arr.count
  loop
    v_trig := dbms_metadata.get_ddl('TRIGGER',v_arr(idx), user);
    execute immediate regexp_replace(regexp_replace(v_trig, 'ALTER TRIGGER.*', ''), 'WHEN ([^\)]*\))', 'WHEN (1=1)', 1, 1, 'mi');
  end loop;
end;
/

'WHEN ([^\)]*\))', 'WHEN (1=1)'部分将WHEN子句替换为 (在我的情况下) WHEN (1=1)

于 2013-02-01T22:30:07.887 回答
0

您可以使用 dba_triggers 将触发器的文本提取到 CREATE 或 replace 语句中。但是由于某些列是 LONG 数据类型,您将无法将它们提取为 VARCHAR2。这可以通过使用在 oracle 网站某处丢失的 Tom Kytes 包来解决。我包括我自己的版本,您可能需要对其进行修改以满足您的需求。

运行选择,插入您的 when 子句,然后运行创建或替换语句。

由于 trigger_body 是长数据类型,这将不起作用

select 'CREATE OR REPLACE TRIGGER '|| description
||trigger_body
from dba_triggers
where owner = 'Your schema'

但如果您的触发器不超过 4000 个字符,这应该可以工作

select 'CREATE OR REPLACE TRIGGER '|| description
    || ADMIN.LONG_HELP.SUBSTR_OF('select trigger_body from dba_triggers where    trigger_name = :0',
1,4000,'0',dt.trigger_name)
from dba_triggers dt
where owner = 'YourSchema';


CREATE OR REPLACE PACKAGE ADMIN.LONG_HELP
   /******************************************************************************
      NAME:       LONG_HELP
      PURPOSE:    Read fields of type long.  (commonly found in data dictionary)

      REVISIONS:
      Ver        Date        Author           Description
      ---------  ----------  ---------------  ------------------------------------
      1.0        10/27/2011             1. Created this package. based on Tom Kyte's column here
      http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:839298816582
      note  that it only retrieves the first 4000 characters of any LONG column
      USAGE in a WHERE
      INSTR(
      ADMIN.LONG_HELP.SUBSTR_OF('SELECT text from all_views where view_name =:o ',
      1,4000,'o',m2.obj_name),m1.FK_ID) > 0

   ******************************************************************************/

   --AUTHID CURRENT_USER 
   --removed to get around ORA-29470: Effective userid or roles are not the same as when cursor was parsed
   --restrict usage to admin schema for Oracle 11g

AS
   FUNCTION substr_of (p_query   IN VARCHAR2,
                       p_from    IN NUMBER,
                       p_for     IN NUMBER,
                       p_name1   IN VARCHAR2 DEFAULT NULL ,
                       p_bind1   IN VARCHAR2 DEFAULT NULL ,
                       p_name2   IN VARCHAR2 DEFAULT NULL ,
                       p_bind2   IN VARCHAR2 DEFAULT NULL ,
                       p_name3   IN VARCHAR2 DEFAULT NULL ,
                       p_bind3   IN VARCHAR2 DEFAULT NULL ,
                       p_name4   IN VARCHAR2 DEFAULT NULL ,
                       p_bind4   IN VARCHAR2 DEFAULT NULL )
      RETURN VARCHAR2;
END LONG_HELP;
/
CREATE OR REPLACE PACKAGE BODY ADMIN.LONG_HELP
AS
   g_cursor   NUMBER := DBMS_SQL.open_cursor;
   g_query    VARCHAR2 (32765);


   PROCEDURE bind_variable (p_name IN VARCHAR2, p_value IN VARCHAR2)
   IS
   BEGIN
      IF (p_name IS NOT NULL)
      THEN
         DBMS_SQL.bind_variable (g_cursor, p_name, p_value);
      END IF;
   END BIND_VARIABLE;



   FUNCTION substr_of (p_query   IN VARCHAR2,
                       p_from    IN NUMBER,
                       p_for     IN NUMBER,
                       p_name1   IN VARCHAR2 DEFAULT NULL ,
                       p_bind1   IN VARCHAR2 DEFAULT NULL ,
                       p_name2   IN VARCHAR2 DEFAULT NULL ,
                       p_bind2   IN VARCHAR2 DEFAULT NULL ,
                       p_name3   IN VARCHAR2 DEFAULT NULL ,
                       p_bind3   IN VARCHAR2 DEFAULT NULL ,
                       p_name4   IN VARCHAR2 DEFAULT NULL ,
                       p_bind4   IN VARCHAR2 DEFAULT NULL )
      RETURN VARCHAR2
   AS
   /******************************************************************************
   NAME:       LONG_HELP.SUBSTR_OF
   PURPOSE:    CONVERT long data fields into VARCHAR2
   WHOSE DATA IS CHANGED: none
   WHAT USES THIS:
   WHERE ARE THE RESOURCES NEEDED:

******************************************************************************/
      l_buffer       VARCHAR2 (4000);
      l_buffer_len   NUMBER;
   BEGIN
      IF (NVL (p_from, 0) <= 0)
      THEN
         raise_application_error (-20002,
                                  'From must be >= 1 (positive numbers)');
      END IF;

      IF (NVL (p_for, 0) NOT BETWEEN 1 AND 4000)
      THEN
         raise_application_error (-20003, 'For must be between 1 and 4000');
      END IF;


      IF (p_query <> g_query OR g_query IS NULL)
      THEN
         IF (UPPER (TRIM (NVL (p_query, 'x'))) NOT LIKE 'SELECT%')
         THEN
            raise_application_error (-20001, 'This must be a select only');
         END IF;

         DBMS_SQL.parse (g_cursor, p_query, DBMS_SQL.native);
         g_query := p_query;
      END IF;

      bind_variable (p_name1, p_bind1);
      bind_variable (p_name2, p_bind2);
      bind_variable (p_name3, p_bind3);
      bind_variable (p_name4, p_bind4);

      DBMS_SQL.define_column_long (g_cursor, 1);

      IF (DBMS_SQL.execute_and_fetch (g_cursor) > 0)
      THEN
         DBMS_SQL.column_value_long (g_cursor,
                                     1,
                                     p_for,
                                     p_from - 1,
                                     l_buffer,
                                     l_buffer_len);
      END IF;

      RETURN l_buffer;
   END substr_of;
END LONG_HELP;
/
于 2013-02-01T19:30:39.100 回答