我们有一个应用程序可以创建一个随机生成名称的表。我想在这个桌子上创建一个触发器。由于我不知道tabe的名字,我想从all_table视图中获取它。我怎样才能实现这样的目标呢?
create or replace trigger t1
after insert or update on (select table_name from all_tables where owner = 'CustomAPP' and table_name like 'STAGE_%')
-- for each row
declare
-- local variables here
begin
end t1;
由于创建触发器之后的select子句而不是表名,上面的SQL显然会出错。请指教
答案 0 :(得分:2)
您需要制作整个CREATE TRIGGER
动态才能执行此操作。这样的事情应该有效。您可能希望使触发器名称取决于表的名称,假设可能有多个表,您对ALL_TABLES
的查询可能返回多行。你当然希望触发器做一些事情,而不是空洞的身体。
SQL> create table stg_12345( col1 number );
Table created.
SQL> begin
2 for x in (select *
3 from user_tables
4 where table_name like 'STG%')
5 loop
6 execute immediate
7 'create or replace trigger trg_foo ' ||
8 ' before insert on ' || x.table_name ||
9 ' for each row ' ||
10 'begin ' ||
11 ' null; ' ||
12 'end;';
13 end loop;
14 end;
15 /
PL/SQL procedure successfully completed.
SQL> select count(*) from user_triggers where trigger_name = 'TRG_FOO';
COUNT(*)
----------
1
当然,动态创建表的应用程序的想法让我害怕核心。如果您对此有任何控制权,我强烈建议您重新考虑该体系结构。
答案 1 :(得分:1)
解决方案1:
如果问题是“由于缺乏统计信息而导致性能不佳”,那么在系统或会话级别更改OPTIMIZER_DYNAMIC_SAMPLING
参数可能会有所帮助。请参阅Performance Tuning Guide以获得更全面的讨论,但我发现默认值为2(64个块)是不够的,特别是对于保持优化程序统计数据不可行的大数据集。
解决方案2:
如果您确实想在创建表后自动创建触发器,则需要为架构创建DDL触发器。下面的SQL演示了。
CREATE OR REPLACE TRIGGER MAKE_ME_A_TRIGGER
AFTER CREATE ON CUSTOM_APP_SCHEMA
AS
l_trigger_sql varchar2(4000);
BEGIN
if l_ora_obj_dict_type = 'TABLE'
then
l_trigger_sql := 'create or replace trigger ' || ora_dict_obj_name
' before insert on ' || ora_dict_obj_type||
' for each row ' ||
'begin ' ||
' null; ' ||
'end;'
execute immediate l_sql;
end if;
END;
/
答案 2 :(得分:0)
如果活动连接对数据库具有适当的权限,则可以使用EXECUTE IMMEDIATE
动态执行SQL,包括DDL脚本。使用PL / SQL通过字符串连接构建完整的DDL语句,然后可以动态执行它。
文档: http://docs.oracle.com/cd/B12037_01/appdev.101/b10807/13_elems017.htm
更多文档: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/dynamic.htm