这是我正在尝试做的事情:
ALTER TABLE publishroomcontacts ADD COLUMN IF NOT EXISTS contactorder integer NOT NULL default 1;
CREATE OR REPLACE FUNCTION publishroomcontactorder() RETURNS trigger AS $publishroomcontacts$
BEGIN
IF (TG_OP = 'INSERT') THEN
with newcontactorder as (SELECT contactorder FROM publishroomcontacts WHERE publishroomid = NEW.publishroomid ORDER BY contactorder limit 1)
NEW.contactorder = (newcontactorder + 1);
END IF;
RETURN NEW;
END;
$publishroomcontacts$ LANGUAGE plpgsql;
CREATE TRIGGER publishroomcontacts BEFORE INSERT OR UPDATE ON publishroomcontacts
FOR EACH ROW EXECUTE PROCEDURE publishroomcontactorder();
我研究了很多例子,它们看起来都是这样的。他们中的大多数只有几岁。这已经改变了吗?或者为什么新的不起作用?我是否必须在函数中执行插入操作,还是 postgres 在函数完成后使用返回的 NEW 对象执行插入操作?
最佳答案
我不确定您要做什么,但您的语法在这里是错误的:
with newcontactorder as (SELECT contactorder FROM publishroomcontacts WHERE publishroomid = NEW.publishroomid ORDER BY contactorder limit 1)
NEW.contactorder = (newcontactorder + 1);
如果后面没有 select,请勿使用 CTE 查询。如果你想增加 contactorder
特别专栏publishroomid
每当添加新的并且这是您的序列(自动增量)机制时,您应该将其替换为:
NEW.contactorder = COALESCE((
SELECT max(contactorder)
FROM publishroomcontacts
WHERE publishroomid = NEW.publishroomid
), 1);
注意更改:
- 没有 CTE,只是使用 SELECT 查询进行变量赋值
- 使用
MAX()
聚合函数而不是ORDER BY
+LIMIT
- 结束了
COALESCE(x,1)
函数正确插入房间的第一个联系人,它将返回1
如果您的查询确实返回NULL
您的触发器应如下所示
CREATE OR REPLACE FUNCTION publishroomcontactorder() RETURNS trigger AS $publishroomcontacts$
BEGIN
IF (TG_OP = 'INSERT') THEN
NEW.contactorder = COALESCE((
SELECT max(contactorder) + 1
FROM publishroomcontacts
WHERE publishroomid = NEW.publishroomid
), 1);
END IF;
RETURN NEW;
END;
$publishroomcontacts$ LANGUAGE plpgsql;
Postgres 会自行插入行,您无需执行任何操作,因为 RETURN NEW
这样做。
此解决方案不考虑并发插入,这使得多用户环境不安全!您可以通过执行 UPSERT
来解决此问题!
关于Postgresql 触发器语法错误位于 "NEW"处或附近,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51837000/