使用案例表达式的Fetch First

问题描述 投票:0回答:1

DB2 UDB v11.x.

是否可以在使用CASE的UPDATE查询中使用FETCH FIRST? 我有点明白为什么它不工作,但想知道是否有一种方法,例如。

db2 "UPDATE mytable SET cstate = CASE WHEN cstate = 801 THEN cstate = 1 AND rstate = 1 WHEN cstate = 804 THEN cstate = 4 AND rstate = 4 END FETCH FIRST 20000 ROWS ONLY"

这样做的结果是一次只能修改一条记录。

我试过了。

db2 "UPDATE mytable SET cstate = CASE WHEN cstate = (SELECT cstate FROM mytable WHERE cstate = 801 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 1 AND rstate = 1 WHEN cstate = (SELECT cstate FROM mytable WHERE cstate = 804 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 4 AND rstate = 4 END"

这得到的结果是:

SQL0811N  The result of a scalar fullselect, SELECT INTO statement, or VALUES
INTO statement is more than one row

有什么方法可以做到这一点?希望不要把它拆分开来,在表中重申两次(或者一次只能做一次更新)。

sql db2
1个回答
1
投票

这将是最简单的方法

UPDATE
(   SELECT * FROM
    (   SELECT
            cstate
        ,   rstate
        ,   CASE WHEN cstate = 801 THEN 1 WHEN cstate = 804 THEN 4 ELSE cstate END new_cstate
        ,   CASE WHEN cstate = 801 THEN 1 WHEN cstate = 804 THEN 4 ELSE rstate END new_rstate
        FROM
            mytable
    )
    WHERE 
        cstate IS DISTINCT FROM new_cstate
    OR  rstate IS DISTINCT FROM new_rstate
    FETCH FIRST 20000 ROWS ONLY
)
SET cstate = new_cstate
,   rstate = new_rstate

只需继续运行,直到没有更新记录为止。


0
投票

在处理子查询时,请使用IN子句,你可能在另一个表中有多个值。

"UPDATE mytable SET cstate = CASE WHEN cstate in (SELECT cstate FROM mytable WHERE cstate = 801 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 1 AND rstate = 1 WHEN cstate in (SELECT cstate FROM mytable WHERE cstate = 804 FETCH FIRST 20000 ROWS ONLY) THEN cstate = 4 AND rstate = 4 END"

0
投票

你可以试试 positioned update 与提交后N个这样的更新。

--#SET TERMINATOR @
BEGIN
  DECLARE V_BATCH_COUNT INT DEFAULT 0;

  FOR V AS C1 CURSOR WITH HOLD FOR
    SELECT 1 DUMMY FROM mytable FOR UPDATE OF cstate, rstate
  DO
    UPDATE mytable
    SET 
      cstate = ...
    , rstate = ...
    WHERE CURRENT OF C1;

    SET V_BATCH_COUNT = V_BATCH_COUNT + 1;
    IF V_BATCH_COUNT = 20000 THEN 
      COMMIT;
      SET V_BATCH_COUNT = 0;
    END IF;
  END FOR;
  IF V_BATCH_COUNT <> 0 THEN
    COMMIT;
  END IF;
END
@

它的工作速度很慢,但可以帮助你避免长时间的过度锁定:)

© www.soinside.com 2019 - 2024. All rights reserved.