Postgresql 当对表1进行SELECT查询时,如何创建将表1的值插入表2的规则
我意识到我不能为SELECT创建触发器,因此依赖于规则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)
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;
此解决方案的主要缺点是,您必须为任何可能需要的条件提供参数(parameterp_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;
此解决方案的主要缺点是,您必须为任何可能需要的条件提供参数(parameterp_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,选择操作会被记录,但是从选择查询收到的响应不会被记录。这就是我想要达到的目标