Postgresql:触发函数使其可编辑,就像可更新视图一样

时间:2012-10-29 01:15:11

标签: sql postgresql triggers

我在PostgreSQL中创建了一个函数,它可以处理几个表,并根据传递的参数组装结果。它工作得很好,从客户端的角度看,它看起来像一个带有附加参数的普通表(即可以像通常的选择查询一样查询)。

为了保持隐藏有关底层数据的信息,我还想创建一种写入表的方法。我以为我会创建一个触发器来执行一个基本上更新相关底层表的函数。但是,我无法在函数上创建触发器。除了桌子之外,还有什么方法可以创建触发器吗?我也在考虑使用一个视图(因为我相信可以在视图上创建一个触发器),但是我需要将该函数更改为一个不适合的视图,因为我无法传递一个参数。

1 个答案:

答案 0 :(得分:3)

您似乎想要在函数上创建等效的可更新视图,您可以在函数上INSERTUPDATEDELETE。这是不可能的。

如果您提供类似功能的界面,也提供数据修改功能。

或者,将您的功能转换为视图。允许它们使用WHERE子句限制视图,而不是将参数传递给函数。然后使用视图触发器(PostgreSQL 9.1及更高版本)或规则(PostgreSQL 9.0及更低版本,如果可能,请不要在较新版本上使用)在视图上启用INSERTUPDATEDELETE 。请参阅CREATE TRIGGERCREATE RULE。规则很棘手,因此请优先使用视图触发器。

PostgreSQL非常聪明地将过滤器推送到视图中,因此SELECT * FROM some_view WHERE some_col = 4通常不会扫描整个视图然后过滤它。它会将WHERE子句“推送”到视图的查询中并执行它。因此,如果您的视图为SELECT * FROM some_table WHERE NOT is_archived,PostgreSQL实际上将执行相当于SELECT * FROM some_table WHERE (NOT is_archived) AND some_col = 4的操作。因此,在查询几行与所有行的视图时,您可以并且经常会获得完全不同的查询计划。 There's an example of this in a post I wrote a while ago

只是将函数包装在视图中将无法正常工作,除非它是STABLE而不是IMMUTABLE的SQL函数(因此可以内联)。您最好从函数中提取SQL并基于相同的SQL创建视图,而不是基于它自己的函数。

如果您的函数参数未在简单WHERE子句中使用,那么它会变得更复杂,因为无法像在函数中那样将参数传递到视图中。您可以在参数的所有可能值上创建视图,然后对其进行过滤,但如果Pg seq扫描视图,则可能导致真正糟糕的性能。在这些更复杂的情况下,我想提供一个函数调用接口来进行修改。