Триггерная функция POSTGRESQL pl / pgsql возвращает ноль при вставке - PullRequest
0 голосов
/ 27 января 2012

У меня есть таблица pg, как это:

CREATE TABLE order_status_history (
order_id integer NOT NULL,
status character varying NOT NULL,
sequence integer DEFAULT 1 NOT NULL,
date_status timestamp with time zone DEFAULT now() NOT NULL,
record_state character varying(12) DEFAULT 'ACTIVE'::character varying NOT NULL
);

с составным PK на order_id и sequence.По сути, столбец состояния представляет собой значение автоинкремента, начинающееся с 1, для каждого отдельного идентификатора заказа.Итак, если order_id 2 уже имеет две строки, последовательности будут 1 и 2, а для новой строки последовательность должна быть 3. Я пытаюсь использовать триггер для реализации этого поведения перед вставкой, но когда я пытаюсьвставить первую строку для нового order_id (то есть триггер не должен изменять строку до вставки), я получаю сообщение об ошибке для PG.говоря, что он не может вставить NULL в последовательность.Я не вижу, как моя функция триггера будет возвращать NULL, но мой pl / sql не очень хорош, поэтому я уверен, что это что-то простое ... Функция триггера ниже, спасибо.

Ответы [ 2 ]

2 голосов
/ 27 января 2012

Если в order_status_history нет ничего для этого order_id, то MAX(sequence) будет нулевым. Используйте COALESCE(MAX(sequence),0), чтобы установить значение по умолчанию 1.

Вы можете просто написать:

NEW.sequence := (SELECT COALESCE(MAX(sequence),0) FROM /* etc.. */) + 1;

Вы должны действительно заблокировать строку заказа в эксклюзивном режиме, прежде чем делать это, чтобы позволить этому работать с несколькими транзакциями, одновременно вставляемыми в историю для одного и того же заказа. То есть:

SELECT 1 FROM orders WHERE orders.order_id = NEW.order_id FOR UPDATE;
1 голос
/ 27 января 2012

max(sequence) всегда FOUND, но может быть NULL, если нет данных. В этом случае ваш NEW.sequence := seq_no + 1 делает его все еще NULL. IF seq_no IS NOT NULL звучит как более подходящее условие.

...