postgres,使用另一个表中的数据进行批量更新

Posted

技术标签:

【中文标题】postgres,使用另一个表中的数据进行批量更新【英文标题】:postgres, bulk update using data from another table 【发布时间】:2016-08-04 20:22:22 【问题描述】:

我有一个目标表(已填充数据)和另一个(源表),我需要将数据检索到第一个表中。

目标表

postgres=# select id,id_user from ttasks;
 编号 | id_user
--+---------
  1 |
  2 |
  3 |
  4 |
  5 |
(5 行)

source_table

postgres=# 从活跃的用户中选择 id;
  ID
------
 1011
 1012
 1013
 1014
(4 行)

我需要使用 ttasks 表中的 id 更新 ttasks 表的 id_user 列,因此 ttasks 的最终结果应该是:

# 更新后的预期结果 [select id, id_user from ttasks;] 编号 | id_user --+--------- 1 | 1011 2 | 1012 3 | 1013 4 | 1014 5 | 1011 (5 行)

我尝试过的(类似于 INSERT ... FROM ... 语句):

postgres=# update ttasks t1 set id_user = q1.id from (select id from tusers where active) q1 返回 t1.id,t1.id_user;
 编号 | id_user
--+---------
  1 | 1011
  2 | 1011
  3 | 1011
  4 | 1011
  5 | 1011
(5 行)

但是这个查询总是使用我的 q1 子查询中的第一个 id。

关于如何完成这项任务的任何想法、帮助甚至解决方案? 非常感谢!

附言这是我在这个社区的第一篇文章,所以如果我的问题中的某些内容不符合您的规则,请对我保持温和。

【问题讨论】:

update t1 set c1 = t2.c2 from t2 where t2.k1 = t1.k1; 语法;你不需要(非)标量子查询。 顺便说一句:您的子查询不相关。 (没有看到这个,因为我讨厌水平滚动) 嗨,也许我太盲目或太愚蠢了,但是,使用我对问题的案例研究,您能否使用我的表创建一个功能查询(ttasks t1 作为目标,tusers t2 作为源) ?我看不到也不知道我应该使用什么 pk (在您的语法描述中使用)。使用update ttasks t1 set id_user = t2.id from tusers t2 给了我相同的结果(在 ttasks t1 目标表中使用相同的 id_user),我的需要是 ttasks 中的 id_user 应该以递归方式填充,请检查我的问题中的# expected result 也许您省略了where t1.k1 = t2.k2 子句? (从问题中不清楚 source_table 的关键字段是什么) tusers 表(作为 source_table)有一列:id(也作为 pk)和三行,id 列的值如下:1,2,3 【参考方案1】:

最后,在我的一位朋友告诉我并非所有内容都可以以“保持愚蠢简单”的方式进行编码之后,我编写了一个 plpqsql (PL/PGSQL) 函数,该函数可以为我完成这项工作,而且还允许在里面使用一些高级过滤器。

创建或替换函数 assign_workers_to_tasks(i_workers_table regclass, i_workers_table_tc text, i_tasks_table regclass, i_tasks_table_tc text, i_workers_filter text DEFAULT ''::text, i_tasks_filter text DEFAULT ''::text) 返回无效 $身体$ 声明工人 int[]; i 整数; total_workers 整数; r 记录; get_tasks 文本; 开始 i_workers_filter := '其中 '||nullif(i_workers_filter,''); i_tasks_filter := '其中 '||nullif(i_tasks_filter,''); EXECUTE format('select array_agg(%s) from (select %s from %s %s order by %s) q', i_workers_table_tc, i_workers_table_tc,i_workers_table, i_workers_filter,i_workers_table_tc) INTO工人; --available [过滤] 工人 total_workers := coalesce(array_length(workers,1),0); --可用的[过滤]工人总数 如果 total_workers = 0 那么 EXECUTE format('update %s set %s=null %s', i_tasks_table, i_tasks_table_tc, i_tasks_filter); 返回; 万一; 我:=1; get_tasks := format('select * from %s %s',i_tasks_table,i_tasks_filter); --[过滤] 任务 FOR r IN EXECUTE (get_tasks) 循环 EXECUTE format('update %s set %s=%s where id = %s', i_tasks_table, i_tasks_table_tc, workers[i],r.id); 我:=我+1; 如果 i>total_workers 那么 i := 1;万一; 结束循环; 返回; 结尾; $身体$ 语言 plpgsql 易失性 费用 100; ALTER FUNCTION assign_workers_to_tasks(regclass, text, regclass, text, text, text) postgres 的所有者;

并完成我自己的问题:

select assign_workers_to_tasks('tusers','id','ttasks','id_user','active');

【讨论】:

以上是关于postgres,使用另一个表中的数据进行批量更新的主要内容,如果未能解决你的问题,请参考以下文章

mysql 数据库表批量更新,需要set的数据是另一个表中的字段

mysql 数据库表批量更新,需要set的数据是另一个表中的字段

使用 Apache Airflow 更新和维护 postgres 表

如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?

Postgres 批量数据导入和填充相关数据

使用返回值更新列