I am using the MERGE INTO statement to work with some tables, and I've a simple question. How can I make a Matched/Not Matched Statement do 2 things? For example, I have this and it works:
MERGE INTO VMFG.dbo._AR_Mill1ActiveSchedule t --target
USING #temp --source
On t.Base_ID = #temp.WORKORDER_BASE_ID AND t.Lot_ID = #temp.WORKORDER_Lot_ID
WHEN MATCHED AND #temp.rollstatus = 'R' THEN
UPDATE
SET t.sawStatus = #temp.sawstatus, t.rollStatus = #temp.rollstatus
WHEN NOT MATCHED BY TARGET THEN
INSERT (BASE_ID, LOT_ID, sawStatus, rollstatus, preheatcheck) VALUES (#temp.WorkOrder_Base_ID, #temp.WorkOrder_Lot_ID, #temp.sawStatus, #temp.rollStatus, 'False')
WHEN NOT MATCHED BY SOURCE AND t.SawStatus = 'C' THEN
Delete ;
Drop Table #temp
Now, I want to accomplish something like this:
MERGE INTO VMFG.dbo._AR_Mill1ActiveSchedule t --target
USING #temp --source
On t.Base_ID = #temp.WORKORDER_BASE_ID AND t.Lot_ID = #temp.WORKORDER_Lot_ID
WHEN MATCHED AND #temp.rollstatus = 'R' THEN
UPDATE
SET t.sawStatus = #temp.sawstatus, t.rollStatus = #temp.rollstatus
WHEN NOT MATCHED BY TARGET THEN
INSERT (BASE_ID, LOT_ID, sawStatus, rollstatus, preheatcheck) VALUES (#temp.WorkOrder_Base_ID, #temp.WorkOrder_Lot_ID, #temp.sawStatus, #temp.rollStatus, 'False')
WHEN NOT MATCHED BY SOURCE AND t.SawStatus = 'C' THEN
INSERT INTO _AR_Mill1RemovedWO (BASE_ID, LOT_ID) VALUES (#temp.WorkOrder_Base_ID, #temp.WorkOrder_Lot_ID)
Delete ;
Drop Table #temp
However, when I run this I get the error "Incorrect syntax near the keyword 'INTO'".
I've tried using the OUTPUT clause but I couldn't get it to work correctly, and would rather use an insert statement anyways if possible.
Thank you :)
EDIT:
The Output clause would be awesome to use, but I'll explain why it hasn't worked. When I used it, i.e.:
....
WHEN NOT MATCHED BY SOURCE AND t.SawStatus = 'C' THEN
--INSERT INTO _AR_Mill1RemovedWO (BASE_ID, LOT_ID) VALUES (#temp.WorkOrder_Base_ID, #temp.WorkOrder_Lot_ID)
Delete
OUTPUT deleted.Base_ID, deleted.Lot_ID INTO VMFG.dbo._AR_Mill1RemovedWO
;
Drop Table #temp
I run in to a problem. It adds rows to my table that weren't actually deleted. It's like it's just adding everything, regardless of being deleted. Is there a reason for this?
This is impossible to do with a single MERGE statement. Use the OUTPUT clause to direct information about the writes executed into a table variable. Execute a second statement such as INSERT to write to the second table.
Related
I have this store procedure
CREATE PROCEDURE [dbo].[upsertGrps] #Groups GrpType READONLY AS
BEGIN
MERGE ExpandedGroupInformation AS Target
USING #Groups AS Source
ON (Source.ObjectGuid = Target.ObjectGuid or Source.Name = Target.Name)
WHEN MATCHED THEN
UPDATE SET Target.Description = Source.Description,
-- update data
WHEN NOT MATCHED BY TARGET
THEN INSERT
GO
This is used to update or insert data using the merge technique.
ObjectGuid in both Target and Source is uniqueidentifier.
I have noticed that it fails on matching them. Is it case sensitive? Do I have to apply some sort of collation on this?
I can do ToLower on both but I have data around 100,000 and then the query gets very slow.
Any suggestions on what I might be missing here?
I have a table in DB where some records exist.
When I add a new record I need to check by column "Name" if the record exists in DB. If such a record does not exist - then add it, if exists - then update. I'm trying like this:
USE [TestDB]
GO
DECLARE #daily nvarchar = 'DailySummaryEmailProcessor'
IF NOT EXISTS ( SELECT *
FROM [dbo].Crons
WHERE name = #daily)
BEGIN
INSERT INTO [dbo].Crons (CronJobID, Name, Description)
VALUES()
END
ELSE
BEGIN
UPDATE [dbo].Crons
SET
WHERE
END
MERGE should fit your requirements MERGE (Transact-SQL):
MERGE Crons AS target
USING (SELECT #Name) AS source (Name)
ON (target.Name = source.Name)
WHEN MATCHED THEN
UPDATE SET target.Name = source.Name
WHEN NOT MATCHED
INSERT INTO Crons (Name) VALUES (source.Name)
OUTPUT $action, deleted.Name, inserted.Name
the issue is you never declare the size of the variable #dialy
try this and see what do you get
DECLARE #daily nvarchar = 'DailySummaryEmailProcessor'
SELECT #daily
Looks like you need to do INSERT .. UPDATE.. check out MERGE statement
https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-2017
EDIT:
Oh.. you have MySQL there in the tag. My answer is specifically on SQL Server.
I am trying to write a MERGE statement. If the record exists, update it. If it doesn't exist, insert it.
This query runs, but is says '0 rows affected'. I know that an add_id of '3' does not exist, so I would expect it to insert a row. What am I doing wrong? Sorry, I've never written a merge query before.
MERGE INTO dbo.delay AS TARGET
USING (SELECT * FROM dbo.delay WHERE add_id = 3) AS SOURCE ON (Source.add_id = Target.add_id)
WHEN MATCHED
THEN UPDATE SET my_value = 22
WHEN NOT MATCHED BY TARGET
THEN INSERT (add_id, my_value) VALUES (1, 22);
I have a Query using T-SQL MERGE Statement. Due to performance issues I am re writing the Query using IF Exists Update and If Not Exists Insert. I am able to write Insert/Update without any issue. But I am unable to handle the DELETE. Can some one please help me on this?
Here is the sample
---SAMPLE MERGE STATEMENT
MERGE
member_topic AS target
USING
someOtherTable AS source
ON
target.mt_member = source.mt_member
WHEN MATCHED THEN
UPDATE SET target.mt_notes = source.mt_notes
WHEN NOT MATCHED THEN
INSERT (mt_member, mt_topic, mt_notes) VALUES (source.mt_member, source.mt_notes)
WHEN NOT MATCHED BY SOURCE THEN
DELETE member_topic;
--UPDATE
UPDATE T SET T.mt_notes = S.mt_notes
FROM member_topic T
JOIN someOtherTable S ON T.mt_member=S.mt_member
--INSERT
INSERT INTO member_topic(mt_member, mt_topic, mt_notes)
SELECT mt_member, mt_topic, mt_notes
FROM someOtherTable S
WHERE NOT EXISTS(SELECT 1
FROM member_topic T
WHERE T.mt_member=S.mt_member)
How to handle
WHEN NOT MATCHED BY SOURCE THEN
DELETE member_topic;
in single DELETE Statement.
a sample script to be embedded between begin and end in proc
MERGE dbo.Tablet AS TARGET
USING dbo.QueryView AS SOURCE
ON (
TARGET.[ID] = SOURCE.[ID]
)
WHEN MATCHED
THEN
UPDATE SET
TARGET.[ID] = SOURCE.[ID]
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID, [Name] )
VALUES (SOURCE.[ID], SOURCE.[Name] )
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
Try
DELETE T
FROM member_topic T
WHERE NOT EXISTS(SELECT 1
FROM someOtherTable S
WHERE T.mt_member=S.mt_member)
DELETE t
FROM member_topic t
LEFT JOIN someOtherTable s ON t.mt_member = s.mt_member
WHERE s.mt_member IS NULL
I have a table, tblstars_new, which is updated weekly from the client. I have another table, tblstars, which needs to import new and updated data from tblstars_new.
Finding rows in tblstars_new that do not exist in tblstars, and then adding then to tblstars is simple.
But, I also need to find rows in tblstars_new in which the column PandA_Code has changed, and then update the identical row in tblstars.
This query tells me which rows from tblstars_new have PandA_Code's that have changed and need to be updated in tblstars.
SELECT
sn.*
FROM
tblstars_new sn
JOIN tblstars s ON sn.Student_ID_Number = s.Student_ID_Number AND sn.PandA_Code != s.PandA_Code
I'm trying to figure out a MERGE statement that will make the changes. As I'm doing in Prod, I can't really play around. Two questions:
1) Is it possible to see the changes without actually doing them?
2) Is the MERGE statement below correct?
BEGIN TRAN;
MERGE tblstars AS T -- Target
USING tblstars_new AS S -- Source
ON
(T.Student_ID_Number = S.Student_ID_Number AND T.PandA_Code != S.PandA_Code)
WHEN NOT MATCHED BY TARGET
THEN
UPDATE SET T.PandA_Code = S.PandA_Code
OUTPUT $action;
ROLLBACK TRAN;
GO
Here is the MERGE query that satisfy your requests.
BEGIN TRAN;
MERGE tblstars AS T -- Target
USING tblstars_new AS S -- Source
ON T.Student_ID_Number = S.Student_ID_Number -- They shoudl match by PK
WHEN MATCHED AND AND T.PandA_Code != S.PandA_Code
THEN -- when matched and PandA_Code different update them
UPDATE SET T.PandA_Code = S.PandA_Code
WHEN NOT MATCHED BY TARGET -- When not matched by TARGET (there is in source but not in target)
THEN INSERT (<field1, field2, ...>)
VALUES (<S.field1, S.filed2, ...>) -- then insert them
OUTPUT deleted.*, $action, inserted.* INTO #TheTempTable;
SELECT * FROM #TheTempTable; -- here you can see the cnages and rollback if something is wrong
ROLLBACK TRAN;
GO
This is simply done by using join instead of merge statement:
UPDATE T SET T.PandA_Code = S.PandA_Code FROM tblstart T
INNER JOIN tblstars_new P ON P.Student_ID_Number = T.Student_ID_Number
WHERE T.PandA_Code <> S.PandA_Code