【发布时间】:2014-10-22 13:26:06
【问题描述】:
我想使用内部联接对表进行某种“批量更新”。以下是它的工作原理。
有两张表有问题,其中一张正在更新中。我会打电话给正在更新的一个OriginalTable 和另一个UpdateData。
OriginalTable 和 UpdateData 都包含一个名为 Id 的 PK 列,我们稍后会加入。 OriginalTable 包含许多其他列,它们都是 nvarchars,我将这些称为数据列。最后,OriginalTable 还包含一个 Checksum 列,我希望在给定行的数据列中包含字符串连接数据的 SHA1 哈希。 UpdateData 包含OriginalTable 中数据列的子集,这就是用于指定将OriginalTable 中的数据更新为的内容。
如果UpdateData 中的值是非空字符串或NULL,那么我想用该值更新OriginalTable 中的相应行。如果值是空字符串,那么我不想修改OriginalTable行的值。
假设OriginalTable中的数据列是:FirstName、LastName、MI、Age。假设UpdateData 中的数据列是:FirstName、LastName、Age。这基本上意味着我们正在更新除 MI 之外的所有信息。
我可以用这个 SQL 完成这个更新:
UPDATE T
SET FirstName = CASE UD.FirstName WHEN '' THEN T.FirstName ELSE UD.FirstName END,
LastName = CASE UD.LastName WHEN '' THEN T.LastName ELSE UD.LastName END,
Age = CASE UD.Age WHEN '' THEN T.Age ELSE UD.Age END
FROM #OriginalTable T
INNER JOIN #UpdateData UD
ON T.Id = UD.Id;
这很好。现在,我面临的挑战是,在更新一行的校验和值时,我不知道如何保证只有在其他行首先更新后才会进行哈希计算。我应该提到,校验和计算发生在同一个语句中是很重要的。我想做这样的事情:
UPDATE T
SET FirstName = CASE UD.FirstName WHEN '' THEN T.FirstName ELSE UD.FirstName END,
LastName = CASE UD.LastName WHEN '' THEN T.LastName ELSE UD.LastName END,
Age = CASE UD.Age WHEN '' THEN T.Age ELSE UD.Age END,
Checksum = CONVERT(varchar(40), HASHBYTES('SHA1', T.FirstName + T.LastName + T.MI + T.Age), 2)
FROM #OriginalTable T
INNER JOIN #UpdateData UD
ON T.Id = UD.Id;
更新后我需要用OriginalTable 中的值计算校验和列的值。如何在同一个 UPDATE 语句中完成这个哈希计算,保证在其他列更新后计算它的数据?
【问题讨论】:
-
你不能只写两个语句,而是将它们包装在一个事务中吗?您是否有理由需要在单个语句中完成它?只是为了原子性吗?
-
一次更新并不是一连串的事件。它同时发生。如果你想这样做,你需要在你的 HASHBYTES 函数中添加所有的 case 表达式或进行第二次更新。您对 HASHBYTES 进行编码的方式将使用当前值,而不是新值。
-
老实说,我会考虑将您的校验和设为计算列。这将避免你不得不与它搏斗。
标签: sql sql-server tsql join