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,它确实不是微不足道的。
但是,在您的示例中,您只使用了OLD
和NEW
,它们是众所周知的行类型,由基础表定义。在这种情况下,访问单个列是微不足道的。
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:删除(更新)与记录匹配的行的主要内容,如果未能解决你的问题,请参考以下文章