Получение Tablename из all_tables для триггера - PullRequest
1 голос
/ 11 января 2012

У нас есть приложение, которое создает таблицу со случайно сгенерированным именем. Я хотел бы создать триггер для этой таблицы. Так как я не знаю имя табе, я хотел бы получить его из представления 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;

Приведенный выше SQL явно дает ошибку из-за предложения select после триггера create вместо имени таблицы. Пожалуйста, сообщите

Ответы [ 3 ]

2 голосов
/ 12 января 2012

Для этого вам нужно сделать весь 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 голос
/ 13 января 2012

Решение 1:

Если проблема заключается в «низкой производительности из-за отсутствия статистики», возможно, может помочь изменение параметра OPTIMIZER_DYNAMIC_SAMPLING на уровне системы или сеанса.См. Руководство по настройке производительности для более подробного обсуждения, но я обнаружил, что по умолчанию 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;
/
0 голосов
/ 11 января 2012

Вы можете использовать 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

...