我意识到我无法为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中。
答案 0 :(得分:0)
当前,
ON SELECT
规则中只能有一个动作,并且它必须是SELECT
的无条件INSTEAD
动作。需要使用此限制,以使规则足够安全才能为普通用户打开它们,并且限制ON SELECT
规则以使其像视图一样。
所以您将无法做您想做的事。
您拥有的选项是使用日志文件或编写挂接到查询执行器的C代码。
如果要使用日志记录,请设置log_statement = all
或log_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函数)来完成,但这很快就会变得很丑。