我在其中一列中有一个使用序列作为默认值的表。每当在此表中有插入内容时,我都想将序列的值插入到另一个表中。但是,在执行此操作时,我获得了由序列生成的值的空值。这是示例代码:
create sequence usq_test
as bigint
increment by 1
start 1
minvalue 1
maxvalue 9223372036854775807
no cycle
owned by none;
create table test1(
id bigint default nextval('usq_test') primary key,
name text not null);
insert into test1(name) values ('test_name');
insert into test1(name) values ('test_name');
insert into test1(name) values ('test_name');
select * from test1;
| id | name |
|----|-----------|
| 1 | test_name |
| 2 | test_name |
| 3 | test_name |
现在,当我添加第二个表并定义触发函数时:
create table test2(id bigint primary key);
create or replace function ufn_insert_trg() returns trigger as
$$
begin
insert into test2(id)
values (NEW.id);
end;
$$ language plpgsql
;
create trigger utr_test1_insert
after insert
on test1
execute function ufn_insert_trg();
insert into test1(name) values ('test_name');
我得到:
[2019-04-04 14:00:45] [23502] ERROR: null value in column "id" violates not-null constraint
[2019-04-04 14:00:45] Detail: Failing row contains (null).
[2019-04-04 14:00:45] Where: SQL statement "insert into test2(id)
[2019-04-04 14:00:45] values (NEW.id)"
[2019-04-04 14:00:45] PL/pgSQL function ufn_insert_trg() line 3 at SQL statement
我在做什么错了?
答案 0 :(得分:1)
问题出在您的触发器上
create trigger utr_test1_insert after insert on test1 execute function ufn_insert_trg();
因为您没有明确说明触发器是行级还是语句级,所以默认情况下它将变为语句级触发器。
每行
每份声明
这指定是否触发 对于受触发器影响的每一行应触发一次函数 事件,或每个SQL语句一次。如果未指定,则FOR 默认为“每个语句”。
而且根据the documentation,语句级触发器中的NEW
和OLD
变量为NULL,这是有道理的,因为语句中可能影响了任何数量的行,因此NEW
或OLD
引用任何特定的语句实际上没有任何意义-您要处理的是语句而不是特定的行。
这就是NEW.id
为NULL的原因。通过将触发器更改为行级触发器,将为受影响的每一行触发该触发器,并按预期设置NEW
/ OLD
变量。
所以:
create trigger utr_test1_insert
after insert
on test1
for each row
execute function ufn_insert_trg();