【问题标题】:How can I create a RULE that INSERTS values of TABLE1 to TABLE2 when a SELECT query is made on TABLE1当对 TABLE1 进行 SELECT 查询时,如何创建将 TABLE1 的值插入到 TABLE2 的规则
【发布时间】:2019-08-31 10:37:58
【问题描述】:

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

【问题讨论】:

  • MySQL、Oracle 还是 PostgreSQL?我认为您没有使用全部三个来运行相同的查询,但您已将它们全部标记。
  • 谢谢,现在改了。我正在使用 PostgreSql

标签: postgresql postgresql-9.5


【解决方案1】:

正如 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 子句的选项有限,那么这可能是一个替代方案。如果您需要更复杂的 where 条件,您可以使用动态 SQL(以及 PL/pgSQL 函数而不是 SQL 函数)来实现,但这也会很快变得丑陋。

【讨论】:

    【解决方案2】:

    The documentation 说:

    目前,ON SELECT 规则中只能有一个操作,并且必须是无条件的SELECT 操作,即INSTEAD。需要此限制以使规则足够安全以向普通用户打开它们,并且它限制ON SELECT 规则的行为类似于视图。

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

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

    如果你想使用日志,设置log_statement = alllog_min_duration_statement = 0,那么所有的语句,包括SELECTs,都会被记录。

    作为源代码中的挂钩,您可以使用来自include/executor/executor.hExecutorEnd_hook。这将在执行程序结束时调用,queryDesc->sourceText 将指向正在处理的语句。阅读auto_explain 了解如何使用此钩子的示例。

    【讨论】:

    • 感谢您回答问题。您能否详细说明“使用日志文件”?我的日志设置为 debug2 级别,我不希望在那里记录任何 SELECT 响应。而且我还没有深入研究 Postgres 代码库,所以不确定我需要把钩子放在哪里。目标是在特定表上记录 SELECT(条件或非条件)查询。
    • 我已经扩展了答案来解释这一点。
    • 感谢您更新答案!但是,我有 log_statement=all 和 og_min_duration_statement = 0 SELECT 操作被记录,但从 select 查询收到的响应不会。这就是我想要实现的目标。至于钩子让我看看,谢谢参考。
    • 捕捉结果是一双完全不同的鞋子,可能会更加困难。为什么不编写一个位于客户端和服务器之间的代理?协议is well documented。那会简单得多。
    • 有同样的想法,但我热衷于留在数据库层并且没有任何应用程序/代理进行日志记录。我正在对特定用例进行基准测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    相关资源
    最近更新 更多