2012-11-19 177 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.因为它们不那么冗长,可以说比较容易阅读。这两个都是测试代码的好品质。