how to see difference between 2 tables - sql

I have 2 tables: 1 temp and the other one is my main table.
Each day I would update my temp table and I want to update my main table based on the changes I made from the temp table.
Example: The first temp table contains an id and name. Then I insert the value from temp into the main table. But when I made changes from my temp like insert another id and name, I want my main table to compare and only insert the unique id from the temp table.

As you said, it seems like you have a table object named as temp table. If this is the case then you may use after insert trigger on temp table to insert new inserted value in your main table.
CREATE TRIGGER AfterINSERTTrigger on [Temptable]
FOR INSERT
AS DECLARE #id INT,
#col1 VARCHAR(50),
.
.
SELECT #id = ins.id FROM INSERTED ins;
SELECT #col1 = ins.col1 FROM INSERTED ins;
.
.
INSERT INTO [MainTable](
[id]
,[col1]
.
.)
VALUES (#id,
#col1,
.
.
.
);
PRINT 'We Successfully Fired the AFTER INSERT Triggers in SQL Server.'
GO
Similarly you can update your table on update of record in temptable using update trigger. You may find this link on more info on trigger. LINK
OR
If you are creating temp table object to get the new inserted record then use simple not in or not exists clause to get the newly inserted record.
Using NOT IN
insert into maintable ( id, col1, ...)
select Id , col1, .... from temptable
where id not in (select id from maintable)
Using NOT EXISTS
insert into maintable ( id, col1, ... )
select id, col1, ... from temptable as temp
where not exists (select id from maintable as main where main.id=temp.id)

You can use NOT EXISTS as follows
INSERT into main_table(
id, name,
...
)
SELECT
id,name,
...
FROM temp_table t
WHERE
NOT EXISTS(
SELECT 1
FROM main_table m
WHERE m.id = t.id
)
Cheers!!

Related

Multi column exist statement

