Как устранить ошибку «кортеж, который должен быть обновлен, уже был изменен операцией, вызванной текущей командой»? - PullRequest
0 голосов
/ 28 июня 2019

Я создаю элемент таблицы, который выглядит следующим образом:

Item {
    id ,
    item_name ,
    position ,
    is_parent ,
    parent_id// parent is an other item
}

Я создаю функцию для обновления позиции всего элемента, например, если я вставляю элемент с позицией 2 иэлемент уже существует с позицией 2, позиция этого элемента будет изменена и будет иметь позицию 3.

ДО ВСТАВКИ :

| id  |    item_name    | position | is_parent | parent_id
|  1  |     item1       |   2      |   FALSE   |
|  2  |     item2       |   3      |   FALSE   |

ПОСЛЕ ВСТАВКИ:

вставка элемента 3 с позицией = 2

| id  |    item_name    | position | is_parent | parent_id |
|  1  |     item1       |   3      |   FALSE   |           |
|  2  |     item2       |   4      |   FALSE   |           |
|  3  |     item3       |   2      |   FALSE   |           |

Для выполнения этой модификации я создаю эту функцию:

CREATE OR REPLACE FUNCTION public.update_position_item()
  RETURNS trigger AS
$BODY$  BEGIN 
    IF(TG_OP = 'UPDATE') THEN
        IF(NEW.position <= OLD.position ) THEN
            EXECUTE 'UPDATE "item" SET position=position+1 WHERE position>=' || NEW.position || ' AND position<' || OLD.position || ' AND id<>' || NEW.id || ';';
        ELSE
            EXECUTE 'UPDATE "item" SET position=position-1 WHERE position>' || OLD.position || ' AND position<=' || NEW.position || ' AND id<>' || NEW.id || ';';
        END IF;
    ELSIF(TG_OP = 'INSERT') THEN
        EXECUTE 'UPDATE "item" SET position=position+1 WHERE position>=' || NEW.position || ' AND id<>' || NEW.id || ';';        
    ELSIF(TG_OP = 'DELETE') THEN
        EXECUTE 'UPDATE "item" SET position=position-1 WHERE position>' || OLD.position || ' AND id<>' || OLD.id || ';';
    END IF;     
    RETURN NEW;
  END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.update_position_item()
  OWNER TO postgres;

Ассоциированный триггер:

CREATE TRIGGER update_item_position
  AFTER INSERT OR UPDATE OR DELETE
  ON public.item
  FOR EACH ROW
  EXECUTE PROCEDURE public.update_position_item();

Работает хорошо, но когда я создаю функцию для обновления значения is_parent, у меня появляется ошибка.

Функция дляupdate is_parent :

CREATE OR REPLACE FUNCTION public.isparent()
  RETURNS trigger AS
$BODY$
BEGIN
IF NEW.parent_id IS NOT NULL THEN
    UPDATE item SET is_parent = true WHERE id = NEW.parent_id;
ELSE
    IF(TG_OP = 'UPDATE') THEN
        IF (NEW.parent_id IS NULL AND OLD.parent_id IS NOT NULL) THEN
        IF((SELECT COUNT(*) FROM item WHERE parent_id = OLD.parent_id) < 1) 
            THEN UPDATE item SET is_parent = false WHERE id = OLD.parent_id;
        END IF ;
        END IF;
    END IF;  
END IF;   
 RETURN NEW;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.isparent()
  OWNER TO postgres;

Связанные триггеры :

CREATE TRIGGER before_insert_update_isparent
  BEFORE INSERT OR UPDATE
  ON public.item
  FOR EACH ROW
  EXECUTE PROCEDURE public.isparent();

Ошибка при попытке вставить элемент 4 с позицией = 2

error position already exist

Более того, я пытаюсь вставить item4 с позицией = 2 , но другой элементуже положение = 2 , поэтому у меня есть ошибка.Но когда я хочу вставить элемент 4 с позицией, которая на данный момент не существует, у меня нет ошибки, и это вставка.

У меня возникает та же проблема, когда я хочу обновить или удалить элемент длякакая его позиция важна.

...