How to compare two SQL tables and insert the difference using PowerShell - sql-server

I have total of 3 SQL Server tables called Temp_Hold_Inv, Hold_Inv and Daily_Proc.
Temp_Hold_Inv contains the latest data, Hold_Inv contain not up-to-date data.
I'm just wondering how can I compare between the Temp_Hold_Inv and Hold_inv table and if there is a difference then insert only the difference to Hold_Inv, Daily_Proc tables and add value in their additional columns.
Currently here is how my tables columns look like. Also here is how it should look when there is a new user aka difference in Temp_Hold_Inv table and insert it to the other two tables.
Temp_Hold_Inv
Hold EmpId Source Exist Type
KLM KLMNOE j.smit#g.com Yes Email
Hold_Inv
Id Hold EmpId Source Type CreatedDate
1 KLM KLMNOE j.smit#g.com Email 04/15/1996
Note: Id is auto-incremented. Also there is no Exist column here. Will need to pass current date automatically.
Daily_Proc
Id Hold EmpId Source Type Operation CreatedDate Status
1 KLM KLMNOE j.smit#g.com Email ADD 04/15/1996 New
This is my PowerShell script and I'm able get the difference but not sure how to insert the difference to Hold_Inv and Daily_Proc tables.
$Server = 'ServerName'
$Database = 'DbName'
$query2 = "
SELECT 'Temp_Hold_Inv' AS SRC, T1.*
FROM (
SELECT Hold, EmpId, Source FROM Temp_Hold_Inv
EXCEPT
SELECT Hold, EmpId, Source FROM Hold_Inv
) AS T1
UNION ALL
SELECT 'Hold_Inv' AS SRC, T2.*
FROM (
SELECT Hold, EmpId, Source FROM Hold_Inv
EXCEPT
SELECT Hold, EmpId, Source FROM Temp_Hold_Inv
) AS T2
;"
$dbData = Invoke-Sqlcmd -Query $query2 -ServerInstance $Server -Database $Database
Any help or suggestion will be really appreciated.

Related

How to remove sql records using PowerShell

I have this simple script that compare the two table and I'm just wondering how can I modify it so that it'll delete if there is a difference in Hold_Inv table.
So basically my Temp_Hold_Inv contain the latest data and I wanted to always in sync with my Hold_Inv table.
Let say a particular user is removed from Temp_Hold_Inv table but the data is already Existed in Hold_inv and Daily_Proc table then removed from those two table too after comparison.
Here I'm able to get the difference but not sure how to use $comparedResult to delete all the difference from Hold_Inv and Daily_Proc Table
$query2 = "
SELECT 'Temp_Hold_Inv' AS SRC, T1.*
FROM (
SELECT Hold, GID, Source FROM Temp_Hold_Inv
EXCEPT
SELECT Hold, GID, Source FROM Hold_Inv
) AS T1
UNION ALL
SELECT 'Hold_Inv' AS SRC, T2.*
FROM (
SELECT Hold, GID, Source FROM Hold_Inv
EXCEPT
SELECT Hold, GID, Source FROM Temp_Hold_Inv
) AS T2
;"
$compareResult = Invoke-Sqlcmd -Query $query2 -ServerInstance $Server -Database $Database
Any help or suggestion will be really appreciated.
You need a MERGE statement, but you need to work out what is the primary key of the table in order to match rows up.
$query2 = "
MERGE Hold_Inv WITH (HOLDLOCK) AS t
USING Temp_Hold_Inv AS s
ON t.SomePrimaryKey = s.SomePrimaryKey
WHEN MATCHED AND (
t.Hold <> s.Hold
OR t.Source <> s.Source)
THEN UPDATE SET
Hold = s.Hold
Source = s.Source
WHEN NOT MATCHED BY TARGET
THEN INSERT (Hold, GID, Source)
VALUES (Hold, GID, Source)
WHEN NOT MATCHED BY SOURCE
THEN DELETE
-- you can get output like this
-- OUTPUT $action, inserted.*, deleted.*
;"
Invoke-Sqlcmd -Query $query2 -ServerInstance $Server -Database $Database

How do I compare two columns from different tables in different databases?

