Postgresql 当对表1进行SELECT查询时,如何创建将表1的值插入表2的规则

Postgresql 当对表1进行SELECT查询时,如何创建将表1的值插入表2的规则,postgresql,postgresql-9.5,Postgresql,Postgresql 9.5,我意识到我不能为SELECT创建触发器,因此依赖于规则 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)

我意识到我不能为SELECT创建触发器,因此依赖于规则

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.
基本上,当用户在表1上选择时,我想在表2中插入行。

说:

当前,在选择上的
规则中只能有一个操作,它必须是一个无条件的
SELECT
操作,而不是
。这一限制是为了使规则足够安全,可以为普通用户打开它们,并且它限制了SELECT上的
规则的行为类似于视图

所以你不能做你想做的事

您可以选择使用日志文件或编写钩住查询执行器的C代码

如果要使用日志记录,请设置
log\u statement=all
log\u min\u duration\u statement=0
,然后将记录所有语句,包括
SELECT
s

作为源代码中的钩子,您可以使用
include/executor/executor.h
中的
ExecutorEnd\u钩子。当执行器结束时将调用,并且
queryDesc->sourceText
将指向正在处理的语句。请阅读如何使用此挂钩的示例。

说明:

当前,在选择上的
规则中只能有一个操作,它必须是一个无条件的
SELECT
操作,而不是
。这一限制是为了使规则足够安全,可以为普通用户打开它们,并且它限制了SELECT上的
规则的行为类似于视图

所以你不能做你想做的事

您可以选择使用日志文件或编写钩住查询执行器的C代码

如果要使用日志记录,请设置
log\u statement=all
log\u min\u duration\u statement=0
,然后将记录所有语句,包括
SELECT
s


作为源代码中的钩子,您可以使用
include/executor/executor.h
中的
ExecutorEnd\u钩子。当执行器结束时将调用,并且
queryDesc->sourceText
将指向正在处理的语句。阅读一个如何使用这个钩子的例子。

正如Laurenz指出的,这在规则中是不可能的

<>但您是否考虑了一个函数,可以访问该表,而不是直接访问表本身? 您可以创建一个函数来运行查询、存储结果并返回结果。然后只授予函数的execute权限并撤销对该表的任何直接访问

比如:

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;

此解决方案的主要缺点是,您必须为任何可能需要的条件提供参数(parameter
p_key
只是一个示例)。如果
WHERE
子句的选项受到限制,则这可能是一种替代方法。如果需要更复杂的where条件,可以使用动态SQL(以及PL/pgSQL函数而不是SQL函数)来实现,但这也会很快变得难看。

正如Laurenz指出的,这在规则中是不可能的

<>但您是否考虑了一个函数,可以访问该表,而不是直接访问表本身? 您可以创建一个函数来运行查询、存储结果并返回结果。然后只授予函数的execute权限并撤销对该表的任何直接访问

比如:

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;

此解决方案的主要缺点是,您必须为任何可能需要的条件提供参数(parameter
p_key
只是一个示例)。如果
WHERE
子句的选项受到限制,则这可能是一种替代方法。如果需要更复杂的where条件,可以使用动态SQL(以及PL/pgSQL函数而不是SQL函数)实现,但这也会很快变得难看。

MySQL、Oracle或PostgreSQL?我不认为您正在使用这三个来运行同一个查询,但是您已经标记了它们。谢谢,现在更改了。我使用的是PostgreSqlMySQL、Oracle还是PostgreSQL?我不认为您正在使用这三个来运行同一个查询,但是您已经标记了它们。谢谢,现在更改了。我正在使用PostgreSql谢谢你回答这个问题。你能详细说明一下“使用日志文件”吗?我的日志设置为debug2级别,我不希望在那里记录任何SELECT响应。而且我还没有翻阅Postgres的代码库,所以不确定我到底需要把钩子放在哪里。目标是记录特定表上的SELECT(有条件或无条件)查询。我扩展了答案来解释这一点。感谢更新答案!但是,我有log_statement=all和og_min_duration_statement=0,选择操作会被记录,但是从选择查询收到的响应不会被记录。这就是我想要实现的。至于钩子,让我看看,谢谢你的参考。捕获结果是一双完全不同的鞋子,可能会更难。为什么不编写一个位于客户端和服务器之间的代理呢?协议。那会简单得多。我也有同样的想法,但我喜欢呆在数据库层,不让任何应用程序/代理做日志记录。我正在测试一个特定的用例。谢谢你回答这个问题。你能详细说明一下“使用日志文件”吗?我的日志设置为debug2级别,我不希望在那里记录任何SELECT响应。而且我还没有翻阅Postgres的代码库,所以不确定我到底需要把钩子放在哪里。目标是记录特定表上的SELECT(有条件或无条件)查询。我扩展了答案来解释这一点。感谢更新答案!但是,我有log_statement=all和og_min_duration_statement=0,选择操作会被记录,但是从选择查询收到的响应不会被记录。这就是我想要达到的目标