2013-03-12 60 views
3

这些行通常第一次进入目标表的方式是使用大量文本数据填充的列的稀疏数量,其余列设置为NULL。在随后的传递中,新数据填充现有已知(非空)和未知(NULL)数据。我确定新数据(#pld)确实包含不同的数据。数据似乎没有改变。下面是我有:sql server:MERGE有意想不到的结果

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 

我试着更换=该声明的更新部分根据与<>!相同的结果。这必须与可能的(可能的)空值与字符串的比较相关 - 甚至可能是另一个空值?无论如何,我打电话给所有的sql-geeks来解决这个问题。

回答

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 
+0

看起来不正确我。 – 2013-03-13 07:22:41

+0

ooops.My fault.NULLIF()函数在 的第一个值为NULL时不起作用。在我的更新中,我使用ISNULL()进行了检查。我再次对不起,感谢@Martin Smith +100500 – 2013-03-13 08:30:05

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意思等同于一个空字符串(这可能不适合) 。

看看this BOL articleNULL比较。

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 

返回零行。尽管比较值为NULLFoo

我会使用的技术从这篇文章:Undocumented Query Plans: Equality Comparisons

WHEN MATCHED AND EXISTS (
         SELECT metroList.[User], metroList.Email,metroList.LocName 
         EXCEPT 
         SELECT listnew.[User], listnew.Email,listnew.LocName 
         )  
+0

选项,EXCEPT是最好的;) – 2013-03-13 08:54:42