在 PostgreSQL 触发器中循环和测试 cte 的结果
Looping and testing the result of a cte in a PostgreSQL trigger
PostgreSQL 11.1
我正在使用以下触发器从 chart_gap table 中获取 "new" 图表编号:
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$;
我如何添加测试以确保 returned 的 chart_number 不存在(在 table 患者中),如果存在,则强制循环获取 table 中的下一个图表编号,等等,直到找到未使用的 chart_number?也就是说,触发器必须 return new 并且 unused chart_numbers.
TIA
注意:我最初的想法是使用递归 cte,但认为直接循环可能更快?
我希望您有充分的理由不使用序列值。
您可以简单地用 LOOP
/ END LOOP;
包围代码块,并在末尾添加 SELECT count(*)
以测试是否有包含 chart_number
的行。只要每笔交易都采用该路线,那应该不会出现竞争条件。
您必须确保 INSERT
在同一事务中发生,同时持有建议锁。
作为咨询锁的替代方案,您还可以
SELECT chart_number
FROM chart_gap
FOR UPDATE SKIP LOCKED
LIMIT 1;
哪个可能更简单。
PostgreSQL 11.1
我正在使用以下触发器从 chart_gap table 中获取 "new" 图表编号:
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$;
我如何添加测试以确保 returned 的 chart_number 不存在(在 table 患者中),如果存在,则强制循环获取 table 中的下一个图表编号,等等,直到找到未使用的 chart_number?也就是说,触发器必须 return new 并且 unused chart_numbers.
TIA
注意:我最初的想法是使用递归 cte,但认为直接循环可能更快?
我希望您有充分的理由不使用序列值。
您可以简单地用 LOOP
/ END LOOP;
包围代码块,并在末尾添加 SELECT count(*)
以测试是否有包含 chart_number
的行。只要每笔交易都采用该路线,那应该不会出现竞争条件。
您必须确保 INSERT
在同一事务中发生,同时持有建议锁。
作为咨询锁的替代方案,您还可以
SELECT chart_number
FROM chart_gap
FOR UPDATE SKIP LOCKED
LIMIT 1;
哪个可能更简单。