在过程中动态添加的表上创建触发器
Posted
技术标签:
【中文标题】在过程中动态添加的表上创建触发器【英文标题】:creating a trigger on a dynamically added table inside a procedure 【发布时间】:2017-04-23 21:41:16 【问题描述】:我正在从 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;
编辑2: 我的代码
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;
/
【问题讨论】:
您的 Oracle 版本是多少?这在 12c 中更容易。 @WilliamRobertson 我有 Oracle 10g 。有什么建议吗?? 你必须做很长的路,然后 - 为你创建的每个表动态定义一个序列和一个触发器。 @WilliamRobertson 你能检查我的代码吗? 【参考方案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;
/
重要提示:
使用 AUTHID CURRENT_USER 消除了“权限不足”的问题。参考见:Execute Immediate within a stored procedure keeps giving insufficient priviliges error
因为动态 sql 只是连接输入参数,因此需要对其进行验证以防止 SQL 注入。另见DBMS_ASSERT。
由于第 2 点。我使用表名来构建触发器名称。
【讨论】:
我收到此错误消息“oracle pls-00103 在期望以下之一时遇到符号创建” 要在动态 sql 中使用l_seq_name
,您必须将其与字符串连接,您不能像发布的那样使用它(检查我如何使用 l_trigger_name
变量)。除了代码运行正常。我没有收到 PLS-00103 错误。你怎么称呼这个过程?
我在 sql 命令行中运行命令“show error procedure trigger_call”
我已经使用 SQLDeveloper 创建了该过程,它运行良好(记住我之前的评论)。您必须提供更多详细信息,否则我无法猜测您的问题是什么。也许您可以显示包含过程创建和错误详细信息的完整 sql 命令行。
您的问题解决了吗?如果是这样,请发布您的答案或接受此答案以供进一步参考。以上是关于在过程中动态添加的表上创建触发器的主要内容,如果未能解决你的问题,请参考以下文章