I am trying to insert data to a table from another where data is not already exists
The table I am inserting the data into
CREATE TABLE #T(Name VARCHAR(10),Unit INT, Id INT)
INSERT INTO #T
VALUES('AAA',10,100),('AAB',11,102),('AAC',12,130)
The table I am selecting the data from
CREATE TABLE #T1(Name VARCHAR(10),TypeId INT,Unit INT, Id INT)
INSERT INTO #T1
VALUES('AAA',3,10,100),('AAA',3,10,106)
In this case I want to select ('AAA',3,10,106) from #T1 because AAA,106 combination not exists in #T
Basically what I want is to populate unique Name and Id combination
I tried below which doesn't seems to work
SELECT *
FROM #T1
WHERE NOT EXISTS(SELECT * FROM #T)
You have to somehow correlate the two tables:
SELECT *
FROM #T1
WHERE NOT EXISTS(SELECT *
FROM #T
WHERE #T1.Name = #T.Name AND #T1.ID = #T.ID)
The above query essentially says: get me those records of table #T1 which do not have a related record in #T having the same Name and ID values.
Your best bet is probably to use a insert statement with a subquery. Something like this:
SQL Insert Into w/Subquery - Checking If Not Exists
Edit: If you're still stuck, try this--
INSERT INTO #T (Name, Unit, Id)
SELECT Name, Unit, Id
FROM #T1
WHERE
NOT EXISTS (SELECT Name, Unit, Id FROM #T
WHERE #T.Name = #T1.Name AND #T.Unit = #T1.Unit AND #T.Id = #T1.Id)

Update while copy records

I want to copy records from one table to another. While doing this I want to set a flag of those records I copy.
This is how I would do it (simplified):
BEGIN TRANSACTION copyTran
insert into destination_table (name)
select top 100 name
from source_table WITH (TABLOCKX)
order by id
update source_table
set copy_flag = 1
where id in (select top 100 id from source_table order by id)
COMMIT TRANSACTION copyTran
Is there an easier way?
By leveraging OUTPUT clause you can boil it down to a single UPDATE statement
UPDATE source_table
SET copy_flag = 1
OUTPUT inserted.name
INTO destination_table(name)
WHERE id IN
(
SELECT TOP 100 id
FROM source_table
ORDER BY id
)
Note: Now tested. Should work just fine.
The problem with your query is, that you may get different records in your UPDATE if someone inserts some data while you are running your query. It is saver to use the INSERTED keyword.
Declare #temp TABLE (Id integer);
INSERT INTO destination_table (name)
OUTPUT INSERTED.Id into #temp
SELECT TOP 100 name
FROM source_table
ORDER BY id
UPDATE source_table
SET copy_flag = 1
WHERE Id IN (SELECT Id FROM #temp)
I think that you could use a temporary table in which you will store the top 100 ids from your source table, after having ordered them. This way you will avoid executing the select statement in where clause of update for each id.
BEGIN TRANSACTION copyTran
insert into destination_table (name)
select top 100 name
from source_table
order by id
declare #Ids TABLE(id int)
#Ids = (select top 100 id from source_table order by id)
update source_table
set copy_flag = 1
where id in (SELECT * FROM #Ids)
COMMIT TRANSACTION copyTran

Inserting data into a temporary table

After having created a temporary table and declaring the data types like so;
CREATE TABLE #TempTable(
ID int,
Date datetime,
Name char(20))
How do I then insert the relevant data which is already held on a physical table within the database?
INSERT INTO #TempTable (ID, Date, Name)
SELECT id, date, name
FROM physical_table
To insert all data from all columns, just use this:
SELECT * INTO #TempTable
FROM OriginalTable
Don't forget to DROP the temporary table after you have finished with it and before you try creating it again:
DROP TABLE #TempTable
SELECT ID , Date , Name into #temp from [TableName]
My way of Insert in SQL Server. Also I usually check if a temporary table exists.
IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP Table #MyTable
SELECT b.Val as 'bVals'
INTO #MyTable
FROM OtherTable as b
SELECT *
INTO #TempTable
FROM table
I have provided two approaches to solve the same issue,
Solution 1: This approach includes 2 steps, first create a temporary table with
specified data type, next insert the value from the existing data
table.
CREATE TABLE #TempStudent(tempID int, tempName varchar(MAX) )
INSERT INTO #TempStudent(tempID, tempName) SELECT id, studName FROM students where id =1
SELECT * FROM #TempStudent
Solution 2: This approach is simple, where you can directly insert the values to
temporary table, where automatically the system take care of creating
the temp table with the same data type of original table.
SELECT id, studName INTO #TempStudent FROM students where id =1
SELECT * FROM #TempStudent
After you create the temp table you would just do a normal INSERT INTO () SELECT FROM
INSERT INTO #TempTable (id, Date, Name)
SELECT t.id, t.Date, t.Name
FROM yourTable t
The right query:
drop table #tmp_table
select new_acc_no, count(new_acc_no) as count1
into #tmp_table
from table
where unit_id = '0007'
group by unit_id, new_acc_no
having count(new_acc_no) > 1
insert into #temptable (col1, col2, col3)
select col1, col2, col3 from othertable
Note that this is considered poor practice:
insert into #temptable
select col1, col2, col3 from othertable
If the definition of the temp table were to change, the code could fail at runtime.
Basic operation of Temporary table is given below, modify and use as per your requirements,
-- CREATE A TEMP TABLE
CREATE TABLE #MyTempEmployeeTable(tempUserID varchar(MAX), tempUserName varchar(MAX) )
-- INSERT VALUE INTO A TEMP TABLE
INSERT INTO #MyTempEmployeeTable(tempUserID,tempUserName) SELECT userid,username FROM users where userid =21
-- QUERY A TEMP TABLE [This will work only in same session/Instance, not in other user session instance]
SELECT * FROM #MyTempEmployeeTable
-- DELETE VALUE IN TEMP TABLE
DELETE FROM #MyTempEmployeeTable
-- DROP A TEMP TABLE
DROP TABLE #MyTempEmployeeTable
INSERT INTO #TempTable(ID, Date, Name)
SELECT OtherID, OtherDate, OtherName FROM PhysicalTable
insert #temptable
select idfield, datefield, namefield from yourrealtable
All the above mentioned answers will almost fullfill the purpose. However, You need to drop the temp table after all the operation on it. You can follow-
INSERT INTO #TempTable (ID, Date, Name)
SELECT id, date, name
FROM physical_table;
IF OBJECT_ID('tempdb.dbo.#TempTable') IS NOT NULL
DROP TABLE #TempTable;

Delete multiple duplicate rows in table

I have multiple groups of duplicates in one table (3 records for one, 2 for another, etc) - multiple rows where more than 1 exists.
Below is what I came up with to delete them, but I have to run the script for however many duplicates there are:
set rowcount 1
delete from Table
where code in (
select code from Table
group by code
having (count(code) > 1)
)
set rowcount 0
This works well to a degree. I need to run this for every group of duplicates, and then it only deletes 1 (which is all I need right now).
If you have a key column on the table, then you can use this to uniquely identify the "distinct" rows in your table.
Just use a sub query to identify a list of ID's for unique rows and then delete everything outside of this set. Something along the lines of.....
create table #TempTable
(
ID int identity(1,1) not null primary key,
SomeData varchar(100) not null
)
insert into #TempTable(SomeData) values('someData1')
insert into #TempTable(SomeData) values('someData1')
insert into #TempTable(SomeData) values('someData2')
insert into #TempTable(SomeData) values('someData2')
insert into #TempTable(SomeData) values('someData2')
insert into #TempTable(SomeData) values('someData3')
insert into #TempTable(SomeData) values('someData4')
select * from #TempTable
--Records to be deleted
SELECT ID
FROM #TempTable
WHERE ID NOT IN
(
select MAX(ID)
from #TempTable
group by SomeData
)
--Delete them
DELETE
FROM #TempTable
WHERE ID NOT IN
(
select MAX(ID)
from #TempTable
group by SomeData
)
--Final Result Set
select * from #TempTable
drop table #TempTable;
Alternatively you could use a CTE for example:
WITH UniqueRecords AS
(
select MAX(ID) AS ID
from #TempTable
group by SomeData
)
DELETE A
FROM #TempTable A
LEFT outer join UniqueRecords B on
A.ID = B.ID
WHERE B.ID IS NULL
It is frequently more efficient to copy unique rows into temporary table,
drop source table, rename back temporary table.
I reused the definition and data of #TempTable, called here as SrcTable instead, since it is impossible to rename temporary table into a regular one)
create table SrcTable
(
ID int identity(1,1) not null primary key,
SomeData varchar(100) not null
)
insert into SrcTable(SomeData) values('someData1')
insert into SrcTable(SomeData) values('someData1')
insert into SrcTable(SomeData) values('someData2')
insert into SrcTable(SomeData) values('someData2')
insert into SrcTable(SomeData) values('someData2')
insert into SrcTable(SomeData) values('someData3')
insert into SrcTable(SomeData) values('someData4')
by John Sansom in previous answer
-- cloning "unique" part
SELECT * INTO TempTable
FROM SrcTable --original table
WHERE id IN
(SELECT MAX(id) AS ID
FROM SrcTable
GROUP BY SomeData);
GO;
DROP TABLE SrcTable
GO;
sys.sp_rename 'TempTable', 'SrcTable'
You can alternatively use ROW_NUMBER() function to filter out duplicates
;WITH [CTE_DUPLICATES] AS
(
SELECT RN = ROW_NUMBER() OVER (PARTITION BY SomeData ORDER BY SomeData)
FROM #TempTable
)
DELETE FROM [CTE_DUPLICATES] WHERE RN > 1
SET ROWCOUNT 1
DELETE Table
FROM Table a
WHERE (SELECT COUNT(*) FROM Table b WHERE b.Code = a.Code ) > 1
WHILE ##rowcount > 0
DELETE Table
FROM Table a
WHERE (SELECT COUNT(*) FROM Table b WHERE b.Code = a.Code ) > 1
SET ROWCOUNT 0
this will delete all duplicate rows, But you can add attributes if you want to compare according to them .

MySQL: How to copy rows, but change a few fields?

I have a large number of rows that I would like to copy, but I need to change one field.
I can select the rows that I want to copy:
select * from Table where Event_ID = "120"
Now I want to copy all those rows and create new rows while setting the Event_ID to 155. How can I accomplish this?
INSERT INTO Table
( Event_ID
, col2
...
)
SELECT "155"
, col2
...
FROM Table WHERE Event_ID = "120"
Here, the col2, ... represent the remaining columns (the ones other than Event_ID) in your table.
This is a solution where you have many fields in your table and don't want to get a finger cramp from typing all the fields, just type the ones needed :)
How to copy some rows into the same table, with some fields having different values:
Create a temporary table with all the rows you want to copy
Update all the rows in the temporary table with the values you want
If you have an auto increment field, you should set it to NULL in the temporary table
Copy all the rows of the temporary table into your original table
Delete the temporary table
Your code:
CREATE table temporary_table AS SELECT * FROM original_table WHERE Event_ID="155";
UPDATE temporary_table SET Event_ID="120";
UPDATE temporary_table SET ID=NULL;
INSERT INTO original_table SELECT * FROM temporary_table;
DROP TABLE temporary_table;
General scenario code:
CREATE table temporary_table AS SELECT * FROM original_table WHERE <conditions>;
UPDATE temporary_table SET <fieldx>=<valuex>, <fieldy>=<valuey>, ...;
UPDATE temporary_table SET <auto_inc_field>=NULL;
INSERT INTO original_table SELECT * FROM temporary_table;
DROP TABLE temporary_table
Simplified/condensed code:
CREATE TEMPORARY TABLE temporary_table AS SELECT * FROM original_table WHERE <conditions>;
UPDATE temporary_table SET <auto_inc_field>=NULL, <fieldx>=<valuex>, <fieldy>=<valuey>, ...;
INSERT INTO original_table SELECT * FROM temporary_table;
As creation of the temporary table uses the TEMPORARY keyword it will be dropped automatically when the session finishes (as #ar34z suggested).
Let's say your table has two other columns: foo and bar
INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, "155"
FROM Table
WHERE Event_ID = "120"
If you have loads of columns in your table and don't want to type out each one you can do it using a temporary table, like;
SELECT *
INTO #Temp
FROM Table WHERE Event_ID = "120"
GO
UPDATE #TEMP
SET Column = "Changed"
GO
INSERT INTO Table
SELECT *
FROM #Temp
Hey how about to copy all fields, change one of them to the same value + something else.
INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, Event_ID+"155"
FROM Table
WHERE Event_ID = "120"
??????????
As long as Event_ID is Integer, do this:
INSERT INTO Table (foo, bar, Event_ID)
SELECT foo, bar, (Event_ID + 155)
FROM Table
WHERE Event_ID = "120"
Adding to the answer by #DaveTheBFG:
If you have an identity column ("Table_PK" in the below example), the INSERT line would fail, but you can do the following (SQL Server-specific, but the concept may apply to other databases):
SELECT *
INTO #Temp
FROM Table WHERE Event_ID = "120"
UPDATE #TEMP
SET Column = "Changed"
ALTER TABLE #TEMP DROP COLUMN Table_PK
EXEC sp_executesql N'INSERT INTO Table SELECT * FROM #Temp'
If you don't mind doing it in your code, its much easier to do. For example, in php you can do
function copyQuery($table, $row){
$queryColumns = $queryValues = '';
foreach ($row as $key => $value) {
$queryColumns .= $key.', ';
$queryValues .= "'$value', ";
}
$queryColumns = rtrim($queryColumns, ', ');
$queryValues = rtrim($queryValues, ', ');
return "INSERT INTO $table ($queryColumns) VALUES ($queryValues)";
}
$records = mysqli_query($connect, "SELECT * FROM Table WHERE Event_ID = 120");
while ($row = mysqli_fetch_assoc($records)) {
unset($row['id']);
$row['Event_ID'] = 155;
$query = copyQuery('Table', $row);
mysqli_query($connect, $query);
}
Using a function is optional. I made it because I needed to do it a few times. I used this option because now I can forget about it if the database columns change in the future.