简体   繁体   中英

Postgresql syntax error at or near “+”

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:

  1. There is no SET in PL/pgSQL. Assignment is done using :=
  2. The 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM