在TABLE1上进行SELECT查询时,如何创建一个将TABLE1的值INSERTS到TABLE2的RULE

问题描述 投票:1回答:2

我已经意识到我无法为SELECT创建触发器,因此可以在RULES上使用。

CREATE OR REPLACE RULE log_select AS 
ON SELECT TO usertable 
DO ALSO INSERT INTO selectLOG(prim_key,val)
VALUES(prim_key,val);

上面的示例不适用于以下错误:

ERROR:  column "prim_key" does not exist
LINE 4: VALUES(prim_key,val)
               ^
HINT:  There is a column named "prim_key" in table "old", but 
it cannot be referenced from this part of the query.

基本上,当用户在table1上创建SELECT时,我想将行插入到table2中。

postgresql postgresql-9.5
2个回答
0
投票

The documentation说:

目前,在ON SELECT规则中只能有一个动作,它必须是SELECT的无条件INSTEAD动作。需要这个限制才能使规则足够安全,以便为普通用户打开它们,并且它限制ON SELECT规则像视图一样运行。

所以你将无法做你想做的事。

您拥有的选项是使用日志文件或编写挂钩到查询执行程序的C代码。

如果要使用日志记录,请设置log_statement = alllog_min_duration_statement = 0,然后将记录所有语句,包括SELECTs。

作为源代码中的钩子,您可以使用ExecutorEnd_hook中的include/executor/executor.h。当执行程序结束时,将调用该函数,queryDesc->sourceText将指向正在处理的语句。阅读auto_explain,了解如何使用此钩子。


0
投票

劳伦斯指出,这是不可能的。

但是你考虑过一个能够访问该表的函数,而不是直接访问表本身吗?

您可以创建一个运行查询的函数,存储结果并返回它。然后,仅授予该函数的执行权限,并撤消对该表的任何直接访问。

就像是:

create function get_usertable(p_key integer)
  returns setof usertable
as
$$
  with result as (
     select *
     from usertable
     where id = p_key
  ), log_query as (
     insert into selectlog (prim_key, val)
     select *
     from result
  )
  select *
  from result;
$$
language sql;

此解决方案的主要缺点是,您必须为可能需要的任何条件提供参数(参数p_key只是一个示例)。如果WHERE子句的选项有限,那么这可能是另一种选择。如果你需要更复杂的条件,你可以用动态SQL(以及PL / pgSQL函数而不是SQL函数)来做到这一点,但这也很快。

© www.soinside.com 2019 - 2024. All rights reserved.