I am looking for the correct syntax and way to do the following directly from SQL: insert or update (if data already exists inside) TableMain
from data contained in TableA
with both having same composite primary key.
Both tables are defined as :
CREATE TABLE TableA (
[TID0] [int] NOT NULL,
[TID1] [int] NOT NULL,
[language] [nvarchar](2) NOT NULL,
[TID2] [nvarchar](200) NOT NULL,
[text] [nvarchar](max) NULL,
[updatedOn] [datetime] NOT NULL DEFAULT (getdate())
PRIMARY KEY (
[TID0],
[TID1],
[language],
[TID2],
)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
TableA
will be periodically deleted and filled.
TableMain
as the same definition but will contain many more rows of data and what I need is to insert never seen values from TableA
into TableMain
, and update already existing rows.
I used to do this kind of insert but I do not know how to handle update and composite primary keys :
INSERT INTO TableMain
SELECT * FROM TableA
EDIT : i am using SQL Server 9.00.5000
EDIT : another way inspired by MERGE and mimick it
DECLARE @updatedIDs TABLE(
[TID0] [int],
[TID1] [int],
[language] [nvarchar](2),
[TID2] [nvarchar](200),
PRIMARY KEY ([TID0], [TID1], [language], [TID2]) -- as stated by Nikola Markovinović above, thanks
);
-- First update records
update TableMain
set [text] = source.[text],
[updatedOn] = source.[updatedOn]
OUTPUT
inserted.[TID0]
inserted.[TID1]
inserted.[language]
inserted.[TID2]
INTO @updatedIDs
from
TableMain AS main
, TableA AS source
WHERE
TableMain.[TID0] = source.[TID0]
and TableMain.[TID1] = source.[TID1]
and TableMain.[language] = source.[language]
and TableMain.[TID2] = source.[TID2]
-- And then insert
insert into TableMain
select *
from TableA AS source
where not exists
(
select 1
from @updatedIDs AS i
where i.[TID0] = source.[TID0]
and i.[TID1] = source.[TID1]
and i.[language] = source.[language]
and i.[TID2] = source.[TID2]
)
you should use a merge statment
something like this:
merge TableMain AS target
using TableA as source
ON <join tables here>
WHEN MATCHED THEN <update>
WHEN NOT MATCHED BY TARGET <Insert>
WHEN NOT MATCHED BY SOURCE <delete>
Here is a script you might use to upsert your data:
-- On error transaction is automatically rolled back
set xact_abort on
begin transaction
-- First update records
update TableMain
set [text] = source.[text],
[updatedOn] = source.[updatedOn]
from TableMain
inner join TableA source
on TableMain.[TID0] = source.[TID0]
and TableMain.[TID1] = source.[TID1]
and TableMain.[language] = source.[language]
and TableMain.[TID2] = source.[TID2]
-- And then insert
insert into TableMain ([TID0], [TID1], [language], [TID2], [text], [updatedOn])
select [TID0], [TID1], [language], [TID2], [text], [updatedOn]
from TableA source
where not exists
(
select *
from TableMain
where TableMain.[TID0] = source.[TID0]
and TableMain.[TID1] = source.[TID1]
and TableMain.[language] = source.[language]
and TableMain.[TID2] = source.[TID2]
)
commit transaction
You might rewrite not exists() as left join ... where TableMain.TID0 is null
if performance is not satisfactory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With