【问题标题】:trigger insert only if tupel satisfies condition仅当元组满足条件时才触发插入
【发布时间】:2021-08-21 13:23:21
【问题描述】:

我想创建一个触发器,在插入之前检查应该插入的元组是否具有特定条件(这也取决于另一个表)。

例如:

create trigger or replace check_tupel
before insert on A
for each row
execute
   if exists (select x,y from B where B.x = A.x and B.y = A.y)

哦,我正在使用 postgreSQL 13。

编辑:是的,我知道我可以在没有触发器的情况下执行此操作,但我要求使用触发器的解决方案是有原因的。

我希望有办法做到这一点...我的另一个想法是创建一个在插入之前调用的 UDF,但我不知道如何检查此 UDF 中的条件,只有在函数返回 true 时才插入。

【问题讨论】:

  • 你会做什么if the tupel which is supposed to be inserted holds a specific condition
  • 查看手册,创建触发函数(!)然后触发:postgresql.org/docs/current/plpgsql-trigger.html
  • 如果符合条件,我想插入元组。

标签: sql postgresql triggers


【解决方案1】:

如果您只是想在基于表B 使用用户定义函数将记录插入表A 之前自动验证记录,则根本不需要触发器。考虑添加一个简单的CHECK CONSTRAINT

CREATE TABLE a (
  x int,
  y int,
 CONSTRAINT exists_in_b CHECK (NOT myfunc(x,y))
);

演示:db<>fiddle

CREATE TABLE b (x int,
                y int);
INSERT INTO b VALUES (42,42);

CREATE OR REPLACE FUNCTION myfunc(x int, y int) 
RETURNS BOOLEAN AS $BODY$
 SELECT EXISTS (SELECT 1 FROM b WHERE b.y =$1 AND b.x=$2 )
$BODY$
LANGUAGE sql;

CREATE TABLE a (
  x int,
  y int,
 CONSTRAINT exists_in_b CHECK (NOT myfunc(x,y)) -- here the magic happens
);

现在,如果我们尝试插入我们的函数未验证的值,则会引发异常:

INSERT INTO a VALUES (42,42);

ERROR:  new row for relation "a" violates check constraint "exists_in_b"
DETAIL:  Failing row contains (42, 42).
SQL state: 23514

EDIT(参见 cmets):使用触发器的解决方案

CREATE OR REPLACE FUNCTION myfunc() 
RETURNS TRIGGER AS $BODY$
BEGIN
 IF EXISTS (SELECT 1 FROM b WHERE b.y =NEW.y AND b.x=NEW.x ) THEN
   RAISE EXCEPTION 'tuple already exists in "b": % %', NEW.x,NEW.y;
 END IF;
 RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

CREATE TRIGGER check_tupel
BEFORE INSERT OR UPDATE ON a
FOR EACH ROW EXECUTE PROCEDURE myfunc();

演示:db<>fiddle

【讨论】:

  • 这是一个非常好的解决方案,但我要求使用触发器是有原因的。
  • @maba 我明白了。所以也许我的最后一次编辑可能会对你有所帮助
【解决方案2】:

所以你需要一个触发解决方案,听起来像是一个家庭作业问题。那么问题就变成了你想要:

  1. 中止整个操作
  2. 稍微压扁该行,但继续其余操作。

下面是第二个:(见demo

create or replace 
function check_b_has_a() 
 returns trigger 
 language plpgsql
as $$
begin 
    if exists 
        ( select null 
            from b 
           where (b.x,b.y) = 
                 (new.x, new.y)
        ) 
    then 
       return null; 
    else 
       return new; 
    end if;
end; 
$$; 

create trigger a_bir
   before insert 
       on a 
      for each row 
      execute function check_b_has_a(); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 2018-06-03
    • 1970-01-01
    相关资源
    最近更新 更多