2016-04-21 2 views
0

я получил следующую PostGreSQL функции:ошибка синтаксиса 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

У вас есть два основные ошибки в вашей функции:

  1. В PL/pgSQL нет SET. Назначение выполняется с использованием :=
  2. Предложение переменной 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; 

Но самой большой проблемой является сама функция. Это не будет работать в среде с более чем одной одновременной транзакцией. Вы не можете «генерировать» новые идентификаторы, используя select max(), он просто не будет работать, если вы не заблокируете всю таблицу для каждой вставки.

0

Спасибо за помощь, которая сработала для меня. Я пытаюсь управлять первичными ключами с помощью триггеров на каждой из моих таблиц. У меня есть таблица FREE_KEYS, которая содержит все первичные ключи, удаленные из таблиц, чтобы сделать их повторно используемыми для следующих вставок. Но, как вы сказали, с одновременными транзакциями, возможно, это не сработает.

Смежные вопросы