首页 > 解决方案 > 如何确保正在返回触发器生成的值?

问题描述

我有这个 INSERT 查询,其目的是在我的数据库中插入一行。同样,我也有一个插入多行的 INSERT 查询。

表中的一个列是在生成值之后生成的,因为它结合了一组列值来构造一个名称。它从触发器生成的名称本身,以及在插入后触发的名称,因为我必须存在列值才能生成名称。

我现在的问题是当我插入一行或多行时,我想知道生成的列值,但是当我返回它时,它声明它为空?

            @$"INSERT INTO registration_table (id, ...,)
        VALUES (1,...,)
        RETURNING row_id, name;";

作为回报,它给了我id一个我插入的,但不是实际的name,而是我得到 null ..

触发器非常简单

CREATE TRIGGER name_insert_trigger
AFTER INSERT
ON registration_table
REFERENCING NEW TABLE AS new_inserts
FOR EACH STATEMENT
WHEN (pg_trigger_depth() = 0)
EXECUTE PROCEDURE registration_entry_name();


CREATE OR REPLACE FUNCTION registration_entry_name()
  RETURNS trigger AS
$$
DECLARE
BEGIN
   UPDATE registration_table
   SET name = |Pattern| -- This one being the actual name generated.. 
   FROM new_inserts
   WHERE new_inserts.row_id = registration_table.row_id;
   RETURN null;
END;
$$
LANGUAGE plpgsql;

但是上面的插入查询不返回名称?为什么不?

标签: sqlpostgresqlnpgsql

解决方案


您实际上需要一个BEFORE触发器,您的数据值将在那里。Before 和 After 的指定经常会引起误解,尤其是对行级触发器的误解。这些条款并未表明它们与 DML 相关的时间。我发现将它们视为“在设置最终数据值之前”和“在设置最终数据值之后”很有用,但两者都在调用 DML 完成之前运行(现在我们将绕过延迟触发器)。让我们看看插入。当前行触发器触发新行时,新行包含该行中每一列的值,语句中未指定的任何值都将为空或包含指定的默认值(如果有)。在行触发器可以更改任何列之前。在行触发器无法更改列之后,如果存在任何更改,则将被忽略。

您的描述和代码意味着您需要组合几列来生成另一列的内容。由于您没有明确指定我将构建一个示例和演示

create table users ( usr_id  integer generated always as identity
                   , lname   text    not null
                   , fname   text    not null 
                   , full_name text  not null
                   ) ;

create or replace  
function users_bir()
 returns trigger
 language plpgsql
as $$
begin 
    if new.full_name is null 
    then 
       new.full_name = trim(new.fname) || ' ' || trim(new.lname); 
    end if; 
    return new;
end;
$$;

create trigger users_bir_trg
  before insert on users 
  for each row
  execute procedure users_bir(); 
  
insert into users(fname, lname) 
       values ( 'George', 'Henery')
            , ( 'Samatha', 'van Horm'); 
       
insert into users(fname, lname, full_name) 
       values ( 'Wacky', 'Warriors','Not so tough guys');

此设置允许指定或生成 full_name。如果只需要生成,则删除 IF,只留下赋值语句。如果您有 Postgres 12 或更高版本,只需将该列定义为生成的列,那就更好了。这也在演示中。


推荐阅读