Database PostgreSQL规则有什么好处? 问题:

Database PostgreSQL规则有什么好处? 问题:,database,postgresql,triggers,rules,Database,Postgresql,Triggers,Rules,我经常看到它这样说。我可以看到规则系统中的危险,但规则肯定有有效的用途,对吗?它们是什么 我问这个是出于一般利益;我对数据库不太熟悉 可能有效使用的示例 例如,过去我需要锁定某些数据,所以我做了如下工作: CREATE OR REPLACE RULE protect_data AS ON UPDATE TO exampletable -- another similar rule for DELETE WHERE OLD.type = 'protected'

我经常看到它这样说。我可以看到规则系统中的危险,但规则肯定有有效的用途,对吗?它们是什么

我问这个是出于一般利益;我对数据库不太熟悉

可能有效使用的示例 例如,过去我需要锁定某些数据,所以我做了如下工作:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;
然后,如果要编辑受保护的数据:

START TRANSACTION;
  ALTER TABLE exampletable DISABLE RULE protect_data;
  -- edit data as I like
  ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;

我同意这是有问题的,但在这种情况下,我无法更改访问数据库的应用程序(甚至不能抛出错误)。因此,奖励积分用于找出规则系统危险/无效使用的原因,但不是用于说明设计不好的原因。

如何:您有一个表需要更改为视图。为了支持插入到所述表中的遗留应用程序,创建了一个规则,将“插入”映射到新视图到基础表。

规则的一个用例是可更新视图(尽管随着9.1版本引入视图而不是触发器,该规则会发生变化)

手册中还有另一个很好的解释:

对于两者都可以实现的东西,哪一个最好取决于数据库的使用情况。对任何受影响的行触发一次触发器。规则操纵查询或生成附加查询。因此,如果一条语句中有多行受到影响,则发出一条额外命令的规则可能比为每一行调用且必须多次执行其操作的触发器要快。然而,触发方法在概念上比规则方法简单得多,新手更容易掌握正确的方法


(摘自:)

此处显示了一些规则问题:(例如,如果查询中包含一个random(),它可能会执行两次并返回不同的值)

规则最大的缺点是人们不理解规则

例如,有人可能会认为拥有规则:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;
这意味着如果我发布:

update exampletable set whatever = whatever + 1 where type = 'protected'
不会运行任何查询。但事实并非如此。查询将运行,但它将在修改后的版本中运行-添加了条件

更重要的是,规则打破了非常有用的东西,那就是返回子句:

$ 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.
总而言之,如果您真的、真的、肯定地必须使用可写视图,并且您使用的是9.1之前的PostgreSQL,那么您可能有充分的理由使用规则


在所有其他情况下——即使你没有立即看到它,你也很可能是在开枪打伤自己。

在处理易失性函数时,我有过一些痛苦的经验(如果内存可用,depesz的博客文章会强调其中的一些)

我在使用它们时也破坏了引用完整性,因为fkey触发器被触发的时间:

CREATE OR REPLACE RULE protected_example AS
  ON DELETE TO example
  WHERE OLD.protected
  DO INSTEAD NOTHING;
。。。然后添加另一个表,并使示例使用on delete级联外键引用该表。然后,从该表中删除*。。。恐惧地退缩

我将上述问题报告为一个bug,并将其作为一个功能/必要的边缘案例予以驳回。仅仅几个月后,我才明白为什么会这样,即fkey触发器完成了它的工作,然后规则启动并执行它自己的工作,但fkey触发器不会检查它的工作是否出于性能原因正确完成

我仍然使用规则的实际用例是,预处理数据的
BEFORE
触发器(SQL标准说是不允许的,但Postgres很乐意这样做)可能导致预处理受影响的行,从而更改它们的ctid(即,它被更新两次,或者由于更新使删除无效而未被删除)

这会导致Postgres返回错误数量的受影响行,除非在发出后续语句之前监视该数量,否则这并没有什么大不了的


在这种情况下,我发现使用一个或两个策略性的规则可以允许先发制人地执行违规语句,导致Postgres返回正确数量的受影响行。

这是无效的用法。应该使用触发器来完成。+1中断
返回
确实是避免规则的一个很好的理由,我没有想到这一点。我的示例可以被视为一个可写视图,因此我想您的摘要是有意义的。有任何理由使用规则吗而不是语句级触发器?