1

我已经通过用户定义的函数重构了一些视图,我想确保它们是相同的。

我写了一个小脚本来测试这种情况:

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)

如何确保 except 方法有效?

4

2 回答 2

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
于 2012-12-04T09:29:31.700 回答
0

这是因为您使用 Top 1000 来限制例外正在处理的行。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
于 2012-12-04T09:35:50.273 回答