Sql 如何从触发器中的多行更新生成一个新行?
基本上,我有几个不同的表,它们共享一个数组字段job_id,每个表都有自己的状态,也是一个整数。在作业表上,id是其主键 Postgres 12.5版 表1: 表格作业: 我的触发功能:Sql 如何从触发器中的多行更新生成一个新行?,sql,postgresql,database-design,triggers,Sql,Postgresql,Database Design,Triggers,基本上,我有几个不同的表,它们共享一个数组字段job_id,每个表都有自己的状态,也是一个整数。在作业表上,id是其主键 Postgres 12.5版 表1: 表格作业: 我的触发功能: CREATE OR REPLACE FUNCTION new_job_id_table1() RETURNS trigger LANGUAGE plpgsql AS $function$ BEGIN if new.status= 3 and new.jobs_ids = '{}' then ins
CREATE OR REPLACE FUNCTION new_job_id_table1()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
if new.status= 3 and new.jobs_ids = '{}' then
insert into job (description, type_id)
select 'automated jobid with id=' || new.id, 1;
new.jobs_ids := array[ max(b.id) ] from job b
where new.jobs_ids = '{}' and b.type_id = 1;
end if;
RETURN NEW;
END;
$function$;
触发器,设置为在更新之前运行:
create trigger job_id_trigger_table1
before update of status on table1
for each row execute function new_job_id_table1();
用户通过qgis更新内容,但通常是:
update table1 set status = 3 where id = $whatever_id_they_picked;
它在作业表中创建一个新条目,并将该id分配给表1中更新的行
如果用户将表1中的一行更新为状态3,则可以正常工作。但是,当用户一次更新多行时,它不会执行任何操作。
如果一次更新多行,我只想为表1中的多行生成一个作业id,而不是当前的多行
如何使触发器与多行更新一起工作?设置
首先,我简化并改进了您的测试设置:
创建表1
id串行主键
,jobs_id int4[]
,状态int4非空-!
;
-放下工作台;
创建表作业
id串行主键
,type_id int NOT NULL默认值1-缺失
,description varchar
,已在默认时间创建_
,已在默认时间修改_
;
同时调整你的原始触发器以了解发生了什么。如果以下解决方案不适合您,您可以将其用作备用方案:
小提琴
解决方案
使用
触发功能:
CREATE OR REPLACE FUNCTION new_job_id_table1()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
if new.status= 3 and new.jobs_ids = '{}' then
insert into job (description, type_id)
select 'automated jobid with id=' || new.id, 1;
new.jobs_ids := array[ max(b.id) ] from job b
where new.jobs_ids = '{}' and b.type_id = 1;
end if;
RETURN NEW;
END;
$function$;
创建或替换功能作业\u id\u触发器\u表1
返回触发器
语言plpgsql AS
$func$
开始
以sel为例
选择n.id
从最新的
使用id加入更新的\u旧o-从不更新id!
其中n.status=3
和o.3状态
和n.jobs_id='{}'
,ins AS
在职务说明中插入,键入\u id
选择“id的自动作业id”| |数组_aggs.id::text,1
从sel s
计数*>0-如果没有匹配行,则跳过所有
返回id
更新表1 t
设置作业\u id=数组[i.id]
来自sel s,ins i
其中t.id=s.id;
返回NULL;-后触发
终止
$func$;
触发:
创建触发器作业\u id\u触发器\u表1
更新表1后
将旧表引用为已更新的旧表
更新后的新表
对于每个语句
当pg_触发器_深度=0时-仅立即更新!
执行功能作业\u id\u触发器\u表1;
小提琴
这将在作业中为任意数量的符合条件的用户创建一行!行在单个命令中更新
我检查新旧转换关系,以确保只有在更新中实际更改状态后才会触发。如果不需要,请删除旧关系
不幸的是,我们不能立即限制状态更新,因为:
该标准允许转换表与特定列一起使用
UPDATE触发器,但在
转换表取决于触发器的列列表。这是
当前未由PostgreSQL实现
我使用id将旧的转换关系连接到新的转换关系。在更新table1.id后,创建一个可能出错的角案例。通常情况下,这种情况不会发生,但要采取预防措施
为了避免更新循环,我在触发器中添加了当pg_trigger_depth=0时。见:
该函数仅使用一条DDL语句和数据修改CTE。应该是最有效的。见:
如果未找到符合条件的行,则跳过插入和更新。什么也没发生
我在fiddle中添加了两个测试,以验证它是否如广告所示工作。请提供一个有效的CREATE TABLE脚本,显示数据类型和约束,而不是关于所述表的文字。第一个是非常有用的,第二个不是那么有用。始终是您的Postgres版本。@ErwinBrandstetter我已经编辑了opI,请参阅函数定义,但没有触发器定义。此外,用户更新功能的定义不明确。什么特征?使现代化插入到底什么是同时发生的?用同一个命令?“太模糊了。”欧文·兰德斯特特再次编辑
update table1 set status = 3 where id = $whatever_id_they_picked;