Создайте триггер с хранимыми процедурами, сделав динамическим в столбце триггера - PullRequest
0 голосов
/ 31 января 2019

Я создаю новый аудит триггера с использованием процедуры сохранения, поэтому требуется гибкий столбец в аудите триггера

im с использованием Oracle 12 C ..

CREATE OR REPLACE PROCEDURE DBADMIN.TEST3 (OUTPUT          OUT SYS_REFCURSOR,
                                          TABLE_NAME   IN     VARCHAR2)
IS
    N   NUMBER;
BEGIN
    N := 0;

    EXECUTE IMMEDIATE '

CREATE OR REPLACE TRIGGER DBADMIN.TA_EMPLOYEES3
    AFTER INSERT OR DELETE OR UPDATE
    ON DBADMIN.EMPLOYEES
    FOR EACH ROW
DECLARE
    SID   VARCHAR2 (30);
BEGIN
    SELECT SYS_CONTEXT ('' USERENV       '', ''    IP_ADDRESS          '') INTO IP FROM DUAL;

    SELECT SEQ#
      INTO SID1
      FROM v$session
     WHERE audsid = (SELECT USERENV ('' SESSIONID '') FROM DUAL);

    IF INSERTING
    THEN
        INSERT INTO DBADMIN.DBLOG_MONITORING_DETAIL2 (SID,
                                                          COLUMNS,
                                                          OLDVALUE,
                                                          NEWVALUE)
                 VALUES (SID1,
                         i.COLUMN_NAME,
                        'for row in (SELECT column_name from user_tab_columns where table_name=''EMPLOYEES'' loop  
                        execute immediate '':old.row.column_name '';
                      end loop;
/

32 26 PLS-00103:Обнаружил символ "ЗА"

Я думаю, что я плохая логика в моем сценарии .. может дать мне лучшую логику или исправить мой сценарий лучше ??.

1 Ответ

0 голосов
/ 31 января 2019

В Oracle вы действительно редко используете динамический SQL для создания объектов базы данных.Люди иногда злоупотребляют той функциональностью, которая, по моему мнению, является тем, что вы пытаетесь сделать.Тот факт, что вы можете сделать это, не означает, что вы должны сделать это, например, вы можете ткнуть глаз карандашом, но вы не должны этого делать.

Практическое правило с динамическим SQL:

  • забудьте о EXECUTE IMMEDIATE
  • Создайте локальную переменную (большую VARCHAR2 или CLOB, в зависимости от того, что вы
  • составляет оператор (CREATE TRIGGER в вашем случае) и
  • сохраняет его в этой переменной
  • отображает его на экране, используя DBMS_OUTPUT.PUT_LINE
  • скопируйте / вставьте его и запустите как отдельный оператор
    • , если это удастся, вы проделали хорошую работу, поэтому теперь вы можете использовать его в EXECUTE IMMEDIATE
    • , если не получитсявам нужно будет немного сложнее, отладить его, исправить ошибки и повторить цикл

По состоянию на полученную ошибку: this:

for row in (SELECT column_name from user_tab_columns where table_name=''EMPLOYEES'' loop  
  execute immediate '':old.row.column_name '';
end loop;

недопустимо в качестве цели INSERT INTO;Вы не можете смешивать SQL и PL / SQL таким образом.Он не будет работать вообще, независимо от того, какой динамический SQL вы используете.Кроме того, очевидно, что это неправильно (отсутствует закрывающая скобка, что именно вы выполняете немедленно ? old_row.column_name? Как бы вы выполнили имя столбца?

По моему мнению (еще раз), вы не должны делать это таким образом. Если вы хотите создать триггер, сделайте это - но не динамически .

...