Reputation: 687
I have a table Items which should have a corresponding record in the table LanguageText. The ID (Identity) of LanguageText is registered in the Items.LanguageTextId field in my Items table.
What I want to accomplish is a merge between LanguageText and Items for all records with null in Items.LanguageTextId and insert the itemname / text of these Item records in LanguageText plus update the LanguageTextId with the ID value from the newly inserted LanguageText record (SCOPE_IDENTITY()?)
The insert works fine:
MERGE [dbo].[LanguageText] AS target
USING (SELECT [Items].* from [dbo].Items ) AS source
ON (TARGET.Id = SOURCE.LanguageTextId)
WHEN NOT MATCHED By Target THEN
INSERT
([Text])
VALUES
(source.[ItemName]);
end
But I don't know how to update my items.Languagetextid, can I do something with: OUTPUT $action, INSERTED.ID ? Or is there a better way to have this done??
Thanks in advance,
Mike
Upvotes: 1
Views: 3672
Reputation: 138990
You can do this with a merge..output to a table variable followed by an update.
MS SQL Server 2008 Schema Setup:
create table Items
(
ItemsId int identity primary key,
ItemName nvarchar(50) not null,
ItemsLanguageTextId int null
);
create table ItemsLanguageText
(
ItemsLanguageTextId int identity primary key,
Text nvarchar(50) not null
);
insert into Items values('Name 1', null);
insert into Items values('Name 2', null);
insert into Items values('Name 3', null);
Query 1:
declare @T table
(
ItemsId int,
ItemsLanguageTextId int
);
merge ItemsLanguageText as T
using (
select ItemsId, ItemName
from Items
where ItemsLanguageTextId is null
) as S
on 0 = 1
when not matched then
insert (Text) values (S.ItemName)
output S.ItemsId, inserted.ItemsLanguageTextId
into @T;
update Items
set ItemsLanguageTextId = T.ItemsLanguageTextId
from @T as T
where T.ItemsId = Items.ItemsId;
Query 2:
select * from Items;
| ITEMSID | ITEMNAME | ITEMSLANGUAGETEXTID |
--------------------------------------------
| 1 | Name 1 | 13 |
| 2 | Name 2 | 14 |
| 3 | Name 3 | 15 |
Query 3:
select * from ItemsLanguageText;
| ITEMSLANGUAGETEXTID | TEXT |
--------------------------------
| 13 | Name 1 |
| 14 | Name 2 |
| 15 | Name 3 |
Upvotes: 9
Reputation: 687
I'm still a noob when it comes to SQL... I guess it can't be done with merge so I've tried it with a stored procedure with a cursor which loops through the records and does what I want it to do:
CREATE PROCEDURE [dbo].[PM_CreateItemsLanguageTexts]
AS
DECLARE @ITEMNAME NVARCHAR(50);
DECLARE @ITEMID BIGINT;
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--Declare Cursor so we can iterate each record
Declare c Cursor For Select Id, ItemName From dbo.Items WHERE NameId is null
Open c
--Fetch First
Fetch next From c into @ITEMID, @ITEMNAME
--As long as we are 'on a roll' go with the flow..
While @@Fetch_Status=0
Begin
PRINT @ITEMNAME;
PRINT @ITEMID;
--FIRST INSERT A NEW TEXT RECORD IN ItemsLauguageText
INSERT dbo.ItemsLauguageText(Text) VALUES (@ITEMNAME);
--UPDATE THE ITEMS RECORD NAMEID FIELD WITH THE LATEST IDENTITY / ID VALUE
UPDATE dbo.Items SET NameID = CAST(SCOPE_IDENTITY() AS bigint) WHERE dbo.Items.Id = @ITEMID;
Fetch next From c into @ITEMID,@ITEMNAME
End
End
CLOSE C;
DEALLOCATE C;
Upvotes: 0
Reputation: 1168
I think what you're looking for is the addition of WHEN MATCHED.
For example
WHEN MATCHED THEN UPDATE SET.... etc etc
WHEN NOT MATCHED THEN INSERT ... etc etc
You can check this MERGE Transaction Documentation for details on how to properly use MERGE. http://technet.microsoft.com/en-us/library/bb510625.aspx
Upvotes: 2