Move row from one table to another? - sql-server

I have two tables with the same column definitions. I need to move (not copy) a row from one table to another. Before I go off and use INSERT INTO/DELETE (in a transaction), is there a smarter way?
SQL Server 2005

for SQL Server 2005 and up, try the OUTPUT Clause (Transact-SQL) clause:
DELETE OldTable
OUTPUT DELETED.col1, DELETED.col2...
INTO NewTable
WHERE ID=...
Working example:
DECLARE #OldTable table(col1 int, col2 varchar(5), col3 char(5), col4 datetime)
DECLARE #NewTable table(col1 int, column2 varchar(5), col3 int , col_date char(23), extravalue int, othervalue varchar(5))
INSERT #OldTable VALUES (1 , 'AAA' ,'A' ,'1/1/2010' )
INSERT #OldTable VALUES (2 , 'BBB' ,'12' ,'2010-02-02 10:11:22')
INSERT #OldTable VALUES (3 , 'CCC' ,null ,null )
INSERT #OldTable VALUES (4 , 'B' ,'bb' ,'2010-03-02' )
DELETE #OldTable
OUTPUT DELETED.col1
,DELETED.col2
,CASE
WHEN ISNUMERIC(DELETED.col3)=1 THEN DELETED.col3
ELSE NULL END
,DELETED.col4
,CONVERT(varchar(5),DELETED.col1)+'!!'
INTO #NewTable (col1, column2, col3, col_date, othervalue)
OUTPUT 'Rows Deleted: ', DELETED.* --this line returns a result set shown in the OUTPUT below
WHERE col1 IN (2,4)
SELECT * FROM #NewTable
OUTPUT:
col1 col2 col3 col4
-------------- ----------- ----- ----- -----------------------
Rows Deleted: 2 BBB 12 2010-02-02 10:11:22.000
Rows Deleted: 4 B bb 2010-03-02 00:00:00.000
(2 row(s) affected)
col1 column2 col3 col_date extravalue othervalue
----------- ------- ----------- ----------------------- ----------- ----------
2 BBB 12 Feb 2 2010 10:11AM NULL 2!!
4 B NULL Mar 2 2010 12:00AM NULL 4!!
(2 row(s) affected)

You can try Insert into abc (a,b,c)
select(a,b,c) from def
doing above so will insert column a, b,c of def into column a,b,c of abc. after inserting run a delete table, drop table or truncate whatever is your criteria.
sample is:
Begin
Begin try
Begin Transaction
Insert into emp(name, department, salary)
Select empName,empDepartment,empSal from employees
Where employees.empID = 211
Truncate table employees
End Transaction
End try
Begin Catch
if ##Error > 0
Rollback Transaction
End Catch
End

There is no such thing as a MOVE command in SQL.
You'll have to first insert from table 1 to table 2
Then remove the copy from table 1.

No, you are pretty much stuck with insert and delete wrapped inside a transaction

INSERT dbo.newtable(
name,
department,
Salary
) SELECT
name,
FirstName,
Lastname
FROM (
DELETE dbo.oldtable
OUTPUT
DELETED.name,
DELETED.department,
DELETED.Salary
WHERE ID IN ( 1001, 1003, 1005 )
) AS RowsToMove
SELECT * FROM dbo.newtable
SELECT * FROM dbo.oldtable

Related

How to update column with if-else-if condition

