SQL Server,将2个表与动态列进行比较

时间:2016-05-16 18:56:52

标签: sql sql-server automated-tests

我正在寻找能够比较具有相同架构的2个表的代码,并告诉我哪些列有差异。

我确信我可以编写此代码,但希望能节省时间和精力并进行测试。

基本上,我有2个表一直在变化,如下所示:

KeyField  Cola Colb Colc Cold

查询(或存储过程)的输出将是:

Keyfield, Column name,  Table 1 value, Table 2 value

可能有100个字段,所以我不想手动继续这样做。

我可以执行EXCEPT以查找哪些行不同(我正在测试数据仓库)。但是,我必须手动查看哪些列不同。列根据测试而变化,我想要一些我可以重用的东西。

我认为这需要动态的sql,显然系统表需要获取列名。

有没有人有这样的代码?

2 个答案:

答案 0 :(得分:1)

快速而肮脏的答案:这会逐列创建并比较两个表(必须具有相同的架构)值。

它只显示两个不相等的值,而不是所有列。这不包含空处理或错误处理。也不建议在可能受SQL注入的情况下使用它。取消注释EXEC,以便在测试后运行动态SQL。

USE TEMPDB
GO
DECLARE @SQL NVARCHAR(MAX), @SQL_OR NVARCHAR(MAX), @SQL_CASE NVARCHAR(MAX)
SET @SQL=''
SET @SQL_OR=''
SET @SQL_CASE=''
IF OBJECT_ID('tempdb.dbo.tmp1') IS NOT NULL DROP TABLE tempdb.dbo.tmp1
IF OBJECT_ID('tempdb.dbo.tmp2') IS NOT NULL DROP TABLE tempdb.dbo.tmp2

CREATE TABLE tempdb.dbo.tmp1 (keyField int identity(1,1), value1 int, value2 int)
CREATE TABLE tempdb.dbo.tmp2 (keyField int identity(1,1), value1 int, value2 int)

INSERT INTO tempdb.dbo.tmp1 (value1, value2)
VALUES (555,1204),
       (999,1255),
       (666,9999),
       (12345,12345)
INSERT INTO tempdb.dbo.tmp2 (value1, value2)
VALUES (555,1205),
       (888,1255), 
       (666,9999),
       (12345,NULL)

SELECT @SQL_OR=@SQL_OR+' OR ISNULL(T1.['+TBL1.COLUMN_NAME+'],'''')!=ISNULL(T2.['+TBL1.COLUMN_NAME+'],'''')' + CHAR(13),
       @SQL_CASE=@SQL_CASE+', CASE WHEN ISNULL(T1.['+TBL1.COLUMN_NAME+'],'''')!=ISNULL(T2.['+TBL1.COLUMN_NAME+'],'''') THEN ISNULL(CONVERT(NVARCHAR,T1.['+TBL1.COLUMN_NAME+']),''NULL'')+'' != ''+ISNULL(CONVERT(NVARCHAR,T2.['+TBL1.COLUMN_NAME+']),''NULL'') ELSE NULL END AS ['+TBL1.COLUMN_NAME+']' + CHAR(13)
FROM INFORMATION_SCHEMA.COLUMNS TBL1
WHERE TBL1.TABLE_NAME='tmp1'
AND TBL1.COLUMN_NAME!='keyField'
AND EXISTS (SELECT 1 
            FROM INFORMATION_SCHEMA.COLUMNS TBL2 
            WHERE TBL2.TABLE_NAME='tmp2' 
            AND TBL2.COLUMN_NAME!='keyField' 
            AND TBL1.COLUMN_NAME=TBL2.COLUMN_NAME)


SET @SQL = 'SELECT T1.keyField'+@SQL_CASE+' 
            FROM tempdb.dbo.tmp1 T1
            LEFT JOIN tempdb.dbo.tmp2 T2
               ON T1.keyField=T2.keyField
            WHERE 1=2' + @SQL_OR

PRINT @SQL
--EXEC(@SQL)

输出:

keyField    value1      value2
1           NULL        1204 != 1205
2           999 != 888  NULL
4           NULL        12345 != NULL

答案 1 :(得分:0)

这可以通过MERGE (Transact-SQL)

来实现