Зацикливание и тестирование результата cte в триггере PostgreSQL - PullRequest
0 голосов
/ 27 января 2020

PostgreSQL 11.1

Я использую следующий триггер для получения «нового» номера диаграммы из таблицы chart_gap:

CREATE FUNCTION phoenix.next_chart()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF 
AS $BODY$
BEGIN
  -- Check for empty chart number
  IF NEW.chart_number is null or NEW.chart_number = 0 THEN
    WITH ins AS (
      SELECT chart_number
      FROM   chart_gap
      WHERE  pg_try_advisory_xact_lock(chart_number)
      LIMIT  1
    )
    DELETE FROM chart_gap c
    USING  ins i
    WHERE  i.chart_number = c.chart_number
    RETURNING i.chart_number INTO NEW.chart_number;
  END IF;

  RETURN NEW;
END;
$BODY$;

Как добавить тест, чтобы быть уверенным возвращаемый номер_карты еще не существует (в таблице пациентов), и если он существует, то заставить al oop получить следующий номер диаграммы в таблице и т. д. c .., пока не будет найден неиспользуемый номер_карты? То есть триггер должен возвращать новые и неиспользованные номера_карт.

TIA

Примечание: мои первоначальные мысли заключаются в том, чтобы использовать рекурсивный cte, но подумайте прямо вперед l oop может быть быстрее?

1 Ответ

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

Я ожидаю, что у вас есть веская причина не использовать значения последовательности.

Вы можете просто заключить блок кода в LOOP / END LOOP; и добавить SELECT count(*) в конце, чтобы проверить, есть строки с этим chart_number. Это должно быть защищено от условий гонки, если каждая транзакция проходит по этому маршруту.

Необходимо убедиться, что INSERT происходит в той же транзакции, пока удерживается консультативная блокировка.

В качестве альтернативы консультативной блокировке вы также можете

SELECT chart_number
FROM chart_gap
FOR UPDATE SKIP LOCKED
LIMIT 1;

, что может быть проще.

...