1

我们正在开发一个迁移程序。DB中有近8000万条记录。代码如下:

static int mymigration(struct progargs *args) 
{
  exec sql begin declare section;
    const char *selectQuery;
    const char *updateQuery;
    long cur_start;
    long cur_end;
    long serial;
    long number;
    char frequency[3];
  exec sql end declare section;

    selectQuery = "select * from mytable where number >= ? and number <= ? for update of frequency ,status";
    updateQuery = "update mytable set frequency = ?, "
    " status = ? "
    " where current of my_cursor";

    cur_start= args->start;
    cur_end = args->end;

    exec sql prepare my_select_query from :selectQuery;
    /* Verify the sql code for error here */

    exec sql declare my_select_cursor cursor with hold for my_select_query;

    exec sql open my_select_cursor using :cur_start, :cur_end;
    /* Verify the sql code for error here */

    exec sql prepare my_update_query from :updateQuery;
    /* Verify the sql code for error here */        

    while (1)
    {
            number = 0;
            serial = 0;
            memset(frequency,0,sizeof(frequency));

            exec sql fetch my_select_cursor into number,:serial,:frequency;
            if (sqlca.sqlcode != SQL_OK)
                    break;            

            exec sql execute my_update_query using :frequency, :frequency;

    }      
    exec sql close my_select_trade_cursor;

}

在执行此操作时,我们收到错误消息“-255”。我们找到了一种添加工作和提交工作的解决方案。由于我们有大量数据,这可能会使事务日志混乱。

有没有其他解决方案可以解决这个问题?Informix 的 IBM 网站显示该用法是正确的。

提前感谢帮助。

谢谢, 马修 Liju

4

1 回答 1

0

错误 -255 是“不在事务中”。

我没有看到 BEGIN WORK(或 COMMIT WORK 或 ROLLBACK WORK)语句。

您需要在使用 FOR UPDATE 子句打开游标之前添加 BEGIN WORK。然后您需要决定是否定期提交以避免事务过长。您使用 FOR HOLD 游标的事实表明您曾考虑过使用子事务;如果你不打算这样做,你就不会使用那个子句。

请注意,Informix 有 3 种主数据库日志记录模式:

  • 未记录(不支持事务)
  • 记录(默认情况下,每个语句都是单例事务;显式 BEGIN WORK 启动由 COMMIT WORK 或 ROLLBACK WORK 终止的多语句事务)。
  • Logged MODE ANSI(稍微简单地说,您自动处于事务中;您需要显式 COMMIT 或 ROLLBACK 来终止事务,然后可以选择使用显式 BEGIN,但实际上不需要 BEGIN)。

根据您描述的症状,您有一个已记录但不是 MODE ANSI 数据库。因此,您必须显式编码 BEGIN WORK 语句。

于 2010-02-22T19:09:39.103 回答