3

2 つのテーブル (OriginalLoad) があり、ストアド プロシージャを使用してそれらを比較したいと考えています。

データベースは SQL Server 2008 です。

これが私のSPの例です:

USE [TestDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[ValidateLoad] 
AS 
    SET nocount ON; 

    IF EXISTS(SELECT * 
              FROM   dbo.original 
              EXCEPT 
              SELECT * 
              FROM   dbo.LOAD) 
      BEGIN 
          PRINT 
      'Warning! The following information has not been loaded' 

       PRINT '---------------------------------' 

       PRINT 'Load result: Fail' 

          SELECT * 
          FROM   dbo.original 
          EXCEPT 
          SELECT * 
          FROM   dbo.LOAD 

      set noexec on
      END 

    IF EXISTS(SELECT * 
              FROM   dbo.LOAD 
              EXCEPT 
              SELECT * 
              FROM   dbo.original) 
      BEGIN 
          PRINT 
      'Warning! The following information does not exist in Original table' 

       PRINT '---------------------------------' 

       PRINT 'Load result: Fail' 

    SELECT * 
    FROM   dbo.LOAD 
    EXCEPT 
    SELECT * 
    FROM   dbo.original 

    set noexec on
END 

    PRINT 'Load result: Succeeded' 

あまり効率的ではないと思います。

私の意図は、これら 2 つのテーブル/データセットが同一であることを検証することです。そうでない場合は、意味のあるエラー メッセージで結果を出力します。

何か考えはありますか?

ありがとうございました。

4

3 に答える 3

0

一般的なケースで答えてください:

SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

詳細な回答:

Q. SQL という文字は何の略ですか? A. 言語としての資格はほとんどありません... ROFLですが、次の重要な点を考慮してください。

CREATE TABLE MyTable
   ( ID INTEGER NOT NULL UNIQUE, data_col VARCHAR(10) NOT NULL );

DECLARE @MyTable TABLE 
   ( ID INTEGER NOT NULL UNIQUE, data_col VARCHAR(10) NOT NULL );

今質問:

Q. 言語 (コンピューター サイエンス) 用語で@MyTable、変数は変数ですか? A.そうですね...

@MyTable問題 1:たとえば、テーブルの値を割り当てることができません

-- Assignment attempt 1:
SET @MyTable = MyTable;  -- COMPILE ERROR

-- Assignment attempt 2:
SET @MyTable = ( VALUES ( 1, NULL ), ( 2, '' ), ( 3, 'Test' ) );  -- COMPILE ERROR

問題 2: 変数を比較できないなど

-- Comparison attempt 1:
IF ( @MyTable = @MyTable ) BEGIN; 
    PRINT 'Tables are the same.' 
END;  -- COMPILE ERROR

-- Comparison 2:
IF ( @MyTable = ( VALUES ( 1, NULL ), ( 2, '' ), ( 3, 'Test' ) ) ) BEGIN; 
    PRINT 'Tables are the same.' 
END;  -- COMPILE ERROR

...したがって、@MyTable は代入も比較もサポートしない「変数」であると信じなければなりません。

Q.@MyTableが変数の場合、言語 (コンピューター サイエンス) 用語で はMyTable何​​ですか? A.コンスタント?価値?タイプ?クラス?構造?上記のどれでもない?

...はい、SQL は非常に奇妙な言語です。

Q. 関係演算子とは何ですか? A. リレーショナル モデルでは、2 つのリレーション値を引数として取り、結果としてリレーション値を返す演算子です。

Q. SQL は関係演算子をサポートしていますか? A. そうではありません。SQL には、真のリレーショナル言語 ( UNIONINTERSECTEXCEPTなど) のユーザーになじみのある演算子があります。ただし、SQL は非リレーショナル機能、特にヌル、重複行、重複列名をサポートしています。したがって、これらの演算子の引数と結果がリレーションと同等になるように細心の注意を払う必要があります。

Q SQL の「リレーショナル スタイル」演算子を使用して 2 つのテーブルを比較して等価性を確認する方法を教えてください。A 1 つの方法は次のとおりです。

SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

上記を実証するためのテスト (以下はすべての関係値ではありませんが、演算子が SQL null で論理的に機能することを証明していることに注意してください):

例 1: テーブルは同じです (ゼロ行 == PASS を想定):

WITH tableA AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 2, '' ), 
                              ( 3, 'Test' )
                     ) AS T ( ID, data_col ) ),
     tableB AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 2, '' ), 
                              ( 3, 'Test' )
                     ) AS T ( ID, data_col ) )
SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

例 2: tableB は tableB の適切なサブセットです (rows == FAIL が予想されます):

WITH tableA AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 2, '' ), 
                              ( 3, 'Test' )
                     ) AS T ( ID, data_col ) ),
     tableB AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 2, '' ) 
                     ) AS T ( ID, data_col ) )
SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

例 3: tableA は tableB の適切なサブセットです (rows == FAIL が予想されます):

WITH tableA AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 3, 'Test' )
                     ) AS T ( ID, data_col ) ),
     tableB AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 2, '' ), 
                              ( 3, 'Test' )
                     ) AS T ( ID, data_col ) )
SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

例 4: tableA と tableB には共通の行の値がいくつかありますが、すべてではありません (rows == FAIL が予想されます)。

WITH tableA AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 4, 'Lone' )
                     ) AS T ( ID, data_col ) ),
     tableB AS
     ( SELECT * FROM ( VALUES ( 1, NULL ), 
                              ( 4, 'Sole' )
                     ) AS T ( ID, data_col ) )
SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

例 5: tableA と tableB には共通の行の値がありません (rows == FAIL が予想されます):

WITH tableA AS
     ( SELECT * FROM ( VALUES ( 5, NULL ), 
                              ( 6, 'Different' )
                     ) AS T ( ID, data_col ) ),
     tableB AS
     ( SELECT * FROM ( VALUES ( 7, NULL ), 
                              ( 8, 'Not the same' )
                     ) AS T ( ID, data_col ) )
SELECT * FROM tableA
UNION 
SELECT * FROM tableB
EXCEPT 
SELECT * FROM tableA 
INTERSECT
SELECT * FROM tableB;

Q. SQL Server DBA がこの構文を使用せず、たとえば を好む傾向があるのはなぜFULL OUTER JOINですか? A. おそらく、従来の構文に精通しているなど、さまざまな理由によるものです (たとえばEXCEPT、SQL Server 2005 で導入されました)。しかし、最も可能性が高いのは、SQL DBA は、最も効率的なクエリであると思われるものを書きたがる傾向があるということです (軽蔑的に言えば、時期尚早の最適化です)。確かに、SQL Server オプティマイザーは演算子INTERSECTおよび をうまく処理できませんEXCEPT

Q. 「リレーショナル スタイル」の演算子が好まれるのはなぜですか? A. 冗長性が低く、間違いなく読みやすいためです。これらはどちらも、テスト コードにとって優れた品質です。

于 2013-02-19T11:45:02.470 に答える
0

merge ステートメントを使用して 2 つを比較することを検討しましたか。

一致しない場合は #temp に挿入します。次に、一時テーブルの結果を表示できます。

于 2012-11-19T22:25:00.077 に答える
0

NOT NULL 制約を持つ少なくとも 1 つの列 c1 があると仮定すると、このクエリは、いずれかのテーブルで欠落しているすべての行のリストを提供する必要があります。

SELECT t1.*,t2.* 
FROM dbo.original t1 full outer join dbo.LOAD t2
ON (list of join keys)
WHERE t1.c1 IS NULL or t2.c1 IS NULL

ただし、EXCEPT ベースのクエリと比較してどれだけ効率的かはわかりませんが、試してみる必要があります。

于 2012-11-19T23:32:49.477 に答える