2012-11-19 228 views
3

我有兩個表(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' 

我覺得不是很有效。

我的目的是驗證這兩個表/數據集是相同的,如果沒有,有意義的錯誤消息的輸出結果。

任何想法?

謝謝。

+1

表中是否有關鍵列?是否有任何獨特的列組合? – Laurence

+1

使用此:http://www.red-gate.com/products/sql-development/sql-data-compare/ –

+0

嗨勞倫斯,這兩個數據集沒有關鍵列,但所有列的組合是唯一的。 – nzsquall

回答

0

你有沒有考慮用MERGE語句比較兩個。

時不匹配插入#TEMP。那麼你可以顯示你的臨時表的結果。

+0

從語法的外觀來看,[當不匹配然後]我似乎無法將它們插入臨時表中?它看起來像我將不得不將它們插入到源表中? – nzsquall

+0

我的歉意。我有一個類似的問題,我不得不報告原來的結果。我使用merge then output子句插入到臨時表中進行報告,但我也必須插入這些缺失的記錄。我相信如果您插入並刪除了插入的行,效率將會從窗口中消失。 – user1836293

0

假設你有一個具有NOT NULL約束至少一個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的查詢相比,你需要嘗試一下。

0

答案在一般情況下:

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

詳細的解答:

問:什麼字母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); 

現在的問題:

問:在語言(計算機科學)而言,是@MyTable變量? A.嗯......

問題1:無法將表格值分配給@MyTable例如,

-- 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是一個既不支持賦值又不支持比較的「變量」。

問:如果@MyTable是一個變量,那麼語言(計算機科學)術語是MyTable? A. Constrant?值?類型?類?結構?以上都不是?

...是的,SQL確實是一種很奇怪的語言!

問:什麼是關係運算符? A.在關係模型中,它是一個運算符,它將兩個關係值作爲參數,並返回一個關係值作爲結果。

問:SQL是否支持關係運算符? A.不完全。 SQL確實有操作員會熟悉真正的關係語言(UNION,INTERSECT,EXCEPT等)的用戶。但是,SQL支持非關係特性,特別是空值,重複行和重複列名。因此,需要非常小心以確保這些運營商的論據和結果等同於關係。

Q如何使用SQL的'關係式'操作符來比較兩個表是否相等? 一這裏有一種方法:

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

測試以證明上述(注意,以下是所有關係值,但也證明了運營商與SQL空值邏輯工作):

例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的的適當子集(期望行== 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:表A是tableB的的適當子集(期望行== 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:表A和tableB的具有一些但不是全部共用行值(期望行== 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:表A和tableB的具有共同(期望行)沒有行值== 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; 

問:爲什麼SQL Server數據庫管理員傾向於不使用此語法,並且傾向於使用FULL OUTER JOIN?可能出於各種原因,如熟悉傳統語法(例如,在SQL Server 2005中引入了EXCEPT)。但最有可能的是,SQL DBA往往希望寫出他們認爲最有效的查詢(貶義,過早的優化)。確實如此,SQL Server優化器不能很好地應對運營商INTERSECTEXCEPT

問:爲什麼更喜歡「關係式」運算符? A.因爲它們不那麼冗長,可以說比較容易閱讀。這兩個都是測試代碼的好品質。