How to capture the unique identifier after the insert [duplicate] - sql

This question already has answers here:
How do I return a new IDENTITY column value from an SQLServer SELECT statement?
(7 answers)
Closed 8 years ago.
I have to create new email records in an existing table in the joining table I would like to update a field that would denote that this is a new record.
Example:
INSERT INTO dbo.email.email (dbo.email.eml_address, dbo.email.eml_customer_key)
SELECT new_email, new_customer_key
FROM NEW_TABLE
Update dbo.email_ext
Set dbo.email_ext.new_eml = '1'
Where dbo.email_ext.eml_key_ext = 'Recently create key from insert statement shown above'

You'll want to use the SCOPE_IDENTITY() value, this will contain the ID of the record just created, but only one.
Assuming you're handling ONE record:
DECLARE #ID INT
INSERT INTO dbo.email (eml_address, eml_customer_key)
SELECT new_email, new_customer_key
FROM NEW_TABLE
SET #ID = SCOPE_IDENTITY()
Update dbo.email_ext
Set new_eml = '1'
Where eml_key_ext = #ID
If you're inserting multiples you need to output the list into a table (in this case a table variable) and you can update them all at once.
DECLARE #myIDs TABLE (NEWID INT)
INSERT INTO dbo.email (eml_address, eml_customer_key)
OUTPUT inserted.ID INTO #myIDs
SELECT new_email, new_customer_key
FROM NEW_TABLE
Update t
Set new_eml = '1'
from dbo.email_ext t
join #myIDs m
on t.eml_key_ext = m.ID

Use an OUTPUT clause to capture autogenerated ids/guids/defaults/etc.
CREATE TABLE #test (
id int identity(1,1) primary key,
uid uniqueidentifier DEFAULT NEWID(),
value varchar(max)
)
INSERT #test (value)
OUTPUT inserted.*
SELECT 'test'
id guid value
----------- ------------------------------------ ---------
1 72B70577-2679-4C2A-A575-62D30807B9D2 test
(1 row(s) affected)

Related

SQL Server trigger if update() with condition

I have a table in SQL Server that has 3 columns: ID, NAME, VALUE.
This table has 2 rows with ID=1 and ID=2.
(The value of ID doesn't change).
Every moment of time the value of column VALUE changes. Every time the column VALUE changes, I want to insert this updated value into a table (Device1 for ID=1, Device1 for ID=2).
I created a trigger for updating as if update(VALUE) begin...but it doesn't do the work.
Is there a way to add a condition in if update(VALUE) to work in each row
I used this query
Create Trigger insertIntoDevices
On ITEMS
For Update
As
If Update(VALUE)
Begin
Insert Into table device1
Where ID = 1
Insert Into table device2
Where ID = 2
End
With this query each update in column VALUE inserts VALUE into device1 and device1 and that duplicates values in my tables device1 and device2.
Table creation on the below ;
CREATE TABLE TestTable(
ID INT IDENTITY(1,1),
Name VARCHAR(5),
VALUE NVARCHAR(50)
)
GO
CREATE TABLE device1(
VALUE NVARCHAR(50)
)
GO
CREATE TABLE device2(
VALUE NVARCHAR(50)
)
GO
Insertion for ID=1 and ID=2
GO
INSERT INTO TestTable(Name,Value)
VALUES('Test1','test1'),('TEST2','test2')
Firstly,To find new values for each row you can use 'inserted' but it can be include non-changed data. For example: ID =1,Name='test1' and VALUE='test1' and updation of name column will be also included in inserted.
Secondly,To find old values for each row you can use 'deleted'.
After that we find the values that only includes updation for VALUE.
To Sump Up,
Finding Inserted rows and deleted rows will give us the result of each rows new and old values. We used intersection (INNER JOIN ) to find only changed values.
CREATE TRIGGER [dbo].[insertIntoDevices]
ON [dbo].[TestTable]
AFTER UPDATE
AS
BEGIN
DECLARE #InsertedTable table (
InsertedID INT,
InsertedName VARCHAR(5),
InsertedVALUE NVARCHAR(50)
)
DECLARE #DeletedTable table (
DeletedID INT,
DeletedName VARCHAR(5),
DeletedVALUE NVARCHAR(50)
)
INSERT INTO #InsertedTable(InsertedID,InsertedName,InsertedVALUE)
SELECT ID,[Name],[Value] FROM inserted;
INSERT INTO #DeletedTable(DeletedID,DeletedName,DeletedVALUE)
SELECT ID,Name,Value FROM deleted;
INSERT INTO device1(VALUE)
SELECT UpdatedValue = it.InsertedVALUE
FROM #InsertedTable as it
INNER JOIN #DeletedTable as dt ON it.InsertedID = dt.DeletedID AND ISNULL(dt.DeletedVALUE,'') <> ISNULL(it.InsertedVALUE,'')
WHERE it.InsertedID = 1
INSERT INTO device2(VALUE)
SELECT UpdatedValue = it.InsertedVALUE
FROM #InsertedTable as it
INNER JOIN #DeletedTable as dt ON it.InsertedID = dt.DeletedID AND ISNULL(dt.DeletedVALUE,'') <> ISNULL(it.InsertedVALUE,'')
WHERE it.InsertedID = 2
END
To test I used the updation queries on the below;
--Example 1
UPDATE TestTable
SET Value='selam'
WHERE ID = 1
--Example 2
UPDATE TestTable
SET Value='hi'
WHERE ID = 2

