更新包括自动增量列

时间:2012-10-31 17:25:33

标签: sql postgresql

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

有人可以帮忙吗?

3 个答案:

答案 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]
    )

或者,将其添加到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
    )

答案 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上的括号匹配。第二组包装子查询以便重复使用。