I want to select back the data I just inserted into the database. I know OUTPUT can be used and we can call INSERTED.[ColumnName] to grab the values that were inserted. Can these values be set to a variable of some kind or given an alias? I do not want to use a TEMP table because I wish to use variables if possible.
It would be nice for the solution to work when the PK is or is not an identity column.
EDIT:
Contacts.PhoneNumberID is a foreign key to PhoneNumber.ID
I want to do both insert statements back to back and I need the ID from PhoneNumber to use for the Contacts.PhoneNumberID
EDIT:
[PhoneNumber].[ID] has a default specified in the database, that is how the ID is being set
Here is what I am looking for:
INSERT INTO [PhoneNumber] (Number)
OUTPUT INSERTED.ID, INSERTED.Number
VALUES ('555-555-5555')
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', {ID From previous insert})
Can we some how alias the insert statement to say:
INSERT INTO [PhoneNumber] (Number)
OUTPUT INSERTED.ID, INSERTED.Number
VALUES ('555-555-5555') as A
I know we cannot actually Alias an insert statement as done above, I am looking for the proper way to do this.
Then you could do this:
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', A.ID)
I am going for a final result of something similar to this:
INSERT INTO [PhoneNumber] (Number)
OUTPUT INSERTED.ID, INSERTED.Number
VALUES ('555-555-5555') as A
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', A.ID)
Reason I am trying to do this:
I wish to put both insert statements in a transaction block, if one of them fails then I can rollback and not commit anything.
For this purpose you need to use IDENT_CURRENT('your_table) function. It returns the last IDENTITY value produced in a table, regardless of the connection that created the value, and regardless of the scope of the statement that produced the value.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.
So your code will look like this:
Declare #last_ident numeric(38,0)
INSERT INTO [PhoneNumber] (Number)
VALUES ('555-555-5555')
SELECT #last_ident = IDENT_CURRENT('PhoneNumber')
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', #last_ident)
More information you can find here
EDIT:
If you need to get non Identity field you should use OUTPUT then
Declare #tbl table(ID int)
INSERT INTO [PhoneNumber] (Number)
OUTPUT INSERTED.ID INTO #tbl
VALUES ('555-555-5555')
Declare #id int
select #id = ID from #tbl
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName',#id)
You can get the latest inserted from SCOPE_IDENTITY().
So your code could look like that:
DECLARE #id AS INT;
INSERT INTO [PhoneNumber] (Number)
VALUES ('555-555-5555')
SELECT #id = SCOPE_IDENTITY();
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', #id)
For DECLARE #id AS INT; you need to change the type of the variable to fit the data type PhoneNumberID column
You could also use Sequence.
Declare #newId int = NEXT VALUE FOR [PhoneNumber_Seq];
Insert into [PhoneNumber] (ID, Number)
values(#newId, '555-555-55555')
INSERT INTO [Contacts] (Name,PhoneNumberID)
VALUES ('SomeName', #newId)
I am writing a store procedure in T-SQL which inserts a row to the table, based on parameters
#UserName ,#CompanyName ,#RestName,#Desc
INSERT INTO Orders(UserId,CompanyId,RestId)
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id FROM UserNames,CompanyNames,RestNames
WHERE
UserNames.Name = #UserName AND
CompanyNames.Name = #CompanyName AND
RestNames.Name = #RestName
Besides the insert to the 3 columns above,I also want to insert the #Desc value.
I tried :
INSERT INTO Orders(UserId,CompanyId,RestId,Desc)
VALUES(
(SELECT UserNames.Id,CompanyNames.Id,RestNames.Id FROM UserNames,CompanyNames,RestNames
WHERE
UserNames.Name = #UserName AND
CompanyNames.Name = #CompanyName AND
RestNames.Name = #RestName),#Desc)
Only one expression can be specified in the select list when the subquery is not introduced with EXISTSt-
It doesn`t work giving the following error:
#UserName ,#CompanyName ,#RestName,#Desc
INSERT INTO Orders(UserId,CompanyId,RestId, Desc_Column)
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id , #Desc --<-- Just SELECT that variable
FROM UserNames,CompanyNames,RestNames -- in your select statement.
WHERE UserNames.Name = #UserName
AND CompanyNames.Name = #CompanyName
AND RestNames.Name = #RestName
Retrieve ID Values Inserted
DECLARE #t TABLE (ID INT); --<-- Declare a table variable
INSERT INTO Orders(UserId,CompanyId,RestId, Desc_Column)
OUTPUT Inserted.ID INTO #t --<-- use OUTPUT, get values from INSERTED Table
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id , #Desc --and insert them into your table variable
FROM UserNames,CompanyNames,RestNames
WHERE UserNames.Name = #UserName
AND CompanyNames.Name = #CompanyName
AND RestNames.Name = #RestName
/*At last just simply select from that table variable to get the inserted IDs*/
SELECT * FROM #t
Hi I have a problem with my stored procedure, I want to insert into three tables which I created a stored procdure to do that, yet I have these two tables called wishlist and general. I want to insert into the wishlist table if the dateaquired row is null but the script I created inserts into the the table regardless, could someone please improve my script so that it does not insert into my wishlist table if my dateaquired row from my general table is not null.
USE [MediaPlayer]
GO
/****** Object: StoredProcedure [dbo].[CreateBooks] Script Date: 12/03/2013 19:05:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CreateBooks]
-- Add the parameters for the stored procedure here
#Name nvarchar (250),
#FileName nvarchar (250),
#FilePath nvarchar (50),
#FileSize float,
#DateAdded date,
#MediaLength nvarchar (50),
#MediaSubType nvarchar(50),
#MediaType nvarchar(50),
#Thumbnail image,
#DateAquired nvarchar(50),
#BooksName nvarchar (50),
#Publisher nvarchar(50),
#Author nvarchar(50),
#YearOfPublication date,
#Genre nvarchar(50),
#ISBN nvarchar (50),
#Synoposis nvarchar(50),
#SeriesTitle nvarchar(50),
#SeriesNumber nvarchar(50),
#GeneralID int output,
#BookID int output,
#WishListID int output
AS
BEGIN
Insert into dbo.General
(Name, FileName, FilePath, FileSize, DateAdded, MediaLength,
MediaSubType, MediaType, Thumbnail, DateAquired)
values (#Name, #FileName, #FilePath, #FileSize, #DateAdded, #MediaLength,
#MediaSubType, #MediaType, #Thumbnail, #DateAquired)
SET #GeneralID = ##IDENTITY
insert into dbo.Book
(GeneralID, BooksName, Publisher, Author, [Year of publication], Genre,
ISBN, Synoposis,[Series Title],[Series Number])
Values (IDENT_CURRENT('dbo.General'), #BooksName, #Publisher, #Author, #YearOfPublication, #Genre,
#ISBN, #Synoposis, #SeriesTitle, #SeriesNumber)
SET #BookID = ##IDENTITY
Select GeneralID, Name, FileName, FilePath,FileSize,DateAdded,MediaLength,MediaSubType,MediaType, Thumbnail,DateAquired As Wishlist
From General where NULLIF(DateAquired,'')IS Null
Select * from WishLists
select GeneralID, MediaSubType, Name
From General where NOT EXISTS (Select Name from WishLists Where Name =#Name);
insert into Wishlists (generalID ,MediaType, Name)
values ((IDENT_CURRENT('dbo.General')),#MediaSubType, #Name)
SET #WishListID = ##IDENTITY
select * from wishlists
END
I could be wrong but to me it seems you are missing some logic cases.
Your code:
Select GeneralID, Name, FileName, FilePath, FileSize, DateAdded,
MediaLength,MediaSubType,MediaType, Thumbnail, DateAquired As Wishlist
From General where NULLIF(DateAquired,'')IS Null
What this does is selects the named fields from General where DateAcquired is Null. On a side note, I believe (I may be wrong) that if you want all those fields AS Wishlist, you should have them all in parentheses like:
Select (GeneralID, Name, FileName, FilePath, FileSize, DateAdded,
MediaLength,MediaSubType,MediaType, Thumbnail, DateAquired) As Wishlist
From General where NULLIF(DateAquired,'')IS Null
Regardless, once you have this data you aren't doing anything with it, you are moving into a new select query, selecting * from Wishlists. Then you are selecting from General again where the the name is not in the table already. Then you are inserting into Wishlists the current Identity value of dbo.General, #MediaSUbType, #Name.
So all this code is really doing is running some queries, then regardless of those results, is inserting the Identity value of dbo.General, and the status values #MediaSubType and #Name into the table wishlist. In order for all the queries you run before to have an affect on what gets inserted, you need to use cases.
I don't know enough about the tables and things to write up the code you will need, but this answer should give you an idea of how to use CASE WHEN to do what you need.
Hope this helps some and isn't just useless ramblings from me.
If you're just trying to skip the WishList insert based on the #DateAquired being null you can modify your script as below. Please reply if this is not what you want.
BEGIN
Insert into dbo.General(Name, FileName, FilePath, FileSize, DateAdded, MediaLength, MediaSubType, MediaType, Thumbnail, DateAquired)
values (#Name, #FileName, #FilePath, #FileSize, #DateAdded, #MediaLength, #MediaSubType, #MediaType, #Thumbnail, #DateAquired);
SET #GeneralID = scope_identity(); --use this instead of ##IDENTITY
insert into dbo.Book(GeneralID, BooksName, Publisher, Author, [Year of publication], Genre, ISBN, Synoposis,[Series Title],[Series Number])
Values (#GeneralID, #BooksName, #Publisher, #Author, #YearOfPublication, #Genre, #ISBN, #Synoposis, #SeriesTitle, #SeriesNumber)
SET #BookID = scope_identity(); --use this instead of ##IDENTITY
-- you already have the DateAquired from the insert into dbo.General above, so just use the param #DateAquired
if(#DateAquired is null)
begin
insert into Wishlists (generalID, MediaType, Name)
values (#GeneralId, #MediaSubType, #Name)
SET #WishListID = scope_identity(); --use this instead of ##IDENTITY
end
select [InsertedGeneralId] = #GeneralID, [InsertedBookID] = #BookID, [InsertedWishListID] = #WishListID
END
AS
BEGIN
Insert into dbo.General
(Name, FileName, FilePath, FileSize, DateAdded, MediaLength,
MediaSubType, MediaType, Thumbnail, DateAquired)
values (#Name, #FileName, #FilePath, #FileSize, #DateAdded, #MediaLength,
#MediaSubType, #MediaType, #Thumbnail, #DateAquired)
SET #GeneralID = SCOPE_IDENTITY() --<--
insert into dbo.Book
(GeneralID, BooksName, Publisher, Author, [Year of publication], Genre,
ISBN, Synoposis,[Series Title],[Series Number])
Values (IDENT_CURRENT('dbo.General'), #BooksName, #Publisher, #Author,
#YearOfPublication, #Genre, #ISBN, #Synoposis, #SeriesTitle, #SeriesNumber)
SET #BookID = SCOPE_IDENTITY()
Select GeneralID, Name, FileName, FilePath,FileSize,DateAdded,MediaLength
,MediaSubType,MediaType, Thumbnail,DateAquired As Wishlist
From General where NULLIF(DateAquired,'')IS Null
Select * from WishLists
select GeneralID, MediaSubType, Name
From General where NOT EXISTS (Select Name from WishLists Where Name =#Name);
IF (#DateAquired IS NULL)
BEGIN
insert into Wishlists (generalID ,MediaType, Name)
values ((IDENT_CURRENT('dbo.General')),#MediaSubType, #Name)
SET #WishListID = SCOPE_IDENTITY()
END
select * from wishlists
END
Also use SCOPE_IDENTITY() instead of ##IDENTITY as it will return last generate Identity in that column , even if it was created by a concurrent connection.
I have a requirement to insert multiple rows into table1 and at the same time insert a row into table2 with a pkID from table1 and a value that comes from a SP parameter.
I created a stored procedure that performs a batch insert with a table valued parameter which contains the rows to be inserted into table1. But I have a problem with inserting the row into table2 with the corresponding Id (identity) from table1, along with parameter value that I have passed.
Is there anyone who implemented this, or what is the good solution for this?
CREATE PROCEDURE [dbo].[oSP_TV_Insert]
#uID int
,#IsActive int
,#Type int -- i need to insert this in table 2
,#dTableGroup table1 READONLY -- this one is a table valued
AS
DECLARE #SQL varchar(2000)
DECLARE #table1Id int
BEGIN
INSERT INTO dbo.table1
(uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active)
SELECT
#uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active
,#G_Active
FROM #dTableGroup
--the above query will perform batch insert using the records from dTableGroup which is table valued
SET #table1ID = SCOPE_IDENTITY()
-- this below will perform inserting records to table2 with every Id inserted in table1.
Insert into table2(#table1ID , #type)
You need to temporarily store the inserted identity values and then create a second INSERT statement - using the OUTPUT clause.
Something like:
-- declare table variable to hold the ID's that are being inserted
DECLARE #InsertedIDs TABLE (ID INT)
-- insert values into table1 - output the inserted ID's into #InsertedIDs
INSERT INTO dbo.table1(ID, Name, Contact, Address, City, State, Zip, Phone, Active)
OUTPUT INSERTED.ID INTO #InsertedIDs
SELECT
#ID, Name, Contact, Address, City, State, Zip, Phone, Active, #G_Active
FROM #dTableGroup
and then you can have your second INSERT statement:
INSERT INTO dbo.table2(Table1ID, Type)
SELECT ID, #type FROM #InsertedIDs
See the MSDN docs on the OUTPUT clause for more details on what you can do with the OUTPUT clause - one of the most underused and most "unknown" features of SQL Server these days!
Another approach using OUTPUT clause and only one statement for inserting data in both destination tables:
--Parameters
DECLARE #TableGroup TABLE
(
Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #Type INT;
--End Of parameters
--Destination tables
DECLARE #FirstDestinationTable TABLE
(
FirstDestinationTableID INT IDENTITY(1,1) PRIMARY KEY
,Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #SecondDestinationTable TABLE
(
SecondDestinationTable INT IDENTITY(2,2) PRIMARY KEY
,FirstDestinationTableID INT NOT NULL
,[Type] INT NOT NULL
,CHECK([Type] > 0)
);
--End of destination tables
--Test1
--initialization
INSERT #TableGroup
VALUES ('Bogdan SAHLEAN', '0721200300')
,('Ion Ionescu', '0211002003')
,('Vasile Vasilescu', '0745600800');
SET #Type = 9;
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
SELECT *
FROM #FirstDestinationTable;
SELECT *
FROM #SecondDestinationTable;
--End of test1
--Test2
--initialization
DELETE #TableGroup;
DELETE #FirstDestinationTable;
DELETE #SecondDestinationTable;
INSERT #TableGroup
VALUES ('Ion Ionescu', '0210000000')
,('Vasile Vasilescu', '0745000000');
SET #Type = 0; --Wrong value
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
DECLARE #rc1 INT, #rc2 INT;
SELECT *
FROM #FirstDestinationTable;
SET #rc1 = ##ROWCOUNT;
SELECT *
FROM #SecondDestinationTable;
SET #rc2 = ##ROWCOUNT;
RAISERROR('[Test2 results] #FirstDestinationTable: %d rows; ##SecondDestinationTable: %d rows;',1,1,#rc1,#rc2);
--End of test1
Since you need all inserted identity values, look at the output clause of the insert statement: http://msdn.microsoft.com/en-us/library/ms177564.aspx