I got the following postgresql function:
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;
i don't understand why the assignment operation returns the following error:
ERROR: syntax error at or near "+"
LINE 700: SET NEW.id_address = max_id + 1;
You have two main errors in your function:
:=
INTO
clause for a variable has to come after the list of columns in the SELECT statement. 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;
But the biggest problem is the function itself. This is not going to work in an environment with more then one concurrent transaction. You can't "generate" new IDs using select max()
it simply won't work unless you lock the whole table for every insert.
Thanks for your help that worked for me. I'm trying to manage primary keys using triggers on each of my tables. I have a table called FREE_KEYS which contains all the primary keys deleted from tables to make them reusable for the next inserts. But as you said with concurrent transactions it will maybe not work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.