完成这项工作的关键是在服务器中完成工作,而不是让服务器选择每一行,将其传递给客户端,然后从客户端接收数据。
UPDATE YourTable
SET y = (CASE WHEN z > x THEN p ELSE y)
WHERE key_column BETWEEN lo_val AND hi_val;
复杂的部分可能会将工作拆分为可管理的子事务;这就是“lo_val .. hi_val”条件的含义。如果您的逻辑日志足够大,可以处理所有 1.3 亿行正在更新的 [大约 (2 * (行大小 + X) * 行数),我相信 X 的值大约是 20] 有剩余空间,那么您可以一次完成。显然,这会“更新”每一行。
如果您决定必须在客户端执行此操作(一个错误,但是...),那么:
您将 SELECT 游标与 HOLD 一起使用,以便它在事务中保持打开并正确定位。你开始一个事务,获取几千行,根据需要更新每一行。确保您使用的是准备好的 UPDATE 语句;也许您使用 WHERE CURRENT OF 条件。
您是否建议将更新作为游标的一部分放在存储过程中?
不,尽管您可以在存储过程中执行此操作。这部分取决于您是否要定期执行此操作;如果是这样,也许存储过程是一个好主意,但我不会一次性练习。
这取决于您将如何确定 lo_val 和 hi_val。我可能会使用 I4GL(因为我精通它),然后我希望准备 UPDATE 语句(用问号代替“lo_val”和“hi_val”),然后我希望执行它多次,每次形成一个单一的语句事务。所以,如果你决定从 000000..099999、100000..199999 开始使用 lo_val..hi_val 范围......那么你会迭代:
for i = 0 to 10000000 step 100000
let j = i + 99999
execute p_update using i, j
end for
在 I4GL 中,您绝对不需要使用准备好的语句。如果您有 IDS 11,则可以在 SPL 中准备语句。在早期版本中,并且没有太大的性能影响(我怀疑您是否可以可靠地测量它),您可以简单地使用:
CREATE PROCEDURE update_your_table()
DEFINE lo_val, hi_val INTEGER;
FOR lo_val = 0 TO 1000000 STEP 100000
LET hi_val = lo_val + 99999;
UPDATE YourTable
SET y = (CASE WHEN z > x THEN p ELSE y)
WHERE key_column BETWEEN lo_val AND hi_val;
END FOR;
END PROCEDURE;
未经测试的代码 - 使用风险自负!