我的问题如下:我在postgresql数据库中插入或更新一行,需要修改此行中的一个字段。但是,当我插入新行以在其他表格上SELECT
JOIN
时,我需要知道新的序列号PK。
我现在陷入困境,因为我已经完成AFTER INSERT AND UPDATE
触发器以获得新的PK(kkw_block_id
)。我使用SELECT
得到了我需要的值,但之后我无法修改行中的值:使用AFTER INSERT AND UPDATE
修改NEW.value并且如果我执行UPDATE
在行上,我进入一个无限循环,触发器在触发器中调用...
CREATE TRIGGER tsvectorupdate
AFTER INSERT OR UPDATE
ON kkw_block
FOR EACH ROW
EXECUTE PROCEDURE kkw_search_trigger();
CREATE OR REPLACE FUNCTION kkw_search_trigger()
RETURNS trigger AS
$BODY$
DECLARE vector_en TEXT;
DECLARE vector_fr TEXT;
DECLARE vector_de TEXT;
BEGIN
-- I need the new serial PK(kkw_id) in the following section.
SELECT coalesce(modell_en, '') || ', ' || coalesce(bezeichnung_en,'') || ', ' || coalesce(kkw.kkw_name_en,'') || ', ' || coalesce(kkw_typ.typ_abr,'') || ', ' || coalesce(kkw_typ.typ_desc_en,'') || ', ' || coalesce(kkw_typ.typ_desc_short_en,'') INTO vector_en
FROM kkw_block
LEFT JOIN kkw ON NEW.kkw_id = kkw.kkw_id
LEFT JOIN kkw_typ ON NEW.kkw_typ_id = kkw_typ.kkw_typ_id
WHERE kkw_block_id = NEW.kkw_block_id;
-- I need to update a field of the newly created or updated row.
NEW.search_vector_en := to_tsvector('english', 'new test vector'); --- This doesn't work with 'AFTER UPDATE' trigger.
RETURN NULL;
END
$BODY$
有什么想法吗?
答案 0 :(得分:2)
删除PK的默认值并将其分配到 BEFORE 触发器中。您必须将现有的触发器从AFTER更改为BEFORE。
您可以从序列中分配PK:
NEW.kkw_block_id = nextval('your_sequence_name_here');
由于您对INSERT和DELETE都使用相同的函数,因此需要检查它是否为INSERT,然后才使用序列。我还检查了PK是否为空。我认为单独就足以在更新期间不会覆盖它。
IF (TG_OP = 'INSERT') AND NEW.kkw_block_id IS NULL THEN
NEW.kkw_block_id = nextval('your_sequence_name_here');
END IF;
只要此触发器适用于每个新行,这将是正常的,似乎是这种情况。这将允许您修改NEW,它将反映在表格中保存的数据中。
答案 1 :(得分:0)
我最终得到了以下解决方案。我做了一个BEFORE
触发器。问题是LEFT JOIN
引用了尚未存在新行的表。这不是理想的,但在这里:
CREATE TRIGGER tsvectorupdate
BEFORE INSERT OR UPDATE
ON kkw_block
FOR EACH ROW
EXECUTE PROCEDURE kkw_search_trigger();
CREATE TYPE kkw_type_record_type AS (typ_abr TEXT, typ_desc_en TEXT, typ_desc_short_en TEXT);
CREATE TYPE kkw_record_type AS (kkw_name_en TEXT);
CREATE OR REPLACE FUNCTION kkw_search_trigger()
RETURNS trigger AS
$BODY$
DECLARE kkw_rec kkw_record_type;
DECLARE kkw_typ_rec kkw_type_record_type;
DECLARE vector_en TEXT;
BEGIN
--- make a individual select instead of LEFT JOIN
SELECT kkw_name_en INTO kkw_rec.kkw_name_en
FROM kkw
WHERE kkw.kkw_id = NEW.kkw_id;
--- make a individual select instead of LEFT JOIN
SELECT typ_abr, typ_desc_en, typ_desc_short_en INTO kkw_typ_rec.typ_abr, kkw_typ_rec.typ_desc_en, kkw_typ_rec.typ_desc_short_en
FROM kkw_typ
WHERE kkw_typ.kkw_typ_id = NEW.kkw_typ_id;
vector_en := coalesce(NEW.modell_en, '') || ', ' || coalesce(NEW.bezeichnung_en,'') || ', ' || coalesce(kkw_rec.kkw_name_en,'') || ', ' || coalesce(kkw_typ_rec.typ_abr,'') || ', ' || coalesce(kkw_typ_rec.typ_desc_en,'') || ', ' || coalesce(kkw_typ_rec.typ_desc_short_en,'');
NEW.search_vector_en := to_tsvector('english', vector_en);
RETURN NEW;
END
$BODY$