如何从 UPDATE 子查询函数访问行值?

1 postgresql subquery update

我需要UPDATE这样使用:

update offer set (bank, bank_id) = (cost, gid)
from (
select cost, osm_points.gid from pgr_kdijkstraCost(
  'SELECT gid as id, source, target, walk_cost as cost FROM ways',
  offer.vertice_id,
  array(select vertice_id from osm_points where super_type = 'bank'),
  false,false)
join osm_points on id2 = vertice_id
where cost != -1
and osm_points.super_type = 'bank'
order by cost
limit 1)t ;
Run Code Online (Sandbox Code Playgroud)

但我得到以下信息:

错误:对表“offer”的 FROM 子句条目的引用无效

提示:表“offer”有一个条目,但不能从查询的这部分引用它。

先感谢您

Dan*_*ité 5

当使用这种形式的查询时:UPDATE a SET columns=values FROM b WHERE ...b子查询的计算独立于a,并且查询末尾的 WHERE 块应该连接 和 的ab

问题中的查询尝试在子查询内部连接,而不是在最上层的 WHERE 子句中连接(实际上它没有这样的 WHERE 子句),但这是不允许的,这就是错误消息所指示的。

使用相关子查询更新每一行的 SQL 标准方法是:

UPDATE a SET (col1,col2) =
   (SELECT val1,val2 FROM b WHERE expression-needing-values-from-a)
Run Code Online (Sandbox Code Playgroud)

但在旧版本的 PostgreSQL(9.4 或之前)中,手册明确告知这种形式没有实现。从9.5开始,实现了。

使用 postgres 9.4 模拟它的典型方法是在子查询中使用表的副本a,并在上层的 WHERE 子句中连接回更新的表,如下所示:

 UPDATE a SET (col1,col2)=(s.col1,s.col2)
  FROM (SELECT a2.ctid,col1,col2 AS ctid_of_row FROM b, a AS a2 WHERE...) AS s
   WHERE s.ctid_of_row = a.ctid;
Run Code Online (Sandbox Code Playgroud)

知道这ctid系统伪列,指示行版本在其表中的物理位置。或者,如果有主键,则可以使用主键。

在您的情况下,转换并不明显,因为您的子查询旨在仅生成一行及其ORDER BY... LIMIT 1末尾。应该重新设计它以在单个结果集中生成所有目标行,大概(verticeid,cost,gid)cost根据gid确定的offer.verticeid