SQL Server比较两个应该相同的查询的结果

Oxe*_*rik 36 sql-server sql-server-2005

我正在稍微修改一个sql server 2005存储过程的性能,我想快速确保旧的存储过程和新的存储过程返回完全相同的结果(列是相同的,我想确保行是相同).

在sql server 2005中有一个简单的方法吗?

jab*_*abs 52

您可以使用except结构来匹配两个查询.

select * from (select * from query1) as query1
except
select * from (select * from query2) as query2
Run Code Online (Sandbox Code Playgroud)

编辑:

然后反转查询以查找与query2的差异作为驱动程序:

select * from (select * from query2) as query2
except
select * from (select * from query1) as query1
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这将丢弃重复项.因此,如果查询1返回1记录并且查询2返回2个彼此相同的记录并且从查询1返回单个记录,则"除"逻辑将返回零行. (9认同)
  • 然后反转它. (6认同)

tpv*_*los 10

要完成@jabs答案,您可以使用以下模板来获取两个查询之间的差异。它还添加了一个额外的列 ( diff_description),用于解释哪个查询中缺少每一行。

with q1 as (
    <INSERT_Q1_HERE>
)
, q2 as (
    <INSERT_Q2_HERE>
)
, missing_from_q2 as (
    select *
    from (
        select * from q1 
        except 
        select * from q2
    )
    cross join (select 'missing from q2' as diff_description)
)
, missing_from_q1 as (
    select *
    from (
        select * from q2 
        except
        select * from q1
    )
    cross join (select 'missing from q1' as diff_description)
)
select * from missing_from_q2
union all
select * from missing_from_q1
Run Code Online (Sandbox Code Playgroud)


Cod*_*Org 5

下面的存储过程将比较 2 个存储过程或 2 个语句的输出结果集。这里的关键是SP不需要知道结果集的结构或模式,因此您可以任意测试任何SP。如果输出相同,它将返回 0 行。此解决方案使用 SQL Server 中的 openrowset 命令。这是存储过程的一些示例用法

DECLARE @SQL_SP1 VARCHAR(MAX)
DECLARE @SQL_SP2 VARCHAR(MAX)

-- Compare results of 2 Stored Procs
SET @SQL_SP1 = 'EXEC SomeDB.dbo.[usp_GetWithTheProgram_OLD] 100, ''SomeParamX'''
SET @SQL_SP1 = 'EXEC SomeDB.dbo.[usp_GetWithTheProgram_NEW] 50, ''SomeParamX'''
EXEC utlCompareStatementResults @SQL_SP1, @SQL_SP2

-- Compare just 2 SQL Statements
SET @SQL_SP1 = 'SELECT * FROM SomeDB.dbo.Table1 WHERE CreatedOn > ''2016-05-08'''
SET @SQL_SP1 = 'SELECT * FROM SomeDB.dbo.Table1 WHERE CreatedOn > ''2016-06-11'''
EXEC utlCompareStatementResults @SQL_SP1, @SQL_SP2
Run Code Online (Sandbox Code Playgroud)

SP 需要满足以下先决条件,这对于生产环境可能并不理想,但对于本地 QA、DEV 和测试环境非常有用。它在代码中使用了openrowset。

EXEC sp_configure 'show advanced options', 1
EXEC sp_configure 'ad hoc distributed queries', 1
EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
Run Code Online (Sandbox Code Playgroud)

这是存储过程的代码。

==================================================================================
    --== SUMMARY utlCompareStatementResults
    --==    - requires sp_configure 'show advanced options', 1
    --==    - requires sp_configure 'ad hoc distributed queries', 1
    --==    - maybe requires EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
    --==    - requires the RecordSet Output to have Unique ColumnNames (no duplicate columns)
    --==    - requires references in straight SQL to be fully qualified [dbname].[schema].[objects] but not within an SP
    --==    - requires references SP call to be fully qualifed [dbname].[schema].[spname] but not objects with the SP
    --== OUTPUT
    --==    Differences are returned 
    --==    If there is no recordset returned, then theres no differences
    --==    However if you are comparing 2 empty recordsets, it doesn't mean anything
    --== USAGE
    --==   DECLARE @SQL_SP1 VARCHAR(MAX)
    --==   DECLARE @SQL_SP2 VARCHAR(MAX)
    --==   -- Compare just 2 SQL Statements
    --==   SET @SQL_SP1 = 'SELECT * FROM SomeDB.dbo.Table1 WHERE CreatedOn > ''2016-05-08'''
    --==   SET @SQL_SP1 = 'SELECT * FROM SomeDB.dbo.Table1 WHERE CreatedOn > ''2016-06-11'''
    --==   EXEC utlCompareStatementResults @SQL_SP1, @SQL_SP2
    --==
    --==   -- Compare results of 2 Stored Procs
    --==   SET @SQL_SP1 = 'EXEC SomeDB.dbo.[usp_GetWithTheProgram_OLD] 100, ''SomeParamX'''
    --==   SET @SQL_SP1 = 'EXEC SomeDB.dbo.[usp_GetWithTheProgram_NEW] 50, ''SomeParamX'''
    --==   EXEC utlCompareStatementResults @SQL_SP1, @SQL_SP2
    --==================================================================================
    CREATE PROCEDURE utlCompareStatementResults
       @SQL_SP1 VARCHAR(MAX),
       @SQL_SP2 VARCHAR(MAX)
    AS
    BEGIN
        DECLARE @TABLE1 VARCHAR(200)
        DECLARE @TABLE2 VARCHAR(200)
        DECLARE @SQL_OPENROWSET VARCHAR(MAX) 
        DECLARE @CONNECTION VARCHAR(100)

        SET @CONNECTION = 'server='+@@SERVERNAME+';Trusted_Connection=yes'

        SET @SQL_SP1 = REPLACE(@SQL_SP1, '''','''''')
        SET @SQL_SP2 = REPLACE(@SQL_SP2, '''','''''')

        SET @TABLE1 = '#' + SUBSTRING(CONVERT(VARCHAR(250),NEWID()), 1, 8)
        SET @TABLE2 = '#' + SUBSTRING(CONVERT(VARCHAR(250),NEWID()), 1, 8)

        SET @SQL_OPENROWSET =
        'SELECT * ' + ' ' +
        'INTO ' + @TABLE1 + ' ' +
        'FROM OPENROWSET(''SQLNCLI'', ' + '''' + @CONNECTION + '''' +
                        ',''' + @SQL_SP1 +'''); ' +
        'SELECT * ' + ' ' +
        'INTO ' + @TABLE2 + ' ' +
        'FROM OPENROWSET(''SQLNCLI'', ' + '''' + @CONNECTION + '''' +
                        ',''' + @SQL_SP2 +'''); ' +
        '(SELECT * FROM ' + @TABLE1 + ' EXCEPT SELECT * FROM ' + @TABLE2 + ') '  +
        ' UNION ALL ' +
        '(SELECT * FROM ' + @TABLE2 + ' EXCEPT SELECT * FROM ' + @TABLE1 + '); ' +
        'DROP TABLE ' + @TABLE1 + '; ' +
        'DROP TABLE ' + @TABLE2 + '; '
        PRINT @SQL_OPENROWSET
        EXEC (@SQL_OPENROWSET)
        PRINT 'DifferenceCount: ' + CONVERT(VARCHAR(100), @@ROWCOUNT)
    END
Run Code Online (Sandbox Code Playgroud)