通过增加序列号来更新 Informix 数据库中的行

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

我在 Informix 数据库中有一个表,假设它名为 store,看起来像:

序列号 store_seq
381-15 82600
381-15 82610
381-15 82640
381-15 82650
381-15 82680
381-114-1 82690

我必须更新serial_num,以便数字像这样增量更新:

序列号 store_seq
381-15-1 82600
381-15-2 82610
381-15-3 82640
381-15-4 82650
381-15-5 82680
381-114-1 82690

评论转录到问题中:

我尝试创建一个过程:

CREATE PROCEDURE update_store()
    DEFINE counter INTEGER;
    DEFINE temp_serial_num CHAR(20);
    FOREACH cur1 FOR
        SELECT serial_num INTO temp_serial_num FROM store WHERE serial_num = '381-15'
        LET counter = 0;
        WHILE counter < (SELECT COUNT(*) FROM store WHERE serial_num = '381-15')
            LET counter = counter + 1;
            UPDATE store
               SET serial_num = temp_serial_num || '-' || counter::CHAR
             WHERE CURRENT OF cur1;
         END WHILE;
     END FOREACH;
END PROCEDURE;

所有 381-15 号码中的结果是 381-15-5。

注意:

serial_num
列是 CHAR(16) 列;
store_seq
是一个 INTEGER 列。

informix
1个回答
0
投票

修复注释中的代码与表的架构之间的一些名称不匹配后,我发现您的存储过程不会更改数据。然而,这部分是因为在附加新计数器之前,您没有使用 TRIM 删除

serial_num
中的尾随空白。如果
serial_num
列是 VARCHAR 而不是 CHAR,则 TRIM 就不是必需的,但除了稍微减慢速度之外,它不会有任何害处。

我在表中添加了 Informix SERIAL 列

rec_num

DROP TABLE IF EXISTS store;

CREATE TABLE store
(
    recnum       SERIAL(1000) NOT NULL PRIMARY KEY,
    serial_num   CHAR(16) NOT NULL,
    store_seq    INTEGER NOT NULL
);

INSERT INTO store VALUES(0, '381-15', '82600');
INSERT INTO store VALUES(0, '381-15', '82610');
INSERT INTO store VALUES(0, '381-15', '82640');
INSERT INTO store VALUES(0, '381-15', '82650');
INSERT INTO store VALUES(0, '381-15', '82680');
INSERT INTO store VALUES(0, '381-114-1', '82690');

修改后的程序将

serial_num
作为参数来修复:

DROP PROCEDURE IF EXISTS update_store;

CREATE PROCEDURE update_store(snum CHAR(16))
    DEFINE counter INTEGER;
    DEFINE temp_serial_num CHAR(20);

    TRACE ON;
    FOREACH cur1 FOR
        SELECT serial_num INTO temp_serial_num FROM store WHERE serial_num = snum
        LET counter = 0;
        WHILE counter < (SELECT COUNT(*) FROM store WHERE serial_num = snum)
            LET counter = counter + 1;
            UPDATE store
               SET serial_num = TRIM(temp_serial_num) || '-' || counter::CHAR
             WHERE CURRENT OF cur1;
         END WHILE;
     END FOREACH;
END PROCEDURE;

运行时,我得到输出:

recnum 序列号 store_seq
1005 381-114-1 82690
1003 381-15-1 82650
1004 381-15-1 82680
1002 381-15-2 82640
1001 381-15-3 82610
1000 381-15-4 82600

这会更改表中的数据,但由于未应用排序,因此行不会按照

store_seq
值的顺序更新,这似乎是所需的结果。

重写的程序处理排序问题:

DROP PROCEDURE IF EXISTS update_store;

CREATE PROCEDURE update_store(snum CHAR(16))

    DEFINE counter INTEGER;
    DEFINE old_serial_num CHAR(20);
    -- DEFINE new_serial_num CHAR(20);
    DEFINE old_store_seq INTEGER;

    -- TRACE ON;

    LET counter = 0;
    FOREACH cur1 FOR
        SELECT serial_num, store_seq
      INTO old_serial_num, old_store_seq
      FROM store
     WHERE serial_num = snum
     ORDER BY serial_num, store_seq
        LET counter = counter + 1;
        -- LET new_serial_num = TRIM(old_serial_num) || '-' || counter;
        UPDATE store
           SET serial_num = TRIM(old_serial_num) || '-' || counter
         WHERE serial_num = old_serial_num AND store_seq = old_store_seq;
     END FOREACH;

END PROCEDURE;

new_serial_num
变量(和
TRACE ON;
语句)帮助识别缺失的 TRIM 问题。

这会产生输出:

recnum 序列号 store_seq
1005 381-114-1 82690
1000 381-15-1 82600
1001 381-15-2 82610
1002 381-15-3 82640
1003 381-15-4 82650
1004 381-15-5 82680

当游标上有 ORDER BY 子句时,无法将

WHERE CURRENT OF cur1
子句应用于 UPDATE。这就是为什么处理过程会通过
serial_num
store_req
来识别要更新的行。

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