Postgresql语法错误在“+”或附近

时间:2016-04-21 11:00:30

标签: sql postgresql stored-procedures sql-function

我有以下postgresql函数:

CREATE OR REPLACE FUNCTION insert_address() RETURNS TRIGGER AS
$BODY$

DECLARE row_count INTEGER;
DECLARE max_id INTEGER;
DECLARE key_ INTEGER;

BEGIN
SELECT count(*) FROM ADDRESS INTO row_count;

IF row_count = 0
THEN SET NEW.id_address = 1;
ELSE SELECT count(table_name)
 FROM FREE_KEYS
 WHERE table_name = 'ADDRESS' INTO row_count;

 IF row_count = 0 
 THEN SELECT max(id_address) FROM ADDRESS INTO max_id;
      SET NEW.id_address = max_id + 1;

 ELSE SELECT min(free_key) FROM FREE_KEYS WHERE table_name = 'ADDRESS' INTO key_;
      SET NEW.id_address = key_;
      DELETE FROM FREE_KEYS WHERE table_name = 'ADDRESS' AND free_key = key_;
 END IF;
END IF;
END;
$BODY$ LANGUAGE plpgsql;

我不明白为什么赋值操作会返回以下错误:

ERROR:  syntax error at or near "+"
LINE 700:        SET NEW.id_address = max_id + 1;

2 个答案:

答案 0 :(得分:0)

您的功能中有两个主要错误:

  1. PL / pgSQL中没有SET。使用:=
  2. 完成分配
  3. 变量的INTO子句必须位于SELECT语句中的列列之后。

  4. CREATE OR REPLACE FUNCTION insert_address() RETURNS TRIGGER AS
    $BODY$
    
    DECLARE row_count INTEGER;
    DECLARE max_id INTEGER;
    DECLARE key_ INTEGER;
    
    BEGIN
      SELECT count(*) 
          INTO row_count --<< the INTO has to be after the column list
      FROM ADDRESS;
    
      IF row_count = 0
      THEN 
        NEW.id_address := 1;  --<< there is no SET in PL/pgSQL
      ELSE 
        SELECT count(table_name)
          INTO row_count   --<< the INTO has to be after the column list
        FROM FREE_KEYS
        WHERE table_name = 'ADDRESS';
    
        IF row_count = 0 
        THEN 
          SELECT max(id_address) 
             INTO max_id  --<< the INTO has to be after the column list
          FROM ADDRESS;
    
          NEW.id_address := max_id + 1;
        ELSE 
          SELECT min(free_key) 
             INTO key_    --<< the INTO has to be after the column list
          FROM FREE_KEYS 
          WHERE table_name = 'ADDRESS';
    
          NEW.id_address := key_;
          DELETE FROM FREE_KEYS WHERE table_name = 'ADDRESS' AND free_key = key_;
    
        END IF;
      END IF;
    
    END;
    $BODY$ LANGUAGE plpgsql;
    

    但最大的问题是功能本身。这在具有多个并发事务的环境中不起作用。你不能生成&#34;使用select max()的新ID除非您为每个插入锁定整个表,否则它将无法工作。

答案 1 :(得分:0)

感谢您的帮助,对我有用。我试图在每个表上使用触发器来管理主键。我有一个名为FREE_KEYS的表,其中包含从表中删除的所有主键,以使它们可以重复用于下一次插入。但正如你所说的并发交易,它可能无法正常工作。