PL/pgSQL:删除(更新)与记录匹配的行

Posted

技术标签:

【中文标题】PL/pgSQL:删除(更新)与记录匹配的行【英文标题】:PL/pgSQL: Delete (update) row matching a record 【发布时间】:2013-08-16 12:24:39 【问题描述】:

我正在用 PL/pgSQL 编写三个触发器。在每种情况下,我都有一个 RECORD 变量,并希望将其插入表中,从表中删除它,或更新它以表示第二个 RECORD 变量。

添加很简单:INSERT INTO mytable VALUES (NEW.*);

删除并不容易,似乎没有这样的语法:

DELETE FROM mytable
WHERE * = OLD.*;

更新也有同样的问题。除了使用this answer 的想法生成匹配的 SQL 查询来比较每个属性之外,是否有一个简单的解决方案?

【问题讨论】:

【参考方案1】:

你可以使用删除技巧

创建表 t(a int, b int); 创建表 ta(a int, b int); 创建函数 t1_delete() 将触发器返回为 $$ 开始 从 ta 中删除,其中 ta = old; 返回空值; 结尾 $$ 语言 plpgsql;

但是这个技巧不适用于 UPDATE。所以在 PL/pgSQL 中完全简单的触发器是不可能的。

【讨论】:

酷 - 不知道。通过将 UPDATE 替换为 DELETE + INSERT(如果该表上有触发器,它可能无法正常工作),可以将其扩展为一个完全工作的通用解决方案(触发器问题除外)。谢谢!【参考方案2】:

你写了一个记录变量,对于access individual columns of an anonymous record in plpgsql,它确实不是微不足道的。

但是,在您的示例中,您只使用了OLDNEW,它们是众所周知的行类型,由基础表定义。在这种情况下,访问单个列是微不足道的。

DELETE FROM mytable
WHERE mytable_id = OLD.mytable_id;

UPDATE mytable_b
SET    some_col = NEW.some_other_col
WHERE  some_id  = NEW.mytable_id;

等等

请注意不要创建无限循环。

如果您只想“更新”当前行的列,您可以简单地将触发器中的NEW 对象分配给列。你知道的,对吧?

NEW.some_col := 'foo';

动态列名

如果您事先不知道列名,您仍然可以使用动态 SQL 通常执行此操作,如以下相关答案中所述:Update multiple columns in a trigger function in plpgsql

【讨论】:

我对这种方法的问题是我需要(手动)为每个表自定义触发器以包含列名 - 我最终编写了一个脚本来自动为我生成这些触发器。 @fefrei:我为 dynamic 列名添加了一个段落。

以上是关于PL/pgSQL:删除(更新)与记录匹配的行的主要内容,如果未能解决你的问题,请参考以下文章

如果一行匹配条件,则 sed 替换与模式范围匹配的行

postgresql 上的更新类型

如何删除与另一个文档中的行匹配的行

Oracle删除与多个值匹配的行

如何从一个表中删除与另一表匹配的行?

循环通过 PL/PGSQL 中的 CURSOR 而不锁定表