Help with T-SQL script: Insert record, then use identity of that insert on another statement? - sql

Just as a preface, I'm not very knowledgeable on T-SQL syntax.
I'd like to create a simple SQL script that will make 3 insert statements.
Insert A
Insert B
Insert C
Insert A statement's identity or "ID" would be needed in insert B statement.
And both the identities Inserts A & B would be needed in Insert C statement.
Pseudo code would look something like:
INSERT INTO tableA
VALUES ('blah', 'blah')
INSERT INTO tableB
VALUES (IDENTITY_FROM_A_INSERT, 'foo')
INSERT INTO tableC
VALUES (IDENTITY_FROM_A_INSERT, IDENTITY_FROM_B_INSERT)
How would I go about writing this script?

Use SCOPE_IDENTITY() after each insert in order to get the identity of the inserted row (in the current session).
I have used two variables to capture the two identities and then insert them into the third table:
DECLARE #Id1 INT
DECLARE #Id2 INT
INSERT INTO tableA VALUES ('blah', 'blah')
SET #Id1 = SELECT SCOPE_IDENTITY()
INSERT INTO tableB VALUES (IDENTITY_FROM_A_INSERT, 'foo')
SET #Id2 = SELECT SCOPE_IDENTITY()
INSERT INTO tableC VALUES (#Id1, #Id2)

scope_identity() is perfect for integer identifiers on single-record insertions (+1 to the other answer btw). However, if you find yourself using a guid/uniqueidentifier (newsequentialid(), newid(), etc) or inserting multiple records at once, you'll need something a little different:
declare #id uniqueidentifier;
-- Table variable for storing your newly inserted identifiers:
declare #NewlyInsertedIds table
(
[Id] uniqueidentifier
);
insert [MyTable]
(
[Blah1]
,[Blah2]
)
-- in the output clause you can access the inserted/deleted pseudo tables:
ouptut inserted.[Id]
into #NewlyInsertedIDs
(
[Id]
)
values
(
'Blah'
,'Blah'
);
select
#id = [Id]
from #NewlyInsertedIds;
Check out the OUTPUT Clause for more information.

Related

Insert multiple rows using triggers using three tables

ALTER TRIGGER tr_ItemAccessInsert
ON [dbo].[tbl_InventoryGroup]
AFTER INSERT
AS
BEGIN
DECLARE #ID decimal(18,3), #InventoryID decimal(18,3)
SELECT #ID = [ItemID] FROM [dbo].[tbl_ItemMain]
SELECT #InventoryID = [GroupID] FROM inserted
INSERT INTO tbl_ItemInventoryAccess ([ItemID], [InventoryID], [Value])
VALUES (#ID, #InventoryID, '0.11')
END
this is my query for trigger
i have 10 item in tbl_itemmain so i want to insert all the 10 itemsid in the tbl_inventoryacess please help me with that
You would just use insert . . . select:
insert into tbl_ItemInventoryAccess ([ItemID], [InventoryID], [Value])
select i.??, i.GroupID, '0.11'
from inserted i;
It is unclear how ItemId is determined. I imagine that a table called tbl_ItemMain has more than one row. Perhaps you can just use i.ItemId.
if i am using like
Alter trigger tr_ItemAccessInsert
on [dbo].[tbl_InventoryGroup]
After insert
as begin
Declare #ID decimal(18,3),#InventoryID decimal(18,3)
select #InventoryID=[GroupID] from inserted
insert into tbl_ItemInventoryAccess([ItemID],[InventoryID],[Value]) values((select itemid from tbl_ItemMain) ,#inventoryid,'0')
end
getting an error subquery returned more than one value

Merge not working for insert a record when it's doesn't exist

Can I use Merge to insert a record when it's doesn't exist like below,
MERGE INTO [dbo].[Test] AS [Target]
USING (SELECT DISTINCT [Name] FROM [dbo].[Test]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), 'Hello');
If the record with value Hello does not exists in table Test, insert it otherwise don't do anything. With above code record is not inserted even I don't have this record in table. And there are no errors.
I know how to accomplish this using insert ... where not exists (...) but am specifically wanting to know how to do it using a merge statement.
The reason your merge statement wasn't working is that you were merging the same table, dbo.Test, back onto itself, so of course there is no missing record.
You can insert a single missing record as follows, where you create a source query to contain the record(s) you wish to insert:
declare #Test table (id uniqueidentifier, [Name] nvarchar(64))
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
MERGE INTO #Test AS [Target]
USING (select 'Hello' [Name]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), [Name]);
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
-- C1C87CD5-F745-436D-BD8D-55B2AF431BED | Hello
I agree with the answer from Dale K. Its correct.
If I suppose you might have a source_table from where the data needs to get inserted and not to get inserted if the record already exists then you can do the following.
Instead of the MERGE you can
insert
into dbo.Test
(id
,name
)
select top 1
newID()
,'Hello'
from dbo.Test a
where not exists(select 1
from dbo.Test b
where b.name='Hello')

Inserting into a Table the result between a variable and a table parameter

Having the following procedure:
CREATE PROCEDURE [dbo].[Gest_Doc_SampleProc]
#Nome nvarchar(255),
#Descritivo nvarchar(255),
#SampleTable AS dbo.IDList READONLY
AS
DECLARE #foo int;
SELECT #foo=a.bar FROM TableA a WHERE a.Nome=#Nome
IF NOT EXISTS (SELECT a.bar FROM TableA a WHERE a.Nome=#Nome)
BEGIN
INSERT INTO TableA VALUES (#Nome,#Descritivo)
INSERT INTO TableB VALUES (scope_identity(),#SampleTable)
END
I am trying, as shown, inserting into TableB all the values of SampleTable, together with the scope_identity.
SampleTable is as:
CREATE TYPE dbo.SampleTable
AS TABLE
(
ID INT
);
GO
How can I correctly achieve this?
The right way to do this type of work is the OUTPUT clause. Although technically not needed for a single row insert, you might as well learn how to do it correctly. And even what looks like a single row insert can have an insert trigger that does unexpected things.
PROCEDURE [dbo].[Gest_Doc_SampleProc] (
#Nome nvarchar(255),
#Descritivo nvarchar(255),
#SampleTable AS dbo.IDList
) READONLY AS
BEGIN
DECLARE #ids TABLE (id int);
DECLARE #foo int;
SELECT #foo = a.bar
FROM TableA a
WHERE a.Nome = #Nome;
IF NOT EXISTS (SELECT 1 FROM TableA a WHERE a.Nome = #Nome)
BEGIN
INSERT INTO TableA (Nome, Descritive)
OUTPUT Inserted.id -- or whatever the id is called
INTO #ids;
VALUES (#Nome,#Descritivo)
INSERT INTO TableB (id, sampletable)
SELECT id, #SampleTable
FROM #ids;
END;
END; -- Gest_Doc_SampleProc
In addition to using OUTPUT, this code also adds column lists to the INSERTs. That is another best practice.

INSERT ONLY SPECIFIC COLUMN FROM A STORED PROCEDURE RESULT

I want to know if it is possible to insert to a table from a specific column of result from a stored procedure?
Something like:
declare #temp as table(
id int
)
insert #temp
exec getlistofStudents --returns multiple columns
this is an example only, Thanks for the help..
You can take a 2 step approach. First INSERT INTO a #TempTable, then populate the #TempVariable with another INSERT INTO, selecting the single column.
DECLARE #temp AS TABLE
(
ID int
);
CREATE TABLE #tempTable1
(
Column1 int,
Column2 int
);
INSERT INTO #tempTable1
Exec getlistofStudents
INSERT INTO #temp
SELECT Column1 FROM #tempTable1

Get List of all last inserted IDs to a table

When I want to get last inserted ID to a table I use it like this:
insert into table1(col1,col2,col3)
values(val1,val2,val3)
declare #last_id int = scope_identity()
Now I have stored procedure that gets a value inserts multiple items:
insert into table1(col1,col2,col3)
select #val1,#val2,val3 from table2 where value=#value //#value is a single value that is passed to procedure as argument
now how can I get the list of IDs of these multiple rows that are added to table1?
declare #inserted table (Id int)
insert into table1(col1,col2,col3)
output inserted.Id into #inserted (Id)
select #val1,#val2,val3
from table2
where value=#value
select * from #inserted
The SCOPE_IDENTITY() gets you the last generated Identity Value in the identity column. to get all the newly inserted values you will need to make use of OUTPUT clause along with a table variable. See below how you can do that.
DECLARE #New_IDs TABLE(IDs INT)
insert into table1(col1,col2,col3)
OUTPUT inserted.Id_column INTO #New_IDs
select #val1,#val2,val3
from table2
where value=#value
SELECT * FROM #New_IDs