是否可以使用单个UPDATE SQL语句执行多个更新?
比方说,我有一个列IDB和标题的表。 我需要更改标题列的所有值:
- 从“a-1”到“a1”
- 从“a.1”到“a1”
- 从“b-1”到“b1”
- 从“b.1”到“b1”。
现在,我正在执行两个UPDATE语句:
UPDATE tbl SET title='a1' WHERE title IN ('a-1', 'a.1') UPDATE tbl SET title='b1' WHERE title IN ('b-1', 'b.1')
这完全不是问题,如果表很小,单个语句在一秒钟内完成,只需要执行几条语句。
你可能猜到了 – 我有一个巨大的表来处理(一个语句在大约90秒内完成),我有大量的更新来执行。
那么,是否可以合并更新,以便只扫描一次表格? 或者,在这样的情况下,还有更好的办法。
编辑:请注意,我正在使用的真实数据和我必须执行的数据的更改并不是真的那么简单 – string更长,他们不遵循任何模式(这是用户数据,所以没有假设可以做成 – 可以是任何东西)。
在更一般的情况下,每个新值可能有数百个映射,您可以创build一个新旧值的单独表,然后在UPDATE语句中使用。 在一个SQL方言中:
CREATE TEMP TABLE mapper (old_val CHAR(5) NOT NULL, new_val CHAR(5) NOT NULL); ...multiple inserts into mapper... INSERT INTO mapper(old_val, new_val) VALUES('a.1', 'a1'); INSERT INTO mapper(old_val, new_val) VALUES('a-1', 'a1'); INSERT INTO mapper(old_val, new_val) VALUES('b.1', 'b1'); INSERT INTO mapper(old_val, new_val) VALUES('b-1', 'b1'); ...etcetera... UPDATE tbl SET title = (SELECT new_val FROM mapper WHERE old_val = tbl.title) WHERE title IN (SELECT old_val FROM mapper);
这两个select语句是至关重要 第一个是相关的子查询(不一定是快速的,但是如果映射表具有数千行,则比大多数select更快)将新值从对应于旧值的映射表中拉出。 第二个确保只有那些在映射表中具有值的行被修改; 这是至关重要的,否则,标题将被设置为空的那些没有映射条目的行(这些是在你开始之前确定的logging)。
对于一些替代scheme,CASE操作是可以的。 但是,如果您有数百或数千或数百万个映射来执行,则可能会超出数据库pipe理系统中SQL语句长度的限制。
您可以使用一个语句和一些case语句
update tbl set title = case when title in ('a-1', 'a.1') then 'a1' when title in ('b-1', 'b.1') then 'b1' else title end
当然,这会导致在每个logging上写一个索引,这可能是一个问题,所以你只能过滤掉你想改变的行:
update tbl set title = case when title in ('a-1', 'a.1') then 'a1' when title in ('b-1', 'b.1') then 'b1' else title end where title in ('a.1', 'b.1', 'a-1', 'b-1')
这将减less对表格的写入次数。
乔纳森的答案工作。
UPDATE tbl SET title = new_val FROM mapper WHERE title IN (SELECT old_val FROM mapper) AND mapper.old_val = tbl.title;
他的初始版本将需要大量的读取映射表。
如果转换和你的例子一样简单,你可以通过一些string操作来完成更新:
UPDATE tbl SET title = left(title, 1) + right(title, 1) WHERE title IN ('a-1', 'a.1', 'b-1', 'b.1')
会有这样的工作吗?
要么
Update Table set title = Replace(Replace(title, '.', ''), '-', '') Where title Like '[ab][.-]1'