这些行通常第一次进入目标表的方式是使用稀疏数量的列填充大部分文本数据,其余列设置为NULL。在后续传递中,新数据填充现有的已知(非空)和未知(NULL)数据。我已经确定新数据(#pld)确实包含不同的数据。数据似乎没有变化。这就是我所拥有的:
BEGIN TRANSACTION
BEGIN TRY
MERGE INTO [metro].listings AS metroList
USING #pld as listnew
ON metroList.id = listnew.id
AND metroList.sid = listnew.sid
WHEN MATCHED AND (
metroList.User != listnew.User
or metroList.Email != listnew.Email
or metroList.LocName != listnew.LocName
) THEN
UPDATE SET
metroList.User = listnew.User,
metroList.Email = listnew.Email,
metroList.LocName = listnew.LocName,
WHEN NOT MATCHED THEN
INSERT
( User,
Email,
LocName
)
VALUES
(
listnew.User,
listnew.Email,
listnew.LocName
);
COMMIT TRANSACTION
END TRY
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH
我尝试用<>替换声明更新部分下的!= 。结果相同。这必须与可能的(可能的)null值与字符串的比较相关 - 甚至可能是另一个null?无论如何,我正在呼吁所有的sql-geeks解开这个。
答案 0 :(得分:3)
您也可以使用NULLIF()功能选项。
如果两个表达式不相等,则NULLIF返回第一个表达式。如果表达式相等,则NULLIF返回第一个表达式类型的空值。
WHEN MATCHED AND (
NULLIF(ISNULL(metroList.[User],''), listnew.[User]) IS NOT NULL
OR NULLIF(ISNULL(metroList.Email, ''), listnew.Email) IS NOT NULL
OR NULLIF(ISNULL(metroList.LocName, ''), listnew.LocName) IS NOT NULL
)
THEN
答案 1 :(得分:2)
将NULL
与空字符串进行比较将无效。
如果任何一方都可以NULL
,您可以执行以下操作:
WHEN MATCHED AND (
COALESCE(metroList.User, '') <> COALESCE(listnew.User, '')
or COALESCE(metroList.Email, '') <> COALESCE(listnew.Email, '')
or COALESCE(metroList.LocName, '') <> COALESCE(listnew.LocName, '')
) THEN
当然,这假设您可以使用NULL
表示与空字符串相同(可能不合适)。
在NULL
比较中查看this BOL article。
答案 2 :(得分:2)
据我所知,您正在寻找一个模仿IS DISTINCT FROM
的表达式。
您接受的答案不正确
WITH metroList([User])
AS (SELECT CAST(NULL AS VARCHAR(10))),
listnew([User])
AS (SELECT 'Foo')
SELECT *
FROM metroList
JOIN listnew
ON NULLIF(metroList.[User], listnew.[User]) IS NOT NULL
返回零行。尽管比较下的值为NULL
和Foo
。
我会使用本文中的技巧:Undocumented Query Plans: Equality Comparisons
WHEN MATCHED AND EXISTS (
SELECT metroList.[User], metroList.Email,metroList.LocName
EXCEPT
SELECT listnew.[User], listnew.Email,listnew.LocName
)