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)

例外アプローチが確実に機能するようにするにはどうすればよいですか?

4

2 に答える 2

1

一意order byの列のセットが必要です。これがないと、SQLは行の順序を保証せず、クエリの2つの部分が完全に異なる行のサブセットを返す可能性があります。

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

これは、Top1000を使用してExceptが作業している行を制限していることが原因です。EXCEPTは、右側のクエリでも見つからない、左側のクエリからの個別の値を返します。NOTEXISTSを使用した方がよいでしょう。

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 に答える