Oracle PL/SQL : 트리거 열의 루프 동적으로 루프
-
16-09-2019 - |
문제
트리거 내부에는 테이블의 모든 열을 루프하고 새 값을 이전 값과 비교하려고합니다. 지금까지 내가 가지고있는 것은 다음과 같습니다.
CREATE OR REPLACE TRIGGER "JOSH".TEST#UPD BEFORE
UPDATE ON "JOSH"."TEST_TRIGGER_TABLE" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
declare
oldval varchar(2000);
newval varchar(2000);
begin
for row in (SELECT column_name from user_tab_columns where table_name='TEST_TRIGGER_TABLE') loop
execute immediate 'select :old.'||row.column_name||' from dual' into oldval;
execute immediate 'select :new.'||row.column_name||' from dual' into newval;
--Do something here with the old and new values
end loop;
end;
트리거가 컴파일되지만 트리거가 발생하면 다음과 같습니다.
ORA-01008 : 모든 변수가 바인딩되는 것은 아닙니다
첫 번째 실행에서 즉시 값을 기대하기 때문에 :old
. :old
그리고 :new
이미 트리거의 일부로 정의되어 있지만 즉시 실행하면 해당 변수를 볼 수 없습니다.
트리거의 열 값을 동적으로 반복 할 수있는 방법이 있습니까?
해결책
아니요, 당신은 참조 할 수 없습니다 : 오래된 것과 : 새로운 값은 동적으로. Shane이 제안한 바와 같이, 정적 트리거 코드를 생성하기 위해 코드를 작성할 수 있습니다. 또한 패키지 절차로 "여기에서 무언가를"만들 수 있도록 트리거가됩니다.
CREATE OR REPLACE TRIGGER JOSH.TEST#UPD BEFORE
UPDATE ON JOSH.TEST_TRIGGER_TABLE
begin
my_package.do_something_with (:old.col1, :new.col1);
my_package.do_something_with (:old.col2, :new.col2);
my_package.do_something_with (:old.col3, :new.col3);
-- etc.
end;
(그건 그렇고 무의미한 참조 절을 버릴 수 있습니다).
다른 팁
당신이하려는 일을 할 수 있는지 확실하지 않습니다. PL/SQL 코드 내부의 테이블 열을 명시 적으로 이름을 지정하고 싶지 않은 이유는 무엇입니까? 테이블 필드가 자주 바뀌는 경우 각 테이블의 PL/SQL 트리거를 동적으로 빌드하는 PL/SQL을 빌드 할 수 있습니다 (각각의 명시 적 필드 이름이 있음). 테이블이 변경 될 때마다 PL/SQL을 실행하여 새 트리거를 생성 할 수 있습니다.
본질적으로 테이블의 모든 변경 사항을 감사하기 위해 자신의 시스템을 구축하려고합니까? (예전의 기존 및 새로운 값으로 무엇을 할 수 있는지에 대한 내 가장 좋은 추측.) 그렇다면 Oracle의 자체 감사 기능을 살펴볼 수 있습니다.
MSSQL에서도 비슷한 문제가있었습니다.
내 해결책은 테이블 및 열 정보 (사전보기 또는 사용자 정의 저장소를 통해)를 통해 반복하는 저장된 절차를 작성하고 필요한 트리거를 생성하는 것이 었습니다. 데이터 모델이 변경된 경우에만 절차를 실행해야합니다.
장점은 각 업데이트에서 메타 모델을 통해 커서를 사용할 필요가 없으며 미리 트리거를 생성한다는 것입니다.