【问题标题】:SQL Server except and ANSI NULLSSQL Server 和 ANSI NULLS 除外
【发布时间】:2012-11-21 21:14:45
【问题描述】:

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

我写了一个小脚本来测试是不是这样:

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 方法有效?

【问题讨论】:

    标签: sql sql-server except


    【解决方案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
    

    【讨论】:

    • 来自 SQL BOL:ORDER BY 子句中的列名或别名必须引用左侧查询返回的列名。
    【解决方案2】:

    这是因为您使用 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
    

    【讨论】:

    • 我怎样才能简单地用大约 20 列来匹配?
    • #Edmondo1984 - 抱歉,我误解了您的问题。您的视图是否有任何 text、ntext、image 或 xml 列?如果不是,您应该能够使用完全外连接和 checksum(*) 函数重写查询以测试是否相等。
    • no...最大的列是 varchar(255) 其他主要是数字。你能提供更多细节吗?谢谢
    猜你喜欢
    • 2010-10-23
    • 2010-11-30
    • 2017-12-07
    • 2011-02-19
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多