dan*_*cek 35 database postgresql triggers rules
我经常看到它声明应该避免使用规则并使用触发器.我可以看到规则系统中的危险,但当然有规则的有效用途,对吧?这些是什么?
我出于一般兴趣而对此提出这个问题; 我对数据库不太熟悉.
例如,在过去我需要锁定某些数据,所以我做了类似这样的事情:
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
Run Code Online (Sandbox Code Playgroud)
然后,如果我想编辑受保护的数据:
START TRANSACTION;
ALTER TABLE exampletable DISABLE RULE protect_data;
-- edit data as I like
ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
我同意这是hacky,但在这种情况下我无法更改访问数据库的应用程序(甚至在它上面抛出错误).所以奖励积分查找原因,这是一个危险的/无效的使用规则系统的,但不是为什么,这是不好的设计.
a_h*_*ame 17
RULES的一个用例是可更新的视图(尽管9.1中的更改因为该版本为视图引入了INSTEAD OF触发器)
另外一个很好的解释可以在手册中找到:
对于两者都可以实现的东西,最好取决于数据库的用法.为任何受影响的行触发一次触发器.规则操纵查询或生成其他查询.因此,如果在一个语句中影响了许多行,则发出一个额外命令的规则可能比为每一行调用的触发器更快,并且必须多次执行其操作.但是,触发器方法在概念上远比规则方法简单,并且新手更容易正确.
(摘自:http://www.postgresql.org/docs/current/static/rules-triggers.html)
小智 12
这里显示了一些规则问题:http://www.depesz.com/index.php/2010/06/15/to-rule-or-not-to-rule-that-is-the-question/(for例如,如果查询中包含random(),则可能会执行两次并返回不同的值).
规则的最大缺点是人们不理解它们.
例如,有人可能认为有这样的规则:
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
Run Code Online (Sandbox Code Playgroud)
如果我要发出:
update exampletable set whatever = whatever + 1 where type = 'protected'
Run Code Online (Sandbox Code Playgroud)
不会运行任何查询.哪个不是真的.查询将运行,但它将以修改版本运行 - 添加条件.
更重要的是 - 规则打破非常有用的东西,即返回子句:
$ update exampletable set whatever = whatever + 1 where type = 'normal' returning *;
ERROR: cannot perform UPDATE RETURNING on relation "exampletable"
HINT: You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.
Run Code Online (Sandbox Code Playgroud)
包装它 - 如果你真的,真的,肯定必须使用可写视图,并且你正在使用9.1之前的PostgreSQL - 你可能有正当理由使用规则.
在所有其他情况下 - 即使你没有立即看到它,你最有可能用脚射击自己.
在处理易失性函数时,我对规则有一些痛苦的经历(如果内存服务,depesz博客文章强调其中一些).
我使用它们时也破坏了引用完整性,因为fkey触发器被触发的时机:
CREATE OR REPLACE RULE protected_example AS
ON DELETE TO example
WHERE OLD.protected
DO INSTEAD NOTHING;
Run Code Online (Sandbox Code Playgroud)
...然后添加另一个表,并使用on delete cascade外键作为示例引用该表.然后,从那张桌子上删除*......然后惊恐地退缩.
我将上述问题报告为一个错误,它被视为一个特征/必要的边缘情况而被驳回.仅仅几个月后,我才明白为什么会这样,即fkey触发器完成它的工作,然后规则开始并自行完成,但fkey触发器不会检查其工作是否因性能原因而正确完成.
我仍在使用规则的实际用例是当BEFORE
预先操作数据的触发器(SQL标准说不允许,但Postgres很乐意)可以导致预先操纵受影响的行并因此改变它们的ctid(即它会更新两次,或者因为更新使删除无效而不会被删除).
这导致Postgres返回不正确数量的受影响行,这在您发出后续语句之前监视该数字之前没什么大不了的.
在这种情况下,我发现使用策略性放置的规则或两个规则可以允许先发制人地执行违规语句,从而导致Postgres返回正确数量的受影响行.
归档时间: |
|
查看次数: |
17337 次 |
最近记录: |