来自 UPDATE 选项的 DB2 SELECT
DB2 SELECT from UPDATE Options
我目前正在尝试做一个
SELECT DISTINCT * FROM FINAL TABLE
(UPDATE mainTable SET value = 'N' WHERE value2 = 'Y')
不过我的DB2版本好像不支持这个
SQL Error [42601]: [SQL0199] Keyword UPDATE not expected. Valid tokens: INSERT.
在 DB2 中是否有任何替代方案可以 return 获得所需的结果?在一个查询中,我们可以在哪里更新和 Return 结果?
编辑 -
Select 语句应该 return 服务器应用程序开始处理的值。发生这种情况时,将更新一列以指示该行的处理已经开始。稍后的命令将在完成后再次更新该行。
ORIGINAL DATA
ROW ID | COLUMN TWO | PROCESSING FLAG
-------------------------------------------
1 | TASK 1 | N
2 | TASK 2 | N
3 | TASK 3 | N
4 | TASK 4 | N
乐观后Select/Update查询
Data Table returned as:
ROW ID | COLUMN TWO | PROCESSING FLAG
-------------------------------------------
1 | TASK 1 | Y
2 | TASK 2 | Y
3 | TASK 3 | Y
4 | TASK 4 | Y
这是由 .NET 应用程序调用的,因此这将被转换为 Table 对象的列表。
您不能在 DB2 IBM i 7.3(现在甚至是 7.4)中的 table-reference 中指定 UPDATE
,因为您可以在 Db2 for LUW 中指定。
只有 INSERT
个可用。
data-change-table-reference
-+-- FINAL -+- TABLE (INSERT statement) correlation-clause
| |
-+-- NEW ---+
一种可能的模拟是使用动态复合语句、定位更新和临时 table 来保存更新行的信息。
--#SET TERMINATOR @
DECLARE GLOBAL TEMPORARY TABLE SESSION.MAINTABLE
(
ID INT, COL VARCHAR (10), FLAG CHAR (1)
) WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED@
INSERT INTO SESSION.MAINTABLE (ID, COL, FLAG)
VALUES
(1, 'TASK 1', 'N')
, (2, 'TASK 2', 'N')
, (3, 'TASK 3', 'N')
, (4, 'TASK 4', 'Y')
@
DECLARE GLOBAL TEMPORARY TABLE SESSION.UPDRES AS
(
SELECT ID FROM SESSION.MAINTABLE
) DEFINITION ONLY WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED@
BEGIN
FOR F1 AS C1 CURSOR FOR
SELECT ID FROM SESSION.MAINTABLE WHERE FLAG = 'N' FOR UPDATE
DO
UPDATE SESSION.MAINTABLE SET FLAG = 'Y' WHERE CURRENT OF C1;
INSERT INTO SESSION.UPDRES (ID) VALUES (F1.ID);
END FOR;
END@
SELECT * FROM SESSION.MAINTABLE@
ID
COL
FLAG
1
TASK 1
Y
2
TASK 2
Y
3
TASK 3
Y
4
TASK 4
Y
SELECT * FROM SESSION.UPDRES@
ID
1
2
3
虽然您目前无法在 Db2 for IBM i 上使用 SELECT FROM FINAL TABLE(UPDATE ...)
...
你可以在事务的上下文中做
UPDATE mainTable SET value = 'Y' WHERE value2 = 'N' with RR
SELECT * FROM mainTable WHERE value2 = 'Y'
COMMIT
使用 RR
- Repeatable 读取意味着整个 table 将被锁定,直到您发出提交。如果您有 knowledge/control 个使用 table.
的任何其他进程,您可以使用较低的 isolation level
或者如果您愿意做一些额外的工作...下面只锁定返回的行。
UPDATE mainTable SET value = '*' WHERE value2 = 'N' with CHG
SELECT * FROM mainTable WHERE value2 = '*'
UPDATE mainTable SET value = 'Y' WHERE value2 = '*' with CHG
COMMIT
直接 SQL 方法是通过光标和 UPDATE WHERE CURRENT OF CURSOR ....
最后,由于您使用的是 .NET,我建议您查看 IBM .NET Provider Technical Reference(IBM ACS Windows 的一部分)中的 iDB2DataAdapter
class应用程序包)
public void Example()
{
//create table mylib.mytable (col1 char(20), col2 int)
//insert into mylib.mytable values('original value', 1)
iDB2Connection cn = new iDB2Connection("DataSource=mySystemi;");
iDB2DataAdapter da = new iDB2DataAdapter();
da.SelectCommand = new iDB2Command("select * from mylib.", cn);
da.UpdateCommand = new iDB2Command("update mylib.mytable set col1 = @col1 where col2 = @col2", cn);
cn.Open();
//Let the provider generate the correct parameter information
da.UpdateCommand.DeriveParameters();
//Associate each parameter with the column in the table it corresponds to
da.UpdateCommand.Parameters["@col1"].SourceColumn = "col1";
da.UpdateCommand.Parameters["@col2"].SourceColumn = "col2";
//Fill the DataSet from the DataAdapter's SelectCommand
DataSet ds = new DataSet();
da.Fill(ds, "table");
//Modify the information in col1
DataRow dr = ds.Tables[0].Rows[0];
dr["col1"] = "new value";
//Write the information back to the table using the DataAdapter's UpdateCommand
da.Update(ds, "table");
cn.Close();
}
您还可以在 Integrating DB2 Universal Database for iSeries with Microsoft ADO .NET 红皮书中找到一些有用的信息。
我目前正在尝试做一个
SELECT DISTINCT * FROM FINAL TABLE
(UPDATE mainTable SET value = 'N' WHERE value2 = 'Y')
不过我的DB2版本好像不支持这个
SQL Error [42601]: [SQL0199] Keyword UPDATE not expected. Valid tokens: INSERT.
在 DB2 中是否有任何替代方案可以 return 获得所需的结果?在一个查询中,我们可以在哪里更新和 Return 结果?
编辑 - Select 语句应该 return 服务器应用程序开始处理的值。发生这种情况时,将更新一列以指示该行的处理已经开始。稍后的命令将在完成后再次更新该行。
ORIGINAL DATA
ROW ID | COLUMN TWO | PROCESSING FLAG
-------------------------------------------
1 | TASK 1 | N
2 | TASK 2 | N
3 | TASK 3 | N
4 | TASK 4 | N
乐观后Select/Update查询
Data Table returned as:
ROW ID | COLUMN TWO | PROCESSING FLAG
-------------------------------------------
1 | TASK 1 | Y
2 | TASK 2 | Y
3 | TASK 3 | Y
4 | TASK 4 | Y
这是由 .NET 应用程序调用的,因此这将被转换为 Table 对象的列表。
您不能在 DB2 IBM i 7.3(现在甚至是 7.4)中的 table-reference 中指定 UPDATE
,因为您可以在 Db2 for LUW 中指定。
只有 INSERT
个可用。
data-change-table-reference
-+-- FINAL -+- TABLE (INSERT statement) correlation-clause
| |
-+-- NEW ---+
一种可能的模拟是使用动态复合语句、定位更新和临时 table 来保存更新行的信息。
--#SET TERMINATOR @
DECLARE GLOBAL TEMPORARY TABLE SESSION.MAINTABLE
(
ID INT, COL VARCHAR (10), FLAG CHAR (1)
) WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED@
INSERT INTO SESSION.MAINTABLE (ID, COL, FLAG)
VALUES
(1, 'TASK 1', 'N')
, (2, 'TASK 2', 'N')
, (3, 'TASK 3', 'N')
, (4, 'TASK 4', 'Y')
@
DECLARE GLOBAL TEMPORARY TABLE SESSION.UPDRES AS
(
SELECT ID FROM SESSION.MAINTABLE
) DEFINITION ONLY WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED@
BEGIN
FOR F1 AS C1 CURSOR FOR
SELECT ID FROM SESSION.MAINTABLE WHERE FLAG = 'N' FOR UPDATE
DO
UPDATE SESSION.MAINTABLE SET FLAG = 'Y' WHERE CURRENT OF C1;
INSERT INTO SESSION.UPDRES (ID) VALUES (F1.ID);
END FOR;
END@
SELECT * FROM SESSION.MAINTABLE@
ID | COL | FLAG |
---|---|---|
1 | TASK 1 | Y |
2 | TASK 2 | Y |
3 | TASK 3 | Y |
4 | TASK 4 | Y |
SELECT * FROM SESSION.UPDRES@
ID |
---|
1 |
2 |
3 |
虽然您目前无法在 Db2 for IBM i 上使用 SELECT FROM FINAL TABLE(UPDATE ...)
...
你可以在事务的上下文中做
UPDATE mainTable SET value = 'Y' WHERE value2 = 'N' with RR
SELECT * FROM mainTable WHERE value2 = 'Y'
COMMIT
使用 RR
- Repeatable 读取意味着整个 table 将被锁定,直到您发出提交。如果您有 knowledge/control 个使用 table.
或者如果您愿意做一些额外的工作...下面只锁定返回的行。
UPDATE mainTable SET value = '*' WHERE value2 = 'N' with CHG
SELECT * FROM mainTable WHERE value2 = '*'
UPDATE mainTable SET value = 'Y' WHERE value2 = '*' with CHG
COMMIT
直接 SQL 方法是通过光标和 UPDATE WHERE CURRENT OF CURSOR ....
最后,由于您使用的是 .NET,我建议您查看 IBM .NET Provider Technical Reference(IBM ACS Windows 的一部分)中的 iDB2DataAdapter
class应用程序包)
public void Example()
{
//create table mylib.mytable (col1 char(20), col2 int)
//insert into mylib.mytable values('original value', 1)
iDB2Connection cn = new iDB2Connection("DataSource=mySystemi;");
iDB2DataAdapter da = new iDB2DataAdapter();
da.SelectCommand = new iDB2Command("select * from mylib.", cn);
da.UpdateCommand = new iDB2Command("update mylib.mytable set col1 = @col1 where col2 = @col2", cn);
cn.Open();
//Let the provider generate the correct parameter information
da.UpdateCommand.DeriveParameters();
//Associate each parameter with the column in the table it corresponds to
da.UpdateCommand.Parameters["@col1"].SourceColumn = "col1";
da.UpdateCommand.Parameters["@col2"].SourceColumn = "col2";
//Fill the DataSet from the DataAdapter's SelectCommand
DataSet ds = new DataSet();
da.Fill(ds, "table");
//Modify the information in col1
DataRow dr = ds.Tables[0].Rows[0];
dr["col1"] = "new value";
//Write the information back to the table using the DataAdapter's UpdateCommand
da.Update(ds, "table");
cn.Close();
}
您还可以在 Integrating DB2 Universal Database for iSeries with Microsoft ADO .NET 红皮书中找到一些有用的信息。