我正在稍微修改一个sql server 2005存储过程的性能,我想快速确保旧的存储过程和新的存储过程返回完全相同的结果(列是相同的,我想确保行是相同的)。
在sql server 2005中有一种简单的方法吗?
答案 0 :(得分:47)
你可以使用except结构来匹配两个查询。
select * from (select * from query1) as query1
except
select * from (select * from query2) as query2
编辑:
然后反转查询以查找与query2的差异作为驱动程序:
select * from (select * from query2) as query2
except
select * from (select * from query1) as query1
答案 1 :(得分:3)
create table #OldProcResults (
<Blah>
)
create table #NewProcResults (
<Blih>
)
insert into #OldProcResults
exec MyOldProc
insert into #NewProcResults
exec MyNewProc
然后使用Jabs的答案来比较两个表格。
答案 2 :(得分:2)
下面的存储过程将比较2个存储过程的输出结果集或2个语句。这里的关键是SP 不需要知道结果集的结构或架构,因此您可以任意测试任何SP。如果输出相同,它将返回0行。此解决方案在SQL Server中使用openrowset命令。 以下是存储过程的一些示例用法
EXEC sp_configure 'show advanced options', 1
EXEC sp_configure 'ad hoc distributed queries', 1
EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
SP需要以下先决条件,这可能不适合生产环境,但对本地QA,DEV和测试环境非常有用。它在代码中使用openrowset。
==================================================================================
--== 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
以下是存储过程的代码。
$server = "server1"
$source_dir = "\\server2\QlikView"
$processing_dir = "M:\script_test\processing"
$processed_dir = ""
$user = 'Domain\user1'
$Password = '******'
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $User, $SecurePassword
Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {
param ($server,$source_dir,$processing_dir)
echo "$source_dir"
Test-path $source_dir
copy-item -Path $source_dir\* -Destination M:\script_test
} -ArgumentList $server,$source_dir,$processing_dir
答案 3 :(得分:2)
要完成@jabs的答案,您可以使用以下模板来获取两个查询之间的区别:
WITH q1 AS (<INSERT_QUERY_1_HERE>)
, q2 AS (<INSERT_QUERY_2_HERE>)
SELECT * FROM q1 EXCEPT SELECT * FROM q2
UNION ALL (
SELECT * FROM q2 EXCEPT SELECT * FROM q1);
示例1:由于查询相同,因此返回0行
WITH q1 AS (SELECT * FROM my_table)
, q2 AS (SELECT * FROM my_table)
SELECT * FROM q1 EXCEPT SELECT * FROM q2
UNION ALL (
SELECT * FROM q2 EXCEPT SELECT * FROM q1);
示例2:这将返回查询之间的不同行(其中foo = 'bar'
)
WITH q1 AS (SELECT * FROM my_table)
, q2 AS (SELECT * FROM my_table WHERE foo <> 'bar')
SELECT * FROM q1 EXCEPT SELECT * FROM q2
UNION ALL (
SELECT * FROM q2 EXCEPT SELECT * FROM q1);
示例3:只是为了好玩,您可以检查示例2中的查询与查询foo = 'bar'
所在的行是否相同。
WITH q1 AS (
WITH q1 AS (SELECT * FROM my_table)
, q2 AS (SELECT * FROM my_table WHERE foo <> 'bar')
SELECT * FROM q1 EXCEPT SELECT * FROM q2
UNION ALL (
SELECT * FROM q2 EXCEPT SELECT * FROM q1)
)
, q2 AS (SELECT * FROM my_table WHERE foo = 'bar')
SELECT * FROM q1 EXCEPT SELECT * FROM q2
UNION ALL (
SELECT * FROM q2 EXCEPT SELECT * FROM q1);
答案 4 :(得分:0)
创建两个临时表,每个过程一个。 运行该过程以将行插入相应的表中。
然后从另一个MINUS select *中选择*,反之亦然
答案 5 :(得分:0)
EXCEPT是比较两个查询的关键(如@jabs所述)。
SELECT count(*), * FROM "query 1 here"
EXCEPT
SELECT count(*), * FROM "query 2 here"
为每个查询添加count(*)
,以确保两个查询的结果相同。万一有些重复的行被除外删除。