在TABLE1上执行SELECT查询时,如何创建将TABLE1值插入TABLE2的规则

时间:2019-04-10 04:05:02

标签: postgresql postgresql-9.5

我意识到我无法为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中。

2 个答案:

答案 0 :(得分:0)

The documentation说:

  

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

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

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

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

作为源代码中的钩子,您可以使用ExecutorEnd_hook中的include/executor/executor.h。这将在执行程序结束时调用,并且queryDesc->sourceText将指向正在处理的语句。阅读auto_explain以获得该钩子如何使用的示例。

答案 1 :(得分:0)

正如劳伦兹(Laurenz)指出的那样,这是不可能的。

但是您是否考虑了一个可以访问该表而不是直接访问表本身的函数?

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

类似:

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函数)来完成,但这很快就会变得很丑。