更新 Informix 中的多行 SQL
Update multiple rows in Informix SQL
我正在尝试为存储序列更新大约 20k 行
数据如下
Table: lc_f
-------------------
|Loc |store_seq|
|BGB011 |82600 |
|BGB012 |82610 |
|BGB021 |82640 |
|BGB022 |82650 |
|BGB031 |82680 |
|BGB032 |82690 |
---------------------
我想用一个更新查询更新所有 store_seq,增量为 2(为简单起见,我将从 1 开始)
这是我希望它之后的样子。
-------------------
|Loc |store_seq|
|BGB011 |00001 |
|BGB012 |00003 |
|BGB021 |00005 |
|BGB022 |00007 |
|BGB031 |00009 |
|BGB032 |00011 |
---------------------
任何帮助都会非常有帮助。
可能有更好的方法来做到这一点,但这个 simple-minded 暴力存储过程应该可以完成这项工作:
CREATE PROCEDURE update_lc_f_sequence_numbers()
DEFINE v_loc CHAR(10);
DEFINE v_seq INTEGER;
BEGIN WORK;
SELECT Loc FROM lc_f INTO TEMP t_lc_f_sequence_numbers;
LET v_seq = 1;
FOREACH SELECT Loc INTO v_loc FROM t_lc_f_sequence_numbers ORDER BY Loc
UPDATE lc_f SET Store_Seq = v_seq WHERE Loc = v_loc;
LET v_seq = v_seq + 2;
END FOREACH;
DROP TABLE t_lc_f_sequence_numbers;
COMMIT WORK;
END PROCEDURE;
任何处理的棘手部分是将序列号应用于正确排序的 'loc' 值。这会在临时 table 中创建 loc 值的副本(最初,我使用 t
,但这并不是很明显),然后按顺序选择值并 运行s 更新每行语句一次,每次调整序号。这不会像在客户端程序中那样对性能造成破坏,因为数据不是在客户端和服务器之间发送的;都在服务器中可用。
事务语句的使用应慎重考虑。如果数据库未记录,则必须省略它们。如果数据库已记录,那么您可能已经处于事务中,在这种情况下 BEGIN WORK 将失败。您可以使用异常处理来识别这一点并继续,留下任何启动事务的代码来完成它(因此如果 BEGIN WORK 失败,则不会执行 COMMIT WORK)。您可以考虑使用 SAVEPOINT 而不是完整的交易。您可能需要某种事务处理,以便在处理过程中出现问题时回滚更改。
可能有一种方法可以使用 OLAP 函数和 ROW_NUMBER() — 或者也许是 ROW_NUMBER() * 2 - 1
— 但我不太确定如何去做。这应该或多或少适用于您可以使用的任何 Informix 版本; OLAP 函数仅在 IDS 12.10 中可用(可能在以后的 11.70 修复包中可用)。
注意:代码不是 运行 — 但存储过程已成功创建,即使数据库不包含 table lc_f
.
我正在尝试为存储序列更新大约 20k 行
数据如下
Table: lc_f
-------------------
|Loc |store_seq|
|BGB011 |82600 |
|BGB012 |82610 |
|BGB021 |82640 |
|BGB022 |82650 |
|BGB031 |82680 |
|BGB032 |82690 |
---------------------
我想用一个更新查询更新所有 store_seq,增量为 2(为简单起见,我将从 1 开始)
这是我希望它之后的样子。
-------------------
|Loc |store_seq|
|BGB011 |00001 |
|BGB012 |00003 |
|BGB021 |00005 |
|BGB022 |00007 |
|BGB031 |00009 |
|BGB032 |00011 |
---------------------
任何帮助都会非常有帮助。
可能有更好的方法来做到这一点,但这个 simple-minded 暴力存储过程应该可以完成这项工作:
CREATE PROCEDURE update_lc_f_sequence_numbers()
DEFINE v_loc CHAR(10);
DEFINE v_seq INTEGER;
BEGIN WORK;
SELECT Loc FROM lc_f INTO TEMP t_lc_f_sequence_numbers;
LET v_seq = 1;
FOREACH SELECT Loc INTO v_loc FROM t_lc_f_sequence_numbers ORDER BY Loc
UPDATE lc_f SET Store_Seq = v_seq WHERE Loc = v_loc;
LET v_seq = v_seq + 2;
END FOREACH;
DROP TABLE t_lc_f_sequence_numbers;
COMMIT WORK;
END PROCEDURE;
任何处理的棘手部分是将序列号应用于正确排序的 'loc' 值。这会在临时 table 中创建 loc 值的副本(最初,我使用 t
,但这并不是很明显),然后按顺序选择值并 运行s 更新每行语句一次,每次调整序号。这不会像在客户端程序中那样对性能造成破坏,因为数据不是在客户端和服务器之间发送的;都在服务器中可用。
事务语句的使用应慎重考虑。如果数据库未记录,则必须省略它们。如果数据库已记录,那么您可能已经处于事务中,在这种情况下 BEGIN WORK 将失败。您可以使用异常处理来识别这一点并继续,留下任何启动事务的代码来完成它(因此如果 BEGIN WORK 失败,则不会执行 COMMIT WORK)。您可以考虑使用 SAVEPOINT 而不是完整的交易。您可能需要某种事务处理,以便在处理过程中出现问题时回滚更改。
可能有一种方法可以使用 OLAP 函数和 ROW_NUMBER() — 或者也许是 ROW_NUMBER() * 2 - 1
— 但我不太确定如何去做。这应该或多或少适用于您可以使用的任何 Informix 版本; OLAP 函数仅在 IDS 12.10 中可用(可能在以后的 11.70 修复包中可用)。
注意:代码不是 运行 — 但存储过程已成功创建,即使数据库不包含 table lc_f
.