Say I have Table_1 in Database_1 with 25 Columns
and say I have Table_2 in Database_2 with 19 Columns
I want to compare the columns in Table_1 and Table_2 and output Columns that exist in Table_1 but not in Table_2
I tried
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='Table_1'
EXCEPT
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='Table_2'
The problem is: If I am in Database_1 it only finds variables in Table_1 and return empty list for Table_2, if I am in Database_2 it only finds variables in Table_2 and returns empty list for Table_1. If say I am in Master, it returns empty list for both Table_1 and Table_2. How do I properly locate each table and their variables from one database?
You can access any database object from any database context by fully qualifying the object name in the form of database.schema.object.
Using SQL Server you are better off using the sys schema, which (if performance matters) is better than using the information_schema schema.
So you can do
select name
from database_1.sys.columns
where object_id=object_id(N'database_1.sys.table_1')
except
select name
from database_2.sys.columns
where object_id=object_id(N'database_2.sys.table_2')

How to compare varbinary data type in where clause

I have a linked server that is created to pull user details from a specific Organisation Unit with a scheduled sql job agent.
The table is created to hold user details has a column for ObjectGUID number and the type is defined as varbinary(50) (I am not sure why..).
The process checks if there is a new user by comparing the ObjectGUID number the saved Users table and if there is a new number then insert the new user in the table.
However I have noticed that the comparisons actually not really working properly.
SELECT
tbl.objectGUID AS UserGUID
FROM [dbo].[ActiveDirectoryUsers] tbl
WHERE tbl.objectGUID NOT IN (SELECT UserGUID FROM dbo.Users)
When I create a new user the new user is appearing in the ActiveDirectoryUsers view.
but when the where clause added to compare results with Users table then result is always empty. It looks like I need to cast or convert the varbinary to varchar then do the comparisons. I tried to cast the varbinary into varchar and uniqueidentifier but still it does not work.
Any idea how would I do the comparisons?
Update
CREATE VIEW [dbo].[ActiveDirectoryUsers] AS
SELECT "SAMAccountName" AS sAMAccountName, "mail" AS Email,
"objectGUID" AS objectGUID
FROM OpenQuery(ADSI, 'SELECT SAMAccountName, mail, objectGUID
FROM ''ldapconnectionstring.com''')
An example of objectGUID in the Users table
0x1DBCC071C69C8242B4895D42750969B1
You should not cast varbinary to smth particular to be able to use it in WHERE clause.
Your problem is that you use NOT IN where NULL values are present.
Try to execute my code first as it is (it will return 1 row) and then uncomment NULL value insert and execute it again.
This time you'll get 0 rows:
declare #t1 table (guid varbinary(50))
insert into #t1
values(0x1DBCC071C69C8242B4895D42750969B1)--, (null);
declare #t2 table (guid varbinary(50))
insert into #t2
values(0x1DBCC071C69C8242B4895D42750969B1), (0x1DBCC071C69C8242B4895D42750969B2);
select *
from #t2 t2
where t2.guid not in (select guid from #t1);
To fix your problem, try to use NOT EXISTS instead of NOT IN like this:
select *
from #t2 t2
where not exists (select *
from #t1 t1
where t1.guid = t2.guid);
In your case the code should be like this:
SELECT tbl.objectGUID AS UserGUID
FROM [dbo].[ActiveDirectoryUsers] tbl
WHERE not exists (SELECT *
FROM dbo.Users u
where u.UserGUID = tbl.objectGUID );

How I can save all the names of my tables into a new table from sql?

I have a huge database in Sql-Server and I need to get all the names of the tables into one new table that I have made. This can be done?
I appreciate your help.
The new table has the fields ID, TableName, Status. Id is the identity and status for now will be 1, not null
Use this query below to get all tables name from your database
SELECT name FROM sys.tables
Then you can do a insert query like -
insert into newtable(name) select * from sys.tables

vb.net comparing two databases then insert or delete

in vb.net how would you loop through database1 to check that all records in database2 exist in Database1 and the other way areound if a record exist in database1 and doesnt exist in database2 then delete it from database1.
so database2 is my reference
how can i do this using queries, also does it have to include nested looping?
note that the records are not in the same order
Thanks
This query will return all of the rows in the attached table that are not in the local version of the table
SELECT * FROM attachedTable
WHERE col1 NOT IN( SELECT lt.col1 FROM localTable as lt)
And this will do the converse, returning all rows in the local table that are not matched in the remote table.
SELECT * FROM localTable
WHERE col1 NOT IN( SELECT rt.col1 FROM attachedTable As rt)

Resources