Postgresql触发“ NEW”或附近的语法错误

时间:2018-08-14 08:28:41

标签: postgresql

这就是我想要做的:

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对象进行插入操作?

2 个答案:

答案 0 :(得分:2)

我不确定您要做什么,但是这里的语法错误:

with newcontactorder as (SELECT contactorder FROM publishroomcontacts WHERE publishroomid = NEW.publishroomid ORDER BY contactorder limit 1)    
NEW.contactorder = (newcontactorder + 1);

如果之后没有选择,请不要使用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

来解决此问题。

答案 1 :(得分:1)

WITH不是PL / pgSQL中的赋值。

PL / pgSQL将该行解释为SQL语句,但这是不好的SQL,因为WITH子句后面是NEW.contactorder,而不是SELECT或另一个CTE。

出现错误;与此无关NEW

您可能想要类似的东西

SELECT contactorder INTO newcontactorder
FROM publishroomcontacts
WHERE publishroomid = NEW.publishroomid
ORDER BY contactorder DESC  -- you want the biggest one, right?
LIMIT 1;

您必须在newcontactorder部分中声明DECLARE

警告::如果同时存在两个插入,则它们可能会以相同的newcontactorder结尾。