Могу ли я скопировать: OLD и: NEW псевдозаписи в / в хранимую процедуру Oracle? - PullRequest
6 голосов
/ 25 февраля 2010

У меня есть триггер AFTER INSERT OR UPDATE OR DELETE, который я пишу для хранения каждой редакции записи, которая происходит в определенной таблице, путем копирования значений INSERT и UPDATE :NEW в зеркальную таблицу и для DELETE значения :OLD.

Я мог бы значительно больше загромождать свой код, условно передавая либо запись :NEW, либо :OLD в процедуру, которая затем выполняла бы вставку в мою таблицу истории. К сожалению, я не могу найти способ передать всю запись :OLD или :NEW.

Я что-то упустил или нет способа избежать перечисления каждого столбца :NEW и :OLD при вызове процедуры вставки?

Я хочу сделать следующее:

DECLARE
  PROCEDURE LOCAL_INSERT(historyRecord in ACCT.ACCOUNTS%ROWTYPE) IS
  BEGIN
    INSERT INTO ACCT.ACCOUNTS_HISTORY (ID, NAME, DESCRIPTION, DATE) VALUES (historyRecord.ID, historyRecord.NAME, historyRecord.DESCRIPTION, SYSDATE);
  END;
BEGIN
  IF INSERTING OR UPDATING THEN
    LOCAL_INSERT(:NEW);
  ELSE --DELETING
    LOCAL_INSERT(:OLD);
  END IF;
END;

Но я застрял, делая это:

DECLARE
  PROCEDURE LOCAL_INSERT(id in ACCT.ACCOUNTS.ID%TYPE,
                         name in ACCT.ACCOUNTS.NAME%TYPE,
                         description in ACCT.ACCOUNTS.DESCRIPTION%TYPE) IS
  BEGIN
    INSERT INTO ACCT.ACCOUNTS_HISTORY (ID, NAME, DESCRIPTION, DATE) VALUES (id, name, description, SYSDATE);
  END;
BEGIN
  IF INSERTING OR UPDATING THEN
    LOCAL_INSERT(:NEW.ID, :NEW.NAME, :NEW.DESCRIPTION);
  ELSE --DELETING
    LOCAL_INSERT(:OLD.ID, :OLD.NAME, :OLD.DESCRIPTION);
  END IF;
END;

Хорошо, это не выглядит большой разницей, но это всего лишь пример с 3 столбцами, а не с десятками.

Ответы [ 4 ]

3 голосов
/ 26 февраля 2010

Это не так. Вы должны сделать это сами путем перечисления.

Причины, по которым он не может / не работает автоматически, включают:

  • :old и :new являются соглашениями по умолчанию; Вы можете назвать ссылки :old и :new как угодно, используя предложение REFERENCING оператора CREATE TRIGGER.

  • вам потребуется публичное объявление типа (через CREATE TYPE или через объявление пакета), чтобы иметь возможность использовать его в качестве аргумента для другого фрагмента кода.

  • триггерный код - это интерпретированный код, а не скомпилированный код.

1 голос
/ 25 февраля 2010

Не думаю, что это возможно. Документация ничего подобного не упоминает.

Это, безусловно, будет стоить производительности, но вы можете попытаться определить свой триггер AFTER INSERT и еще один BEFORE UPDATE OR DELETE, и в триггере сделать что-то вроде:

SELECT *
INTO rowtype_variable
FROM accounts
WHERE accounts.id = :NEW.id; -- :OLD.id for UPDATE and DELETE

и затем вызовите вашу процедуру с этим rowtype_variable.

0 голосов
/ 23 сентября 2015

Если вы используете ПОСЛЕ триггера, вы можете использовать rowid в качестве параметра для вызова процедуры

insert into t_hist
select * from t where rowid = r;

Если вы используете ДО триггер, вы получите ORA-04091 таблицу мутаций, НО ваше решение может быть (http://www.dba -oracle.com / t_avoiding_mutating_table_error.htm ):

  • Не использовать триггеры. Лучший способ избежать ошибки таблицы мутаций - не использовать триггеры. В то время как объектно-ориентированный Oracle предоставляет «методы», связанные с таблицами, большинство опытных разработчиков PL / SQL избегают триггеров, если в этом нет крайней необходимости.
  • Используйте триггер «после» или «вместо» - если вам необходимо использовать триггер, лучше всего избежать ошибки таблицы мутаций, используя триггер «после», чтобы избежать проблем с валютой, связанных с таблицей мутаций. Например, при использовании триггера «: после обновления в xxx» исходное обновление завершено, и таблица не будет изменяться.
  • Переработайте синтаксис триггера. Доктор Холл сделал несколько замечательных замечаний по изменению ошибок таблиц и предлагает другие способы избежать изменения таблиц с помощью комбинации триггеров уровня строки и уровня оператора.
  • Использовать автономные транзакции - вы можете избежать ошибки таблицы мутаций, пометив триггер как автономную транзакцию, сделав его независимым от таблицы, которая вызывает процедуру.
0 голосов
/ 22 сентября 2011

Использовать SQL для генерации SQL;

select ' row_field.'||COLUMN_NAME||' := :new.'||COLUMN_NAME||';'  from 
    ALL_TAB_COLUMNS cols 
where 
    cols.TABLE_NAME = 'yourTableName'
order by cols.column_name.

Затем скопируйте и вставьте вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...