在表上创建复杂触发器
Posted
技术标签:
【中文标题】在表上创建复杂触发器【英文标题】:create complex trigger on table 【发布时间】:2012-07-18 20:34:16 【问题描述】:我有一个表格参与者,其结构如下所示:
Pid number
name varchar2(20)
version number
每当我在 participants
表中插入任何记录时,版本 =1
都会被填充。
例如,如果我插入了 pid=1 ,name='Gaurav' 然后用 version =1
记录会被填充到 participants table
中。
现在我的issue
与update
在participants
表上,
-
假设我正在为参与者表中的 pid=1 更新 name ='Niharika',然后需要在同一个表上创建一个 pid=1、name='Niharika' 和版本 =2 的新记录。
我再次在参与者表中更新 name='Rohan' for pid='1' 需要创建一个 pid=1、name='Rohan' 和 version=3 的新记录。
我怎样才能做到这一点,显然我需要为将要更新的 pid 获取 max(version)+1。
我可以使用视图来实现这一点,并使用而不是触发器插入视图,但我对我的解决方案不满意。
我还创建了复合触发器,即使这对我不起作用,因为在触发器内部我需要对该表使用插入语句,这会给我递归错误
【问题讨论】:
【参考方案1】:你真的应该有两张桌子。使用您描述为“日志记录”表的结构制作一个。它将保留所有记录的历史记录。有另一个被认为是“当前”的表,它是相同的,但没有 version
列。然后,当“当前”表的记录发生插入/更新时,在日志表中有一个机制(例如触发器)SELECT FOR UPDATE
max(version),添加一个,然后插入到日志表中。这样,您就不会遇到变异表错误或任何类似的奇怪问题。这种方式有一些序列化,但它最接近你想要做的。
【讨论】:
【参考方案2】:通常不推荐,但无论如何您都可以这样做,而无需其他额外的日志记录表-
CREATE or REPLACE
TRIGGER part_upd
AFTER UPDATE of name
ON participants
FOR EACH ROW
DECLARE
retval BOOLEAN;
BEGIN
retval := insert_row(:old.pid,:new.name);
END part_upd;
函数-
CREATE or REPLACE
FUNCTION insert_row (pid1 number, name1 varchar2)
RETURN boolean
IS
PRAGMA autonomous_transaction;
BEGIN
INSERT INTO participants
SELECT pid1, name1, max(vers)+1
FROM participants
WHERE pid = pid1;
COMMIT;
RETURN true;
END;
您必须通过添加日志记录和异常处理来适当地微调触发器和函数。阅读有关autonomous_transaction 的更多信息。
【讨论】:
-1 如果触发语句回滚,这将导致插入虚假行。 这就是第一个词是“通常不推荐”的原因,使用“autonomous_transaction”总是有一个警告 “通常不推荐”意味着您可能“有时推荐”这种方法。我不同意。以上是关于在表上创建复杂触发器的主要内容,如果未能解决你的问题,请参考以下文章
在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?