0

我正在使用 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...

有人可以帮忙吗?

4

3 回答 3

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子句中是因为我怀疑这就是你想要的。行的顺序仍然是任意的。如果您想更好地控制分配的号码,您需要定义您想要的,然后采取不同的路线。

于 2012-10-31T20:01:08.770 回答
1

Tyler Eaves 是正确的,这个动作是不可取的。

但是,如果您坚持,这可能会有所帮助:

一旦你在列上有一个序列,你就不必nextval()SET语句中调用。只需将其保留,该列将自动递增。

UPDATE
    trk2
SET 
    (
        track_id = [track_id Value],
        track_point = [track_point Value]
    )

或者,包括它并将其设置为defaultnull

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
    )
于 2012-10-31T17:51:54.940 回答
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 上的括号匹配。第二组包装子查询以供重用。

于 2012-10-31T17:58:33.917 回答