Reputation:
I need to compare ALL fields in two tables... they are the same size (four lines) and have the same amount of columns (five columns). The logic I'm looking for is...
If (table 1 = table 2)
do something
Else
do something else
In SQL I wrote something like...
If (Select * from table 1 = select * from table 2)
do something
else
do something else
THIS DOESN'T WORK!!!
I tried doing EXCEPT and UNION ALL statements... but I don't need to know the row that is different or even the values that are different, I just need to know BOOLEAN 'yes' the tables are different or 'no' they are not.
Upvotes: 1
Views: 16496
Reputation: 1
being tired to write all the columns new every time I expanded Wiretaps code.
"exec CompareTables table1, table2" will do the Job easier:
CREATE PROCEDURE [dbo].[CompareTables](@table1 varchar(100),
@table2 Varchar(100))
AS
-- Table1, Table2 are the tables or views to compare.
-- The columns of both tables are acquired from the table definition
-- ordered by the ordinal position
-- The result is all rows from either table that do NOT match
-- the other table in all columns specified, along with which table that
-- row is from.
declare @SQL varchar(8000);
declare @T1ColumnList varchar(1000);
SET @T1ColumnList = (
Select TOP 1 Stuff(
(
Select ',' + C.COLUMN_NAME
From INFORMATION_SCHEMA.COLUMNS As C
Where C.TABLE_SCHEMA = T.TABLE_SCHEMA
And C.TABLE_NAME = T.TABLE_NAME
Order By C.ORDINAL_POSITION
For Xml Path('')
), 1, 1, '') As Columns
From INFORMATION_SCHEMA.TABLES As T WHERE T.TABLE_NAME=@table1)
declare @T2ColumnList varchar(1000);
SET @T2ColumnList = (
Select TOP 1 Stuff(
(
Select ',' + C.COLUMN_NAME
From INFORMATION_SCHEMA.COLUMNS As C
Where C.TABLE_SCHEMA = T.TABLE_SCHEMA
And C.TABLE_NAME = T.TABLE_NAME
Order By C.ORDINAL_POSITION
For Xml Path('')
), 1, 1, '') As Columns
From INFORMATION_SCHEMA.TABLES As T WHERE T.TABLE_NAME=@table2)
set @SQL = 'SELECT ''' + @table1 + ''' AS TableName, ' + @t1ColumnList +
' FROM ' + @Table1 + ' UNION ALL SELECT ''' + @table2 + ''' As TableName, ' +
@t2ColumnList + ' FROM ' + @Table2
set @SQL = 'SELECT Max(TableName) as TableName, ' + @t1ColumnList +
' FROM (' + @SQL + ') A GROUP BY ' + @t1ColumnList +
' HAVING COUNT(*) = 1'
exec ( @SQL)
GO
Upvotes: 0
Reputation: 76952
If you want to compare only few columns (or tables with 2-5 columns), you may use this FULL JOIN
(not tested):
select COUNT(*) AS UnmatchedRows
from table1 t1
full join table2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2
and t1.col3 = t2.col3
and t1.col4 = t2.col4
and t1.col5 = t2.col5
where COALESCE(t1.col1, t2.col1) IS NULL
Still the solution referenced by Druid is very cool.
Upvotes: 0
Reputation: 40289
[Revised]
Here's how you'd do this with "SELECT...EXCEPT...":
IF not exists(select *
from MyTable
except select *
from MyOtherTable)
and not exists(select *
from MyOtherTable
except select *
from MyTable)
PRINT 'They match'
ELSE
PRINT 'They do not match'
A bit quicker to write, unless you need to compare fewer than all the columns. This will require four table scans, so you should compare and contrast performance with the UNION strategies presented. In my experience SELECT...EXCEPT... tends to run very quickly -- I'd guess because all the unioning and column comparing is occuring internally.
Upvotes: 1
Reputation: 781
Something like this should work, using Exist/Not Exists - then it's up to you how to interpret either getting or not getting a row back as True or False. The actual syntax will depend on the database. This is Transact-SQL
Create table A
( one int, two int, three int , four int)
Create table B
( one int, two int, three int, four int)
insert A values ( 1,2,3,4)
insert B values( 1,2,3,4)
select * from A a
where exists ( select 1 from B b where
a.one = b.one
and a.two = b.two
and a.three = b.three
and a.four = b.four)
one two three four
1 2 3 4
Upvotes: 0
Reputation: 2793
ALTER PROCEDURE dbo.CompareTables
(
@table1 VARCHAR(100),
@table2 VARCHAR(100),
@T1ColumnList VARCHAR(1000),
@T2ColumnList VARCHAR(1000) = ''
)
AS
/*
Table1, Table2 are the tables or views to compare.
T1ColumnList is the list of columns to compare, from table1.
Just list them comma-separated, like in a GROUP BY clause.
If T2ColumnList is not specified, it is assumed to be the same
as T1ColumnList. Otherwise, list the columns of Table2 in
the same order as the columns in table1 that you wish to compare.
The result is all rows from either table that do NOT match
the other table in all columns specified, along with which table that
row is from.
*/
DECLARE @SQL VARCHAR(8000)
IF @t2ColumnList = '' SET @T2ColumnList = @T1ColumnList
SET @SQL = 'SELECT ''' + @table1 + ''' AS TableName, ' + @t1ColumnList +
' FROM ' + @Table1 + ' UNION ALL SELECT ''' + @table2 + ''' As TableName, ' +
@t2ColumnList + ' FROM ' + @Table2
SET @SQL = 'SELECT Max(TableName) as TableName, ' + @t1ColumnList +
' FROM (' + @SQL + ') A GROUP BY ' + @t1ColumnList +
' HAVING COUNT(*) = 1'
EXEC ( @SQL)
Upvotes: 0
Reputation: 6453
This blog post explains how to do this:
The shortest, fastest, and easiest way to compare two tables in SQL Server: UNION
Upvotes: 9