【问题标题】:Syntax error while using EXECUTE format in Postgresql Function to assign variable在 Postgresql 函数中使用 EXECUTE 格式分配变量时出现语法错误
【发布时间】:2020-12-27 14:55:23
【问题描述】:

我一直在尝试创建一个函数,该函数旨在为声明的变量赋值,并根据该值采取相应的行动。

我使用EXECUTE format(<SQL statement>) 将值分配给cnt

CREATE OR REPLACE FUNCTION my_function() RETURNS TRIGGER AS $$ 
DECLARE 
    cnt bigint;
BEGIN 
    IF NEW.field1 = 'DECLINED' THEN 
        cnt := EXECUTE format('SELECT count(*) FROM table1 WHERE field2 = $1 AND field1 != $2 AND id != $3;') USING NEW.field2, NEW.field1, NEW.id INTO cnt;
        IF cnt = 0 THEN
             EXECUTE format('UPDATE table1 SET field1 = %1$s WHERE id = $2') USING 'DECLINED', NEW.field2;
         END IF;
    END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER my_trigger BEFORE 
UPDATE OF field1 ON table1 FOR EACH ROW WHEN (NEW.field1 = 'DECLINED') EXECUTE FUNCTION my_function();

但是,我收到以下错误:

ERROR:  syntax error at or near "("
LINE 7:         cnt := EXECUTE format('SELECT count(*) FROM...

不确定是否相关,但id 是文本列,field1 是 ENUM,field2 也是文本列。这可能是SELECT 语句中的问题吗?

有什么我可能会遗漏的想法吗?

【问题讨论】:

  • 我错过了什么吗?我看不到有关这些陈述的任何动态。为什么你使用EXECUTE 而不是直接触发语句?
  • @stickybit 如果cnt 等于0,我只想触发第二个EXECUTE 语句。这就是我使用第一个EXECUTE 的原因。还有其他方法吗?
  • 我在问你为什么使用EXECUTE format(SELECT ... 而不仅仅是SELECT ......
  • 在这种情况下,如果没有format(),我如何将变量传递给WHERE 子句?
  • 随便写? ... WHERE field2 = new.field2 ... 变量可以在语句中用于值(但不能用于标识符,那是你需要动态 SQL 而不是值的时候)。

标签: sql postgresql triggers plpgsql


【解决方案1】:

如果 cnt 等于 0,我只想触发第二个语句

它可以重写为单个语句:

UPDATE table1 
SET field1 = ...
WHERE id = ...
  AND NOT EXISTS (SELECT * 
                  FROM table1 
                  WHERE field2 = ...
                     AND field1 != ... 
                     AND id != ...);

在触发器中使用它表明它是尝试实现部分唯一性。如果是这样,那么部分/过滤索引也是一种选择:

CREATE UNIQUE INDEX uq ON table1(id, field1) WHERE field2 = ....;

【讨论】:

  • 不错,点赞。如果没有UNIQUE INDEX,它会在函数中工作吗?
  • 是的,唯一索引是供将来调查的附录(如果适用)
【解决方案2】:

虽然@Lukasz 解决方案也可能有效。我最终在问题的 cmets 中使用了@stickybit 建议的实现

答案:

CREATE OR REPLACE FUNCTION my_function() RETURNS TRIGGER AS $$ 
DECLARE 
    cnt bigint;
BEGIN 
    IF NEW.field1 = 'DECLINED' THEN 
        cnt := ('SELECT count(*) FROM table1 WHERE field2 = NEW.field2 AND field1 != NEW.field1 AND id != NEW.id;')
        IF cnt = 0 THEN
             'UPDATE table1 SET field1 = 'DECLINED' WHERE id = NEW.field2';
         END IF;
    END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

【讨论】:

    猜你喜欢
    • 2011-10-15
    • 2018-07-12
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    相关资源
    最近更新 更多