【发布时间】:2015-08-21 00:43:16
【问题描述】:
我在 Oracle 中有一个存储过程,它通过构建 SQL 代码并使用 Oracle 的 PL/SQL EXECUTE 命令执行它来为我的所有表动态创建触发器(因为它们触发相同的存储过程)(尽管我使用的是 SQL Commander用于检测)。如何在触发器中正确创建 if 语句?下面是我的代码,它在 IF 语句开始的那一行出现语法错误。
CREATE OR REPLACE TRIGGER "DATABASE"."TABLE_TRIGGER"
AFTER INSERT OR DELETE OR UPDATE ON TABLE
FOR EACH ROW
DECLARE
v_op VARCHAR2(20);
BEGIN
IF INSERTING THEN
v_op := 'INSERT';
ELSIF UPDATING THEN
v_op := 'UPDATE';
ELSE
v_op := 'DELETE';
END IF;
PKG.STORED_PROC(v_op, ' - MY_COLUMN: ' || :NEW.MY_COLUMN || '', 'MY_TABLE');
END;
这是我用来生成 SQL 代码的代码示例。
PROCEDURE CREATE_TRIGGERS(
IN_TABLE_OMIT IN VARCHAR2, -- IN_TABLE_OMIT is a list of tables to not create a trigger on, as CSV
OUT_RESULT OUT VARCHAR2)
AS
v_table_results SYS_REFCURSOR;
v_column_results SYS_REFCURSOR;
v_template_head VARCHAR2(512);
v_template_body VARCHAR2(512);
v_template_operation VARCHAR(512);
v_template_column VARCHAR2(128);
v_template_data VARCHAR2(1024);
v_template_foot VARCHAR2(512);
v_result VARCHAR2(1024);
BEGIN
-- Create a template for each trigger
v_template_head := 'CREATE OR REPLACE TRIGGER "MY_DB"."MY_TABLE_TRIGGER"' || chr(10);
v_template_head := v_template_head || 'AFTER INSERT OR DELETE OR UPDATE ON MY_TABLE' || chr(10);
v_template_head := v_template_head || 'FOR EACH ROW' || chr(10) || 'DECLARE' || chr(10) || 'v_op VARCHAR2(20);' || chr(10) || 'BEGIN' || chr(10) || chr(10);
v_template_operation := 'IF INSERTING THEN v_op := ''INSERT''; ELSIF UPDATING THEN v_op := ''UPDATE''; ELSE v_op := ''DELETE''; END IF;' || chr(10);
v_template_body := 'MY_DB.STORED_PROC(' || chr(10) || 'v_op,' || chr(10);
v_template_column := ''' - MY_COLUMN: '' || :NEW.MY_COLUMN || ';
v_template_foot := '''MY_TABLE'');' || chr(10) || chr(10) || 'END;';
-- Insert double quotes into template
-- Loop through each table
FOR LOOP_TABLE IN (SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME) LOOP
IF INSTR(IN_TABLE_OMIT, LOOP_TABLE.TABLE_NAME) != 0 OR INSTR('AUDIT_TABLE', LOOP_TABLE.TABLE_NAME) != 0 THEN
FOR LOOP_COLUMN IN (SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = LOOP_TABLE.TABLE_NAME) LOOP
v_template_data := v_template_data || REPLACE(v_template_column, 'MY_COLUMN', LOOP_COLUMN.COLUMN_NAME);
END LOOP;
v_template_head := REPLACE(v_template_head, 'MY_TABLE', LOOP_TABLE.TABLE_NAME);
v_template_data := v_template_data || ''''',' || chr(10);
v_template_foot := REPLACE(v_template_foot, 'MY_TABLE', LOOP_TABLE.TABLE_NAME);
v_result := v_template_head || v_template_operation || v_template_body || v_template_data || v_template_foot;
v_template_data := '';
OUT_RESULT := chr(10) || v_result;
ELSE
dbms_output.put_line('Searched for ' || LOOP_TABLE.TABLE_NAME || ' in ' || IN_TABLE_OMIT);
END IF;
END LOOP;
END;
【问题讨论】:
-
ELSEIF应该是ELSIF。 -
如果您将 IF 块分解为多行,则错误会更容易诊断!
-
你需要orale还是sql server的解决方案??
-
看起来您正在重现 Oracle 中现有的审计功能