我有以下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;
答案 0 :(得分:0)
您的功能中有两个主要错误:
:=
INTO
子句必须位于SELECT语句中的列列之后。
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的表,其中包含从表中删除的所有主键,以使它们可以重复用于下一次插入。但正如你所说的并发交易,它可能无法正常工作。