我正在使用PostgreSQL,我想更新一个包含自动编号列ID的表。我知道这可能非常简单,但我做过类似的事情;
CREATE SEQUENCE SEQ_ID
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10
update trk2
set (id, track_id, track_point) =
(select nextval('seq_id'), trk1.track_fid, trk1.wkb_geometry
from track_points_1 as trk1
where track_fid = 0)
问题是它给了我以下错误(代码重新格式化):
ERROR: syntax error at or near "select"
LINE 3: set (id, track_id, track_point)=(select nextval('seq_id'), t...
有人可以帮忙吗?
答案 0 :(得分:2)
您的查询在几个地方被破坏了。它可能看起来像这样:
UPDATE trk2
SET (id, track_id, track_point) =
(next_id, x.track_fid, x.wkb_geometry)
FROM (
SELECT id
,nextval('seq_id') AS next_id
,track_fid
,wkb_geometry
FROM track_points_1
WHERE track_fid = 0
) x
WHERE trk2.id = x.id; -- adapt to your case
或更简单(更好的语法):
UPDATE trk2
SET (id, track_id, track_point) =
(nextval('seq_id'), x.track_fid, x.wkb_geometry)
FROM track_points_1 x
WHERE x.track_fid = 0
AND trk2.id = x.id; -- adapt to your case
如果您确实需要更改表格中的每一行,则UPDATE
没有WHERE
子句才有意义。否则它是错误的或至少是次优的。
当您从另一个表中检索值时,如果您没有添加将目标与源连接的CROSS JOIN
子句,则会在目标和源之间获得WHERE
- 这意味着目标表的每一行都将使用源表中的每一行进行更新。这可能需要很长时间并导致任意结果。最后UPDATE
获胜。简而言之:这几乎总是完全无稽之谈,而且非常昂贵。
在我的示例中,我通过id
列链接目标和来源。你必须用适合你情况的东西替换它。
您可以在SET
中的一个UPDATE
子句中分配多个值,但您只能从相关的子选择表达式返回单个值。因此,严格不可能在具有多个值的SET
子句中进行子选择。
您的初始语法错误来自您的子选择周围缺少一对括号。但是添加它只能揭示上面提到的错误。
根据您的目标,您可以直接在子查询或nextval('seq_id')
子句中包含SET
。这可能会导致非常不同的结果,尤其是当子查询中的行未在UPDATE
中使用时。
我把它放在SET
条款中因为我怀疑,这就是你想要的。行的顺序仍然是任意的。如果您想要更多地控制分配的数字,您需要定义您想要的内容,然后采用不同的路线。
答案 1 :(得分:1)
Tyler Eaves是正确的,此操作不可取。
但是,如果你坚持,这可能会有所帮助:
在列上有序列后,您无需在nextval()
语句中调用SET
。只需将其保留,列就会自动增加。
UPDATE
trk2
SET
(
track_id = [track_id Value],
track_point = [track_point Value]
)
或者,将其添加到default
或null
UPDATE
trk2
SET
(
id = default,
track_id = [track_id Value],
track_point = [track_point Value]
)
使用您的示例:
UPDATE
trk2
SET
(
track_id,
track_point
) = (
SELECT
trk1.track_fid,
trk1.wkb_geometry
FROM
track_points_1 AS trk1
WHERE
track_fid = 0
)
答案 2 :(得分:0)
我认为你需要在SET子句的RHS上使用第二组括号:
UPDATE trk2
SET (id, track_id, track_point) =
((SELECT nextval('seq_id'), trk1.track_fid, trk1.wkb_geometry
FROM track_points_1 as trk1
WHERE track_fid = 0));
第一组括号与SET子句的LHS上的括号匹配。第二组包装子查询以便重复使用。