我的任务涉及更新许多完全相同的查询但应用于多个不同表的触发器。有没有办法使用 FOR 或类似的语句来更新所有这些触发器?实际上我需要做的是修改所有这些触发器的 WHEN 子句。
问问题
540 次
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 回答