Подзапрос, возвращающий null из count. (PostgreSQL) - PullRequest
0 голосов
/ 28 января 2020

PostgreSQL 11.1

ОШИБКА: нулевое значение в столбце "chart_number" нарушает ненулевое ограничение

ОК, здесь я явно что-то не так делаю, но я не вижу этого.

Таблица пациентов имеет

COLUMN chart_number integer NOT NULL;

Ошибка исходит из триггера:

CREATE OR REPLACE FUNCTION phoenix.next_chart()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF 
AS $BODY$
BEGIN
  IF NEW.chart_number is null or NEW.chart_number = 0 THEN
        LOOP
            EXIT WHEN 0 = (select count(*) from patients where chart_number = NEW.chart_number);

            SELECT nextval('chartsequence') INTO NEW.chart_number;
        END LOOP;       
  END IF;

  RETURN NEW;
END;
$BODY$; 

Последовательность "последовательность последовательности" определена обычным способом:

CREATE SEQUENCE chartsequence START 1;

Я пытаюсь сделать вывод l oop, когда значение последовательности НЕ существует у пациентов в таблице.

Любая помощь наиболее ценится , ТИА

1 Ответ

1 голос
/ 28 января 2020

Если new.chart_number равно NULL, то

SELECT count(*)
       FROM patients p
       WHERE p.chart_number = new.chart_number

всегда возвращает 0, поскольку в patients не может быть строк с chart_number, равным NULL, поскольку столбец определен NOT NULL, не говоря уже о том, что = не будет работать на NULL, но нуждается в операции IS NULL.

Это означает, что условие

0 = (SELECT count(*)
            FROM patients p
            WHERE p.chart_number = new.chart_number)

всегда true в таких случаях, что, в свою очередь, означает, что вы немедленно выходите из l oop в начале его первой итерации, но до того, как new.chart_number даже будет изменен один раз. Остается NULL. И поскольку он не должен быть NULL, возникает ошибка.

Я думаю, вам просто нужно изменить порядок операторов в теле l oop. Сначала установите new.chart_number в соответствии с последовательностью, затем проверьте, не существует ли она. Говоря о существовании, вы также можете использовать EXISTS здесь и только оператор присваивания вместо SELECT ... INTO.

...
IF new.chart_number IS NULL
    OR new.chart_number = 0 THEN
  LOOP
    new.chart_number := nextval('chartsequence');
    EXIT WHEN NOT EXISTS (SELECT *
                                 FROM patients p
                                 WHERE p.chart_number = new.chart_number);
  END LOOP;       
END IF;
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...