为大量更新声明游标的正确方法

时间:2010-02-21 22:51:34

标签: informix embedded-sql

我需要一些关于我的想法是否合适的建议。我有一个情况:

我需要对表格的每一行进行更新。更新中涉及一些逻辑。 逻辑非常简单,但需要为每一行完成。每一行都有可能得到更新。

目前,我正在考虑编写ESQL / C程序来执行此操作。我正在考虑将每一行加载到其中 等效C结构通过select for update游标,运行逻辑和提交。 HOLD关键字对游标的作用是什么?我对此的作用感到有点困惑。

这些更新将在系统停机期间完成。该表包含大约1.3亿行。它有 大约45列。大多数列都是SMALLINT和INTEGER类型。

我是否在正确的轨道上?建议欢迎。

数据库将是Informix(IDS版本11.50 FC6)

2 个答案:

答案 0 :(得分:2)

使这项工作的关键是在服务器中完成工作,而不是让服务器选择每一行,将其传递给客户端,然后从客户端接收数据。

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,我相信有空间可供使用,那么你可以一次完成所有工作。显然,这会“更新”每一行。

如果您决定必须在客户端进行(错误,但......),那么:

使用带有HOLD的SELECT游标,使其保持打开状态并在事务中正确定位。您启动一个事务,获取几千行,根据需要更新每个行。确保使用准备好的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;

未经测试的代码 - 使用风险自负!

答案 1 :(得分:0)

SPL是要走的路!...但我建议您复制表并首先测试您的批量更新。