Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何从触发器中的多行更新生成一个新行?_Sql_Postgresql_Database Design_Triggers - Fatal编程技术网

Sql 如何从触发器中的多行更新生成一个新行?

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

基本上,我有几个不同的表,它们共享一个数组字段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 
   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;