I am new to SQL Server and on the learning phase. I wanted to perform following task.
I have two table Table1 and Table2. I want to loop the row of Table1 to check if value matches with any row of Table2.
Table1:
ID Name Nationality DOB Priority
--------------------------------------------
1 Sujan Nepali 1996 NULL
2 Sujan Nepali 1999 NULL
3 Sujan Chinese 1996 NULL
4 Sujan Chinese 1888 NULL
Table 2:
ID Name Nationality DOB Address Rank
---------------------------------------------------
1 Sujan Nepali 1996 Kathmandu 1
In Table1 with ID 1 matches all value of same column name in Table2. I need to Update priority of it as 1.
In ID 2 DOB is different and Name and Nationality matches so Update priority as 2.
In ID 3 Name and Year is same as of Table2, so Update priority as 3.
In ID 4 only Name is same, so Update priority as 4.
Expected Output:
Table1:
ID Name Nationality DOB Priority
---------------------------------------------
1 Sujan Nepali 1996 1
2 Sujan Nepali 1999 2
3 Sujan Chinese 1996 3
4 Sujan Chinese 1888 4
I have used CASE but need to perform using IF ELSE IF condition. Any help would be appreciated.
I guess you need something like this. Cross join two tables and look for columns that match each other. According to that make updates.
declare #table1 table (ID int, Name varchar(100), Nationality varchar(100), DOB int, Priority int)
insert into #table1
values
(1, 'Sujan', 'Nepali', 1996, NULL)
, (2, 'Sujan', 'Nepali', 1999, NULL)
, (3, 'Sujan', 'Chinese', 1996, NULL)
, (4, 'Sujan', 'Chinese', 1888, NULL)
declare #table2 table (ID int, Name varchar(100), Nationality varchar(100), DOB int, Address varchar(100), Rank int)
insert into #table2 values (1, 'Sujan', 'Nepali', 1996, 'Kathmandu', 1)
;with cte as (
select
a.*, rnk = row_number() over (order by case when a.Name = b.Name then 100 else 0 end
+ case when a.Nationality = b.Nationality then 10 else 0 end
+ case when a.DOB = b.DOB then 1 else 0 end desc)
from
#table1 a
join #table2 b on a.Name = b.Name
)
update cte
set priority = rnk
select * from #table1
Here's a rextester demo
Unless this is homework I see no reason to use if constructs.
update table1 set priority = (
select min(case
when table2.id = table1.id and ... then 1
when ... then 2
when ... then 3
...
end
from table2
)
Just make sure the branches go in order of highest to lowest priority.

Check if we have matching data for two columns inside a group

I have some data like:
ID Col1 Col2
--- ----- -----
5 10 10 <--- Matching
5 11 10
5 15 10
6 22 22 <--- Matching
6 10 22
6 12 22
And I tried a query like:
SELECT ID FROM #Table
GROUP BY ID HAVING MAX(COL1) = MAX(COL2)
But, this only returns id 6, as max for group 5 Col1 is 15 which does not match with Col2 max value 10 for group 5. Is there any way to get all groups 5 & 6 which has matching data 10 & 22 in Col1 & Col2?
Expected Output:
ID
---
5
6
Just showing the ID of matching group.
It is as smiple as this:
DECLARE #tblQuestion AS Table
(
ID int,
col1 int,
col2 int
)
INSERT INTO #tblQuestion VALUES
(5,10,10),
(5,11,10),
(5,15,10),
(6,22,22),
(6,10,22),
(6,12,22);
select distinct ID from #tblQuestion a
where a.col1 = a.col2
TRY THIS:
SELECT DISTINCT ID
FROM table_name
WHERE (col1 - col2) = 0
Try the below query. Maybe it is your requirement, first get same value rows and then get max value from group:
DECLARE #tblQuestion AS Table
(
ID INT,
Col1 INt,
Col2 INT
)
INSERT INTO #tblQuestion VALUES(5,10,10)
INSERT INTO #tblQuestion VALUES(5,10,21)
INSERT INTO #tblQuestion VALUES(5,27,10)
INSERT INTO #tblQuestion VALUES(6,10,12)
INSERT INTO #tblQuestion VALUES(6,15,15)
INSERT INTO #tblQuestion VALUES(6,25,25)
INSERT INTO #tblQuestion VALUES(6,18,10)
;WITH T AS
(
SELECT
*,
ROW_NUMBER() OVER (Partition BY ID order by Col1 Desc) AS PartNo
FROM #tblQuestion
WHERE Col1=Col2
)
SELECT ID,Col1,Col2 FROM T
WHERE PartNo=1
ORDER BY ID, Col1 DESC
Output:
Try this:
SELECT distinct ID FROM table_name
where COL1 = COL2
In my case I tried a different approach, as I needed to use GROUP BY & HAVING clause due to my original query complexity like:
SELECT DISTINCT ID FROM #Table
GROUP BY ID
HAVING MAX(CASE WHEN Col1 = Col2 THEN 1 ELSE 0 END) = 1
Just wanted to share my solution here, in case anyone is interested.

Sql server table has has month name as column, how to convert into multiple rows datewise [duplicate]

I have a scenario where I need to convert columns of table to rows
eg -
table - stocks:
ScripName ScripCode Price
-----------------------------------------
20 MICRONS 533022 39
I need to represent the table in the following format, but I just need this kind of representation for single row
ColName ColValue
-----------------------------
ScripName 20 MICRONS
ScripCode 533022
Price 39
so that I can directly bind the data to the datalist control.
Sound like you want to UNPIVOT
Sample from books online:
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Returns:
VendorID Employee Orders
---------- ---------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
see also: Unpivot SQL thingie and the unpivot tag
declare #T table (ScripName varchar(50), ScripCode varchar(50), Price int)
insert into #T values ('20 MICRONS', '533022', 39)
select
'ScripName' as ColName,
ScripName as ColValue
from #T
union all
select
'ScripCode' as ColName,
ScripCode as ColValue
from #T
union all
select
'Price' as ColName,
cast(Price as varchar(50)) as ColValue
from #T
select 'ScriptName', scriptName from table
union all
select 'ScriptCode', scriptCode from table
union all
select 'Price', price from table
As an alternative:
Using CROSS APPLY and VALUES performs this operation quite simply and efficiently with just a single pass of the table (unlike union queries that do one pass for every column)
SELECT
ca.ColName, ca.ColValue
FROM YOurTable
CROSS APPLY (
Values
('ScripName' , ScripName),
('ScripCode' , ScripCode),
('Price' , cast(Price as varchar(50)) )
) as CA (ColName, ColValue)
Personally I find this syntax easier than using unpivot.
NB: You must take care that all source columns are converted into compatible types for the single value column
DECLARE #TABLE TABLE
(RowNo INT,ScripName VARCHAR(10),ScripCode VARCHAR(10)
,Price VARCHAR(10))
INSERT INTO #TABLE VALUES
(1,'20 MICRONS ','533022','39')
SELECT ColumnName,ColumnValue from #Table
Unpivot(ColumnValue For ColumnName IN (ScripName,ScripCode,Price)) AS H
i solved the query this way
SELECT
ca.ID, ca.[Name]
FROM [Emp2]
CROSS APPLY (
Values
('ID' , cast(ID as varchar)),
('[Name]' , Name)
) as CA (ID, Name)
output look like
ID Name
------ --------------------------------------------------
ID 1
[Name] Joy
ID 2
[Name] jean
ID 4
[Name] paul
CREATE TABLE #ORIGINAL
(
COUNTRY VARCHAR(50),
MALE_CRICKETER VARCHAR(50),
FEMALE_CRICKETER VARCHAR(50),
MALE_STAR VARCHAR(50),
FEMALE_STAR VARCHAR(50),
)
select * from #ORIGINAL
SELECT COUNTRY, ca.GENDER, ca.STAR, ca.CRICKETR
FROM #ORIGINAL
CROSS APPLY (
Values
('M', MALE_CRICKETER, MALE_STAR),
('F', FEMALE_CRICKETER, FEMALE_STAR)
) as CA (GENDER, CRICKETR, STAR)

Converting Columns into rows with their respective data in sql server

I have a scenario where I need to convert columns of table to rows
eg -
table - stocks:
ScripName ScripCode Price
-----------------------------------------
20 MICRONS 533022 39
I need to represent the table in the following format, but I just need this kind of representation for single row
ColName ColValue
-----------------------------
ScripName 20 MICRONS
ScripCode 533022
Price 39
so that I can directly bind the data to the datalist control.
Sound like you want to UNPIVOT
Sample from books online:
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
Returns:
VendorID Employee Orders
---------- ---------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
see also: Unpivot SQL thingie and the unpivot tag
declare #T table (ScripName varchar(50), ScripCode varchar(50), Price int)
insert into #T values ('20 MICRONS', '533022', 39)
select
'ScripName' as ColName,
ScripName as ColValue
from #T
union all
select
'ScripCode' as ColName,
ScripCode as ColValue
from #T
union all
select
'Price' as ColName,
cast(Price as varchar(50)) as ColValue
from #T
select 'ScriptName', scriptName from table
union all
select 'ScriptCode', scriptCode from table
union all
select 'Price', price from table
As an alternative:
Using CROSS APPLY and VALUES performs this operation quite simply and efficiently with just a single pass of the table (unlike union queries that do one pass for every column)
SELECT
ca.ColName, ca.ColValue
FROM YOurTable
CROSS APPLY (
Values
('ScripName' , ScripName),
('ScripCode' , ScripCode),
('Price' , cast(Price as varchar(50)) )
) as CA (ColName, ColValue)
Personally I find this syntax easier than using unpivot.
NB: You must take care that all source columns are converted into compatible types for the single value column
DECLARE #TABLE TABLE
(RowNo INT,ScripName VARCHAR(10),ScripCode VARCHAR(10)
,Price VARCHAR(10))
INSERT INTO #TABLE VALUES
(1,'20 MICRONS ','533022','39')
SELECT ColumnName,ColumnValue from #Table
Unpivot(ColumnValue For ColumnName IN (ScripName,ScripCode,Price)) AS H
i solved the query this way
SELECT
ca.ID, ca.[Name]
FROM [Emp2]
CROSS APPLY (
Values
('ID' , cast(ID as varchar)),
('[Name]' , Name)
) as CA (ID, Name)
output look like
ID Name
------ --------------------------------------------------
ID 1
[Name] Joy
ID 2
[Name] jean
ID 4
[Name] paul
CREATE TABLE #ORIGINAL
(
COUNTRY VARCHAR(50),
MALE_CRICKETER VARCHAR(50),
FEMALE_CRICKETER VARCHAR(50),
MALE_STAR VARCHAR(50),
FEMALE_STAR VARCHAR(50),
)
select * from #ORIGINAL
SELECT COUNTRY, ca.GENDER, ca.STAR, ca.CRICKETR
FROM #ORIGINAL
CROSS APPLY (
Values
('M', MALE_CRICKETER, MALE_STAR),
('F', FEMALE_CRICKETER, FEMALE_STAR)
) as CA (GENDER, CRICKETR, STAR)

Need compare tables utility for SQL Server

Command line or library "compare tables" utility for SQL server with comprehensive diff output to a file in .Net
I can't find anything like that. Commercial or free ( XSQL Lite is suitable for my case and ) tools show diffs in grids with possibility to export to CSV. Also they generate sync SQL scripts when run from command line. What I need is an output as a comprehensive report ( XML , HTML ) suitable for parsing so that I would be able to show similar diff grid in my application ( updated old/new values for each column , added - all values for row , deleted - all values for row and etc... ) .
Since it sounds like you only want to show the diffs in your application, just write your own query, it isn't that hard, here is an example:
DECLARE #TableA table (RowID int, Col1 int, Col2 varchar(5), Col3 datetime)
DECLARE #TableB table (RowID int, Col1 int, Col2 varchar(5), Col3 datetime)
set nocount on
INSERT #TableA VALUES( 1,111,'AAA','1/1/2010')
INSERT #TableA VALUES( 2,222,'BBB','1/1/2010')
INSERT #TableA VALUES( 3,333,'CCC','1/1/2010')
INSERT #TableA VALUES( 4,444,'DDD','1/1/2010')
INSERT #TableA VALUES( 5,555,'EEE','1/1/2010')
INSERT #TableA VALUES( 6,666,'FFF','1/1/2010')
INSERT #TableA VALUES( 7,777,'GGG','1/1/2010')
INSERT #TableA VALUES( 9,888,'HHH','1/1/2010')
INSERT #TableA VALUES(10,111,'III','1/1/2010')
INSERT #TableB VALUES( 1,111,'AAA','1/1/2010')
INSERT #TableB VALUES( 3,333,'CCC','1/1/2010')
INSERT #TableB VALUES( 4,444,'DD' ,'1/1/2010')
INSERT #TableB VALUES( 5,555,'EEE','2/2/2010')
INSERT #TableB VALUES( 6,666,'FFF','1/1/2010')
INSERT #TableB VALUES( 7,777,'GGG','1/1/2010')
INSERT #TableB VALUES( 8,888,'ZZZ','1/1/2010')
INSERT #TableB VALUES( 9,888,'HHH','1/1/2010')
INSERT #TableB VALUES(10,111,'III','1/1/2010')
set nocount off
SELECT
a.RowID, CASE WHEN b.RowID IS NULL THEN 'A' ELSE '' END AS RowsOnlyExistsIn
,a.Col1,b.Col1, CASE WHEN a.Col1=b.Col1 OR (COALESCE(a.Col1,b.Col1) IS NULL) THEN 'N' ELSE 'Y' END AS Col1Diff
,a.Col2,b.Col2, CASE WHEN a.Col2=b.Col2 OR (COALESCE(a.Col2,b.Col2) IS NULL) THEN 'N' ELSE 'Y' END AS Col2Diff
,a.Col3,b.Col3, CASE WHEN a.Col3=b.Col3 OR (COALESCE(a.Col3,b.Col3) IS NULL) THEN 'N' ELSE 'Y' END AS Col3Diff
FROM #TableA a
LEFT OUTER JOIN #TableB b On a.RowID=b.RowID
UNION ALL
SELECT
b.RowID, 'B' AS RowsOnlyExistsIn
,null,b.Col1, 'Y' AS Col1Diff
,null,b.Col2, 'Y' AS Col2Diff
,null,b.Col3, 'Y' AS Col3Diff
FROM #TableB b
WHERE b.RowID NOT IN (SELECT RowID FROM #TableA)
ORDER BY 1
OUTPUT:
RowID RowsOnlyExistsIn Col1 Col1 Col1Diff Col2 Col2 Col2Diff Col3 Col3 Col3Diff
----------- ---------------- ----------- ----------- -------- ----- ----- -------- ----------------------- ----------------------- --------
1 111 111 N AAA AAA N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
2 A 222 NULL Y BBB NULL Y 2010-01-01 00:00:00.000 NULL Y
3 333 333 N CCC CCC N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
4 444 444 N DDD DD Y 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
5 555 555 N EEE EEE N 2010-01-01 00:00:00.000 2010-02-02 00:00:00.000 Y
6 666 666 N FFF FFF N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
7 777 777 N GGG GGG N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
8 B NULL 888 Y NULL ZZZ Y NULL 2010-01-01 00:00:00.000 Y
9 888 888 N HHH HHH N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
10 111 111 N III III N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
(10 row(s) affected)
of course you would need to generate this dynamically so any two tables could be compared. This query will get you the columns of any tables:
SELECT
*
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_CATALOG ='database'
AND TABLE_SCHEMA='dbo'
AND TABLE_NAME ='yourtable'
ORDER BY ORDINAL_POSITION
here is a quick dynamic sql version (I attempt to pull in all the PK columns and use them to dynamically join the tables, but I only tested it on tables with 1 PK column):
set up for dynamic sql
CREATE TABLE TableA (RowID int primary key, Col1 int, Col2 varchar(5), Col3 datetime)
CREATE TABLE TableB (RowID int primary key, Col1 int, Col2 varchar(5), Col3 datetime)
set nocount on
INSERT TableA VALUES( 1,111,'AAA','1/1/2010')
INSERT TableA VALUES( 2,222,'BBB','1/1/2010')
INSERT TableA VALUES( 3,333,'CCC','1/1/2010')
INSERT TableA VALUES( 4,444,'DDD','1/1/2010')
INSERT TableA VALUES( 5,555,'EEE','1/1/2010')
INSERT TableA VALUES( 6,666,'FFF','1/1/2010')
INSERT TableA VALUES( 7,777,'GGG','1/1/2010')
INSERT TableA VALUES( 9,888,'HHH','1/1/2010')
INSERT TableA VALUES(10,111,'III','1/1/2010')
INSERT TableB VALUES( 1,111,'AAA','1/1/2010')
INSERT TableB VALUES( 3,333,'CCC','1/1/2010')
INSERT TableB VALUES( 4,444,'DD' ,'1/1/2010')
INSERT TableB VALUES( 5,555,'EEE','2/2/2010')
INSERT TableB VALUES( 6,666,'FFF','1/1/2010')
INSERT TableB VALUES( 7,777,'GGG','1/1/2010')
INSERT TableB VALUES( 8,888,'ZZZ','1/1/2010')
INSERT TableB VALUES( 9,888,'HHH','1/1/2010')
INSERT TableB VALUES(10,111,'III','1/1/2010')
set nocount off
dynamic sql
DECLARE #TableA sysname
,#TableB sysname
,#SQLa varchar(max)
,#SQLb varchar(max)
,#SQL varchar(max)
SELECT #TableA='TableA'
,#TableB='TableB'
,#SQLa=NULL
,#SQLb=NULL
DECLARE #PKs table (RowID int identity(1,1) primary key, PkColumn sysname)
DECLARE #index_id int
,#PK sysname
,#i int
SELECT #index_id=index_id from sys.indexes where object_id=OBJECT_ID(#TableA) AND is_primary_key=1
SELECT #PK=''
,#i=0
while (#PK is not null)
BEGIN
SET #i=#i+1
SELECT #PK = index_col(#TableA, #index_id, #i)
IF #PK IS NULL BREAK
INSERT INTO #PKs (PkColumn) VALUES (#PK)
END
SELECT #SQLa=''
,#SQLb=''''+#TableB+''' '
SELECT
#SQLa=#SQLa+' ,a.'+COLUMN_NAME+',b.'+COLUMN_NAME+', CASE WHEN a.'+COLUMN_NAME+'=b.'+COLUMN_NAME+' OR (COALESCE(a.'+COLUMN_NAME+',b.'+COLUMN_NAME+') IS NULL) THEN ''N'' ELSE ''Y'' END AS '+COLUMN_NAME+'Diff '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME =#TableA
ORDER BY ORDINAL_POSITION
SELECT
#SQLb=#SQLb+' ,null,b.'+COLUMN_NAME+', ''Y'' AS '+COLUMN_NAME+'Diff'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME =#TableA
ORDER BY ORDINAL_POSITION
SET #SQL='SELECT CASE WHEN b.'+(SELECT PkColumn FROM #PKs WHERE RowID=1)+' IS NULL THEN '''+#TableA+''' ELSE '''' END AS RowsOnlyExistsIn '
+#SQLa
+'FROM '+#TableA+' a LEFT OUTER JOIN '+#TableB+' b ON '
SELECT
#SQL=#SQL+ CASE WHEN RowID!=1 THEN 'AND ' ELSE '' END +'a.'+PkColumn+'=b.'+PkColumn+' '
FROM #PKs
SET #SQL=#SQL+' UNION ALL SELECT '
+#SQLb
+' FROM '+#TableB+' b LEFT OUTER JOIN '+#TableA+' A ON '
SELECT
#SQL=#SQL+ CASE WHEN RowID!=1 THEN 'AND ' ELSE '' END +'b.'+PkColumn+'=a.'+PkColumn+' '
FROM #PKs
SET #SQL=#SQL+'WHERE a.'+(SELECT PkColumn FROM #PKs WHERE RowID=1)+' IS NULL ORDER BY 2,3'
EXEC(#SQL)
output:
RowsOnlyExistsIn RowID RowID RowIDDiff Col1 Col1 Col1Diff Col2 Col2 Col2Diff Col3 Col3 Col3Diff
---------------- ----------- ----------- --------- ----------- ----------- -------- ----- ----- -------- ----------------------- ----------------------- --------
TableB NULL 8 Y NULL 888 Y NULL ZZZ Y NULL 2010-01-01 00:00:00.000 Y
1 1 N 111 111 N AAA AAA N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
TableA 2 NULL Y 222 NULL Y BBB NULL Y 2010-01-01 00:00:00.000 NULL Y
3 3 N 333 333 N CCC CCC N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
4 4 N 444 444 N DDD DD Y 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
5 5 N 555 555 N EEE EEE N 2010-01-01 00:00:00.000 2010-02-02 00:00:00.000 Y
6 6 N 666 666 N FFF FFF N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
7 7 N 777 777 N GGG GGG N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
9 9 N 888 888 N HHH HHH N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
10 10 N 111 111 N III III N 2010-01-01 00:00:00.000 2010-01-01 00:00:00.000 N
(10 row(s) affected)
I;m assuming you want to compare data not schema and I'm assuming that the tables are in diff databases.
I would not do it in SQL but load the data in generic .Net DataSet, and iterate thru Table
object, columns and rows. This way one piece of code would work for any database table, no need for awkward dynamic SQL, however the downside is possible perf hit since you will need to load the data into a dataset - in this case just run the code on SQl server itself and dump the result files to a file share.
Open Source DiffKit will do all of that except the .NET part.
www.diffkit.org

Resources