我遇到了以下问题。我想更改 INSERT 语句的一些值,例如有一个查询:
INSERT INTO table(a,b) values(x,y);
但是 table 还有另一列c。我想从上面的查询中检查(在插入之前)b的值,然后根据一个人的值设置c=z,但只针对我刚刚插入的这个特定行。
我认为一些触发器可以帮助解决我的问题,但我不知道该怎么做。任何伪代码将不胜感激。
我遇到了以下问题。我想更改 INSERT 语句的一些值,例如有一个查询:
INSERT INTO table(a,b) values(x,y);
但是 table 还有另一列c。我想从上面的查询中检查(在插入之前)b的值,然后根据一个人的值设置c=z,但只针对我刚刚插入的这个特定行。
我认为一些触发器可以帮助解决我的问题,但我不知道该怎么做。任何伪代码将不胜感激。
限制普通用户直接访问表是 goog 的做法。它可以通过使用存储过程来完成,并且只授予它们访问权限。例如(对不起,长代码):
create table foo (
a integer,
b integer,
c integer);
--== Create table. Yes, it is no PK, but for example it is not necesarry
create or replace function p_foo_insert(in aa integer, in ab integer) returns integer as
$$
declare
result integer;
begin
insert into foo (a, b, c) values (aa, ab, aa + ab) returning c into result;
return result;
end; $$ language plpgsql SECURITY DEFINER;
--== It is function for row insertion. Inside this function you can do any data manipulation.
select p_foo_insert(1, 2);
--== Test statement. Result must be a + b = 1 + 2 = 3
所以,忘了insert into
,使用存储过程:o)
PS:关于SECURITY DEFINER
选项的注意事项。它允许授予对函数的访问权限,而无需授予对其中使用的对象的访问权限。
You can do this in the INSERT
statement itself, no trigger needed.
Given table t
:
CREATE TEMP TABLE t (a int, b int, c int)
Default for c
is NULL
.
Consider this demo:
WITH i(x,y,z) AS (
VALUES
(1, 2, 111)
,(1, 7, 666)
)
INSERT INTO t(a,b,c)
SELECT x, y, CASE WHEN y = 2 THEN z ELSE NULL END
FROM i
RETURNING *
The WITH
(requires Postgres 9.1+) and the RETURNING
clause are just for testing convenience .
The important part is the SELECT
with the CASE
statement.
This test should work for pg 8.4:
INSERT INTO t(a,b,c)
SELECT x, y, CASE WHEN y = 2 THEN z ELSE NULL END
FROM (
VALUES
(1, 2, 111)
,(1, 7, 666)
) i (x,y,z)
RETURNING *