如何在每次插入/更新中强制指定一列(不是默认为空)

cti*_*dex 5 postgresql update check-constraints

下表:

CREATE TABLE kontrolle.negativtext
(
  id serial NOT NULL,
  ausschluss character varying(255) NOT NULL, 
  nur_domains character varying(255)[] NOT NULL DEFAULT '{}'::character varying[],
  nicht_domains character varying(255)[] NOT NULL DEFAULT '{}'::character varying[],
  bemerkung character varying(255), 
  last_change_user character varying(3) NOT NULL,
  last_change_timestamp timestamp without time zone,
  hits integer NOT NULL DEFAULT 0,
  is_regex boolean NOT NULL DEFAULT false, 
  check_doc negative_doc_check[] DEFAULT '{CONTENT_TXT_DIRTY, CONTENT_TXT_CLEAN}', 
  CONSTRAINT negativtext_pkey PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)

该表中数据记录的值应该可由多个用户更改。我想强制每个人更新或插入此表中的值以提供用户名(我们不需要讨论为什么这不是外键)。
将列设置为NOT NULL DEFAULT NULL将防止该值为空,这很好。但是,当用户abc插入一行并xyz稍后更新它时,xyz应该需要为 column 提供一个值last_change_user,这意味着此更新语句应该抛出错误:

Update kontrolle.negativtext set ausschluss = :a, regex : rgx where id = :id
Run Code Online (Sandbox Code Playgroud)

即使已经有一个用户名集,但这应该有效:

Update kontrolle.negativtext
set ausschluss = :a, regex : rgx, last_change_user = :user
where id = :id
Run Code Online (Sandbox Code Playgroud)

认为约束不起作用,触发器before update on应该起作用,但我没有成功:

create trigger mandatory_username before update on kontrolle.negativtext
for each row
execute procedure check_mandatory_username();


create or replace function check_mandatory_username()
returns trigger as $bla$
begin
    if NEW.last_change_user is null then 
        raise exception 'no last_change_user provided'
        USING HINT = 'please add your name';
    else return NEW;
    end if;
end;
$bla$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

这永远不会引发异常。如果我删除条件部分:

create or replace function check_mandatory_username()
returns trigger as $bla$
begin            
    raise exception 'no last_change_user provided'
    USING HINT = 'please add your name';            
end;
$bla$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

然后我每次都会收到消息,所以总的来说这可能是要走的路。但我认为NEW.last_change_user不检查提供的名称,而仅检查新值(即旧名称)。

有人有主意吗?

小智 5

NEW.last_change_user is null仅当 UPDATE 语句显式包含 a 时,触发器中的检查才会为 true set last_change_user = NULL,而不是如果值未更改(则新的和旧的完全相同)。

您可以使用检查值是否更改if new.last_change_user is distinct from old.last_change_user,但根本无法检查值是否已指定,可能提供与列中已存在的值相同的值。

这里需要类似 Oracle 的updating(column_name)功能,但 Postgres 没有。

所以我认为你的问题的答案是:不,这是不可能的。