在过程内的动态添加表上创建触发器

时间:2017-04-23 21:41:17

标签: java database stored-procedures plsql triggers

我正在从java创建动态表。我想要的是我想在每个添加的新表上创建一个触发器,它只使用序列来填充每个表中常见的主键(serial_no)。如何实现这个???

编辑: 我试过这段代码,但是我收到一条消息“用编译错误创建的程序”

create or replace procedure "TRIGGER_CALL" (trigger_name IN VARCHAR2, table_name IN VARCHAR2, sno IN NUMBER) as begin CREATE SEQUENCE abc MINVALUE 1 MAXVALUE 10000 INCREMENT BY 1 START WITH 141 CACHE 20 NOORDER NOCYCLE; CREATE OR REPLACE TRIGGER trigger_name before insert on table_name for each row begin select s_no.nextval into :new.sno from dual; end; end;

EDIT2: 我的代码

CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name   IN VARCHAR2) 
AUTHID CURRENT_USER                          
AS 
  l_sql VARCHAR2(4000);
  l_dummy NUMBER;
  l_trigger_name VARCHAR2(30);
  l_seq_name VARCHAR2(30);
BEGIN

  --SELECT '1'
    --INTO l_dummy
    --FROM all_tables
  -- WHERE table_name = UPPER(p_table_name);

  l_trigger_name := p_table_name || '_trg'; 
  l_seq_name := p_table_name || 's_no';
EXECUTE IMMEDIATE 'CREATE SEQUENCE l_seq_name start with 1 increment by 1 ';
  l_sql :=
    'CREATE OR replace TRIGGER ' || l_trigger_name ||
    '  BEFORE INSERT ON ' || p_table_name ||
    '  FOR EACH ROW 
     BEGIN 
       SELECT l_seq_name.NEXTVAL 
       INTO   :new.sno 
       FROM   dual;
     END;';

  EXECUTE IMMEDIATE l_sql;
END; 
/

1 个答案:

答案 0 :(得分:1)

请检查以下代码:

CREATE SEQUENCE my_sequence;
/

CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name   IN VARCHAR2) 
AUTHID CURRENT_USER                          
AS 
  l_sql VARCHAR2(4000);
  l_dummy NUMBER;
  l_trigger_name VARCHAR2(30);
BEGIN
  -- Validate if a p_table_name is a valid object name
  -- If you have access you can also use DBMS_ASSERT.SQL_OBJECT_NAME procedure
  SELECT '1'
    INTO l_dummy
    FROM all_tables
   WHERE table_name = UPPER(p_table_name);

  l_trigger_name := p_table_name || '_trg'; 

  l_sql :=
    'CREATE OR replace TRIGGER ' || l_trigger_name ||
    '  BEFORE INSERT ON ' || p_table_name ||
    '  FOR EACH ROW 
     BEGIN 
       SELECT my_sequence.NEXTVAL 
       INTO   :new.sno 
       FROM   dual;
     END;';

  EXECUTE IMMEDIATE l_sql;
END; 
/

CREATE TABLE my_test(sno NUMBER);
/

BEGIN
  trigger_call('my_test');
END;
/

重要说明:

  1. 使用AUTHID CURRENT_USER消除了"不足的权限"问题。有关参考,请参阅:Execute Immediate within a stored procedure keeps giving insufficient priviliges error

  2. 因为动态sql只是连接输入参数,所以需要对其进行验证以防止SQL注入。另请参阅DBMS_ASSERT

  3. 由于第2点,我使用表名来构建触发器名称。