Generate ID for duplicate values in sql server

I found following link to assign identical ID to duplicates in SQL server,
my understanding there is no sql server function to automatically generate it rather than using insert and update queries in link attached, is that statement True, if yes, then what would be the trigger if for example someone insert data to MyTable then run insert and update query from link:
Assign identical ID to duplicates in SQL server
INSERT INTO secondTable (word) SELECT distinct word FROM MyTable;
UPDATE MyTable SET ID = (SELECT id from secondTable where MyTable.word = secondTable.word)
thanks,
S
Is this what you want? I can't think of an "automatic" solution that would just increase the Id for new words.
CREATE TABLE MyTable (
Id INT NOT NULL,
Word NVARCHAR(255) NOT NULL
PRIMARY KEY (Id, Word)); -- primary key will make it impossible to have more than one combination of word and id
DECLARE #word NVARCHAR(255) = 'Hello!';
-- Get existing id or calculate a new id
DECLARE #Id INT = (SELECT Id FROM MyTable WHERE Word = #word);
IF(#id IS NULL) SET #Id = (SELECT MAX(Id) + 1 FROM MyTable);
INSERT INTO MyTable (Id, Word)
VALUES (#id, #word)
SELECT * FROM MyTable
If you can't for some reason have id and word as a combined primary key, you may use an unique index to make sure that there is only one combination

How to return NULL for Identity when no INSERT is performed

I have two tables
CREATE TABLE Temp_1
(
ID Int IDENTITY(1,1),
Name Varchar(500)
)
CREATE TABLE Temp_2
(
ID Int IDENTITY(1,1),
Name Varchar(500)
)
INSERT INTO Temp_1
SELECT 'CC'
INSERT INTO Temp_2
SELECT Name
FROM Temp_1
WHERE 2 = 1
There is no insertion into the table Temp_2.So my expected output for the SCOPE_IDENTITY () for the table Temp_2 is NULL.
How can i get the Identity Value of the Temp_2 as null?
If we use the SCOPE_IDENTITY() OR ##IDENTITY, the identity value we are getting is only of the table Temp_1. We need to get the identity value of table Temp_2 which is "null" as there is no insertion in the table Temp_2 .
Neither. You want to use the output clause:
DECLARE #ids TABLE (id INT);
INSERT INTO Temp_1
OUTPUT inserted.id INTO #ids
SELECT 'CC' ;
This is session-safe, statement-safe, multi-threaded safe. And it allows you to handle multiple row inserts. And it allows you to return additional columns.
There is no reason to use any other method.

How can I use SQL MERGE to insert if not exists, and SET a variable to the Id?

I have an Id column set by SEQUENCE
Given a varchar I need to INSERT if there is not match, and return an Id.
The Id will be either:
The existing Id of the row with the matchine ItemName
The new Id generated by the sequence because a row was inserted
NULL because the string was passed as NULL
I'm trying to MERGE into the table to insert if not exists, otherwise get the Id. I need it to be threadsafe.
Here is what I have so far but I'm thinking there is a better way:
DECLARE #vValueId INT NULL
DECLARE #inserted AS TABLE (Id INT NOT NULL)
MERGE
dbo.foo WITH (HOLDLOCK) AS f
USING
(SELECT #vName AS val WHERE #vName IS NOT NULL) AS new_item
ON f.ItemName = new_item.val
WHEN MATCHED THEN
UPDATE SET #vValueId = f.Id
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ItemName)
VALUES
(#vName)
OUTPUT inserted.Id AS Id INTO #inserted;
SELECT #vValueId = ISNULL(s.Id, #vValueId) FROM #inserted AS s

SQL Server 2008: Sql Insert/Update into another table using insertion IDs output from another table

I have a procedure for insert in multiple dependent tables (update in case record exist). I have input parameters as comma separated string which I am reading in table.
After 1st insertion I am getting InsertedIds in another table variable.
I am struggling over how to do insert in 2nd table. I have following input parameters for 2nd table:
Declare #IdsToBeUpdated table (primary key identity pkey, id int) -- values are 1,-1,3,-1
Declare #CommentsTobeInserted table( primary key identity pkey, comment varchar (max)) -- values are 'com1', 'com2', 'com3'
-1 input in table #IdsToBeUpdated depicts insertion for the corresponding rows in all input tables and value other than -1 depicts that records at that pkey value in all other tables (#CommentsTobeInserted table as in example) have to be updated.
So after first insertion I am getting the inserted ids for rows with -1 value. #InsertedIds = 4,5
So my Ids list logically would become.. 1,4,3,5.
But I am stuck now how to insert/update records in second table respectively.
2nd table would be like follows:
Pkey Primary key identity, commentIds(coming from inserted ids and #IdsToBeUpdated), comments.
I have added one more InsertedIds column in #CommentsTobeInserted. If I could fill it with right InsertedId against correct row, I guess I would be able to do insert/update in 2nd table. And where the value is Id in new column I would do insert, where it's null, I would perform update using #IdsToBeUpdated table.
But currently none of my approach is working. I am new to SQL. Any help would be highly appreciated.
Following is some portion of script for better understanding. I have added first insertion script as well.
USE [Demo]
GO
/****** Object: StoredProcedure [dbo].[USP_NewRequest_Insert] Script Date: 2/11/2016 2:50:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_NewRequest_Insert]
-----------------------------------
--------- SomeInput parameters
---------for first insertion omitted
--------------------------------
#IdsToBeUpdated varchar(MAX), --Values are 23|-1|32|-1|-1
#CommentList AS VARCHAR(MAX), --Values 'C2'|'C4'|'C5'|'C6'|'C7'
#MCodeList VARCHAR(MAX), --Values 'M2'|'M4'|'M5'|'M6'|'M7'
#CustomerIdsList VARCHAR(MAX), ----Values 'Cust2'|'Cust4'|'Cust5'|'Cust6'|'Cust7'
#ReturnValue AS INT OUTPUT,
------------------Data is in the order it has to be inserted.. where IDs exist in #IdsToBeUpdated, updation would be done. For -1 values, insertion.
AS
BEGIN
BEGIN TRANSACTION
--------------------------Split input strings aand insert in Table variable----------------------------
declare #MCodes Table (pkey int primary key identity, MCode varchar(20))
insert into #MCodes select s.Item from [dbo].UDF_SplitString(#MCodeList, '|') s
declare #CusCodes Table (pkey int primary key identity, CusCode varchar(200))
insert into #CusCodes select s.Item from [dbo].UDF_SplitString(#CustomerIdsList, '|') s
declare #ReqDetailsIds Table (pkey int primary key identity, Id Int)
insert into #ReqDetailsIds select Convert(INT,RTRIM(LTRIM(s.Item))) from [dbo].UDF_SplitString(#IdsToBeUpdated, '|') s
where s.Item is not null and RTRIM(LTRIM(s.Item)) <>''
declare #ProductComments Table (pkey int primary key identity, Comment Varchar(max), insertedId int null)
insert into #ProductComments(Comment) select s.Item from [dbo].UDF_SplitString(#CommentList, '|') s
DECLARE #intErrorCode int;
------------------------------------------------------------------------------------------------------------
-----------------First Insertion which returns inserted IDs for 2nd insertion
------------------------------------------------------------------------------------------------------------------
---Insert/Update product details in [RequestDetails]
Declare #InsertedIDList Table (pkey int primary key identity, ID int); --------Table to read inserted Ids. Used in query below
-----------------------Insert query in case Detail id = -1
INSERT INTO [dbo].[RequestDetails]
[MCode]
,[CustomerIds]
,[ExpectedVolume]------Some parameters coming for first insertion in input
,[StatusCode])
Output INSERTED.ReqDetailId Into #InsertedIDList(ID)
SELECT A.MCode, B.CusCode, E.Vol,1
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id = -1 --If id = -1, insert
---------------------------Update Query for rest records
UPDATE [dbo].[RequestDetails]
SET [MCode] = upd.MCode
,[CustomerIds] = upd.CusCode
,[ExpectedVolume] = upd.ExVol
,[StatusCode] = 1
FROM(
SELECT A.MCode, B.CusCode, E.ExVol, G.Id
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id <> -1
) upd
WHERE upd.Id = dbo.RequestDetails.ReqDetailId
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
---------------------------------------------------------------------------
----------------------------Now similarly I have to do insert/update in Comments Table. But
----------------------------Comments table has RequestDetails Id column as foreign key. So
----------------------------now the challange is to add the rows with Inserted ID where value was = -1
----------------------------in input. We have got the IDs corresponding to -1 values from above insertion
----------------------------in the #InsertedIDList Table variable
-----------------------------------------------------------------------------------------
----------------------------Following is what I have tried so far. But I am not able to insert
----------------------------correct InsertedId against correct record.
----------------------------------------------------------------------------------------
-----------------------Here I tried to insert the new generated ids against corresponding comments in table variable.
-----------------------So that I can perform insert where value is not null. As NULL would be inserted where new ID has not been created
-----------------------and corresponding updated ID exists in input (Values not equal to -1)
-------------------------------------------------------------------------------------------------
Update #ProductComments set insertedId = i.ID from ---------This query is not working
(select A.pkey, B.id as detailId, row_number() over (order by (select 0)) as row_num from
#ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey) as mappedNewIds right join
#InsertedIDList i on i.pkey = mappedNewIds.row_num
where mappedNewIds.pkey = [#ProductComments].pkey
----Insert in CommentsTable for New Comments against request
---------------------------------
INSERT INTO [dbo].CommentsTable
( ReqDetailId, Comments, CreatedOn )
SELECT A.insertedId, A.Comment, GETDATE()
FROM #ProductComments A
where A.insertedId is not null
-----Update Query
------------------------------------------------------------------------------------------
UPDATE [dbo].[CommentsTable]
SET [ReqDetailId] = upd.Id
,[Comments] = upd.Comment
,[CreatedOn] = GetDate()
FROM(
SELECT A.Comment, B.Id
FROM #ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey
WHERE A.insertedId is not null
) upd
WHERE upd.Id = dbo.CommentsTable.ReqDetailId
END
select * from CommentsTable;
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
COMMIT TRANSACTION
ERROR:
IF (#intErrorCode <> 0) BEGIN
SET #ReturnValue = 0;
ROLLBACK TRANSACTION
END
END