当对 TABLE1 进行 SELECT 查询时,如何创建将 TABLE1 的值插入到 TABLE2 的规则
How can I create a RULE that INSERTS values of TABLE1 to TABLE2 when a SELECT query is made on TABLE1
我意识到我无法为 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 进行 SELECT 时将行插入表 2。
Currently, there can be only one action in an ON SELECT
rule, and it must be an unconditional SELECT
action that is INSTEAD
. This restriction was required to make rules safe enough to open them for ordinary users, and it restricts ON SELECT
rules to act like views.
所以你将无法为所欲为。
您可以选择使用日志文件或编写挂接到查询执行程序的 C 代码。
如果要使用日志记录,请设置 log_statement = all
或 log_min_duration_statement = 0
,然后将记录所有语句,包括 SELECT
s。
作为源代码中的钩子,您可以使用 include/executor/executor.h
中的 ExecutorEnd_hook
。这将在执行程序结束时调用,并且 queryDesc->sourceText
将指向正在处理的语句。阅读 auto_explain
以了解如何使用此挂钩的示例。
正如 Laurenz 所指出的,这在规则中是不可能的。
但是您是否考虑过一个可以访问 table 而不是直接访问 table 本身的函数?
您可以创建一个函数来运行查询、存储结果并 returns 它。然后仅授予该函数的执行权限并撤销对该函数的任何直接访问 table.
类似于:
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 函数),但这也很快变得丑陋。
我意识到我无法为 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 进行 SELECT 时将行插入表 2。
Currently, there can be only one action in an
ON SELECT
rule, and it must be an unconditionalSELECT
action that isINSTEAD
. This restriction was required to make rules safe enough to open them for ordinary users, and it restrictsON SELECT
rules to act like views.
所以你将无法为所欲为。
您可以选择使用日志文件或编写挂接到查询执行程序的 C 代码。
如果要使用日志记录,请设置 log_statement = all
或 log_min_duration_statement = 0
,然后将记录所有语句,包括 SELECT
s。
作为源代码中的钩子,您可以使用 include/executor/executor.h
中的 ExecutorEnd_hook
。这将在执行程序结束时调用,并且 queryDesc->sourceText
将指向正在处理的语句。阅读 auto_explain
以了解如何使用此挂钩的示例。
正如 Laurenz 所指出的,这在规则中是不可能的。
但是您是否考虑过一个可以访问 table 而不是直接访问 table 本身的函数?
您可以创建一个函数来运行查询、存储结果并 returns 它。然后仅授予该函数的执行权限并撤销对该函数的任何直接访问 table.
类似于:
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 函数),但这也很快变得丑陋。