虽然可能有办法通过花哨的子选择来用另一个表更新一个表,但我相信最好的方法是使用 SQL API 编写一个程序来执行此操作(无论是用于 perl 的 DBD::DB2 驱动程序的 DBI,用于Java 或 C 库等)执行 SELECT,使用游标从 RESULTSET 中获取每个结果行,并进行更新。
PSEUDOCODE(不知道你熟悉什么语言):
dbHandle = sqllib->open_connection(database, user, password)
select_statement = dbHandle->prepare('SELECT id FROM idstoupdate')
update_statement = dbHandle->prepare('UPDATE clients SET col1=?, col2=? WHERE ID=?')
resultset = statement->execute(select_statement)
foreach (row in resultset) {
id = row.getColumn('id')
update_statement->execute('1','2',id)
}
dbHandle->disconnect();
您会想要添加错误检查。如果您希望应用所有更新,或者不应用任何更新,那么您必须考虑开始一个事务并在没有错误的情况下提交整个事务。DB2 Infocenter中有大量关于如何完成上述所有工作的资料。
注意:
如果您的源数据idstoupdate
是一个文件,那么您可以跳过 select 语句和您为加载idstoupdate
表所做的工作,而只需从文件中读取并更新数据库。这将是处理表更新的最有效方式。
如果您只是必须使用纯 SQL 从另一个表更新一个表,那么最常见的示例是这种格式:
UPDATE table1 t1
SET (t1.field1, t1.field2) =
(
SELECT t2.field1,
t2.field2
FROM table2 t2
WHERE t1.joinfield = t2.joinfield
AND t2.criteriafield = 'qualifier'
)
WHERE EXISTS
(
SELECT 1
FROM table2
WHERE t1.joinfield = table2.joinfield
AND t2.criteriafield = 'qualifier'
)
它消除了IN
谓词,但可能不会提高内存或日志空间的效率,而且因为它不如选择、循环、获取、更新那么简单,您需要确保所有条件都正确。你的情况有点简单——我认为这会起作用,但我需要一个 db2 实例来尝试它:
UPDATE clients t1
SET t1.col1 = '1', col2 = 'y'
WHERE EXISTS
(
SELECT 1
FROM idstoupdate t2
WHERE t1.id = t2.id
)
编辑:
我实际上很惊讶您提供的查询不适用于 SQL squirrel,因为它是合法查询。它甚至可以执行类似于我给出的示例,因为 DB2 非常擅长优化 SQL/确定最佳访问路径。
在我的回答中,我试图展示更新表的最节省内存的方法,以及使用纯 SQL 从另一个表更新一个表中的行的一般模式(这将涵盖一个表包含的不仅仅是要更新的行)。
此外,我怀疑包含超过 20 个左右值的 IN 谓词,即使现代数据库引擎可以轻松处理它们。
但是,检查数据库引擎是否有效地处理您的查询和/或比较两个 SQL 查询的最佳方法是使用SQL 解释命令。