我通过用户定义的函数重构了一些视图,我想确保它们是相同的。
我写了一个小脚本来测试这种情况:
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)
我如何确保其他方法有效?
答案 0 :(得分: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
答案 1 :(得分:0)
这是因为您使用Top 1000来限制Except正在处理的行。 EXCEPT返回左查询中的任何不同值,这些值在右侧查询中也找不到。 你最好使用NOT EXISTS e.g。
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