2012-12-04 80 views
1

我通過用戶定義的函數重構了一些視圖,我想確保它們是相同的。SQL Server除了和ANSI NULLS

我寫了一個小的腳本來測試這種情況:

SET ANSI_NULLS OFF 
GO 

SELECT TOP 1000 [DealNumber] 
     ,...others 
FROM OLD_VIEW 
EXCEPT 
SELECT TOP 1000 [DealNumber] 
      ,...others 
    FROM NEW_VIEW 

當我申請這個,我獲得了一些行作爲結果。但是,如果我採取了DealNumber從任何行,我運行以下命令:

SET ANSI_NULLS OFF 
GO 

SELECT [DealNumber] 
     ,...others 
FROM OLD_VIEW 
WHERE DealNumber = 'MyDealNumber' 
EXCEPT 
SELECT [DealNumber] 
      ,...others 
FROM NEW_VIEW 
WHERE DealNumber = 'MyDealNumber' 

這將返回如預期,一個空的記錄集。

作爲一種替代方法,我寫了一個函數Test_View_Correctness做前測試。但是,如果我這樣運行它:

SELECT TOP 1000 [DealNumber] from OLD_VIEW 
where DealNumber IN (SELECT a.DealNumber 
        FROM Test_View_Correctness(DealNumber) as a) 

如何確保除了方法的作品?

回答

1

您需要order by一個獨特組列,而沒有SQL 從未保證行順序和查詢兩個部分將有可能返回的行完全不同的子集:

SELECT ... FROM (SELECT TOP 1000 [DealNumber],...others 
        FROM OLD_VIEW 
        ORDER BY x,y,z) a 
EXCEPT 
SELECT ... FROM (SELECT TOP 1000 [DealNumber],...others 
        FROM NEW_VIEW 
        ORDER BY x,y,z) b 
+0

這產生了關鍵字 'ORDER' 附近有語法錯誤。 – Edmondo1984

+0

來自SQL BOL:ORDER BY子句中的列名或別名必須引用左側查詢返回的列名。 –

+0

@ Edmondo1984查看編輯 – 2012-12-04 10:25:48

0

這是這是因爲您正在使用Top 1000來限制Except正在處理的行。 EXCEPT返回左查詢中不在正確查詢中也找不到的任何不同值。 你最好用NOT EXISTS 根據進一步的澄清

SELECT TOP 1000 [DealNumber] 
      ,... others 
FROM OLD_VIEW 
WHERE NOT EXISTS 
    (SELECT * FROM NEW_VIEW WHERE OLD_VIEW.[DealNumber] = [DealNumber]) 

---更新

;WITH NV 
AS 
(
    SELECT *, CHECKSUM(*) as CHK 
    FROM NEW_VIEW 
), 
OV 
AS 
(
    SELECT *, CHECKSUM(*) AS CHK 
) 
SELECT * 
FROM NV 
FULL OUTER JOIN OV 
    ON NV.DealNumber = OV.DealNumber 
WHERE NV.DealNumber IS NULL -- CATCH missing rows in new view 
    OR OV.DealNumber IS NULL -- CATCH extra rows in new view 
    OR NV.CHK <> OV.CHK  -- CATCH differing columns in either view 
+0

我該如何做到這一點,只需約20列匹配? – Edmondo1984

+0

#Edmondo1984 - 對不起,我誤解了你的問題。你的觀點是否有任何文字,ntext,圖像或XML列?如果不是的話,你應該可以使用完整的外連接和校驗和(*)函數來重寫查詢來測試是否相等。 –

+0

不......最大的列是varchar(255),其他列主要是數字。你能否提供更多細節?謝謝 – Edmondo1984