源表和目标表都有大约40列。要更新的行数约为20.目标表的行数约为30k。
下面是否有更好的(更短的查询)方法?
UPDATE destination_table t1
SET
field1 = (select field1 from src_table t2 where t2.pk = t1.pk),
field2 = (select field2 from src_table t2 where t2.pk = t1.pk),
...
field40 = (select field40 from src_table t2 where t2.pk = t1.pk),
WHERE EXISTS (select 1 from src_table t2 where t2.pk = t1.pk)
答案 0 :(得分:5)
您可以使用以下内容:
UPDATE dest
SET dest.Field1 = src.Field1,
dest.Field2 = src.Field2,
dest.Field3 = src.Field3,
dest.Field4 = src.Field4,
dest.Field5 = src.Field5,
dest.Field6 = src.Field6
FROM destination_table dest
INNER JOIN src_table src
ON src.pk = dest.pk
您只需添加额外字段即可进行更新。
答案 1 :(得分:3)
update t1 set
field1 = t2.field1,
field2 = t2.field2,
...
field40 = t2.field40,
from destination_table t1
join src_table t2 on t2.pk = t1.pk
已添加(评论后):
在我看来,避免动态查询会更好,但如果你真的想要,你可以按照下面的方式去做。生成查询,无需记下所有列,但所有列都将更新。
declare @sql as nvarchar(max)
set @sql = ''
select @sql = @sql + ', ' + column_name + ' = t2.' + column_name
from information_schema.columns
where table_name = 'destination_table'
set @sql =
'update t1 set ' +
stuff(@sql, 1, 2, '') +
' from destination_table t1 join src_table t2 on t2.pk = t1.pk'
exec sp_executesql @sql
答案 2 :(得分:1)
您的原始查询是标准SQL-92'标量子查询'方法**。更喜欢它的一个原因(除了可移植性的概念)是SQL Server的专有UPDATE..FROM..JOIN
语法提供了可能模糊和意外的结果。
然而,'标量子查询'方法毫无疑问是冗长的(尽管智能优化器会发现重复的代码)。作为一个reault,SQL-99标准引入了MERGE
语句,该语句在SQL Server 2008中实现(有用的扩展),例如
MERGE INTO destination_table
USING src_table t2
ON t2.pk = destination_table.pk
WHEN MATCHED THEN
UPDATE
SET field1 = T2.field1,
field2 = T2.field2,
field2 = T2.field3,
...
field40 = T2.field40;
由于您不支持传统(2008年之前)代码,并且假设您没有立即计划移植到不支持MERGE的SQL产品(注意Oracle和postgreSQL没有,而mySQL没有),我认为没有理由使用MERGE
以外的任何构造进行此类更新。
**好吧,差不多。您的更新以具有相关名称't1`的表为目标。在SQL-92中,相关名称应该具有在SQL语句末尾实现超出范围的表的效果。换句话说,虽然语法有效,但结果应该是底层基表中的数据不受影响。但是,似乎很明显这不是您更新的意图,实际上SQL Server的实际效果是基表受到影响,技术上不符合规范的行为!