I have a question, let's say I have two tables I am doing an insert operation to the first table with the stored procedure, but how do I insert the auto incrementing ID in the first table in the other table? 🤔🤔
Would be good if you provided one example of what you are trying to achieve.
To get the inserted Id by the store procedure, you could use SCOPE_IDENTITY.
SCOPE_IDENTITY(): returns the last identity value generated in the current scope.
For instance:
INSERT INTO.... VALUES(); SELECT SCOPE_IDENTITY();
This query will insert into a the given table and will return the id inserted.
You can also use Select ##IDENTITY, this will return the last id inserted regardless the scope.
INSERT INTO.... VALUES(); SELECT ##IDENTITY;
Related
How can I get get generated ID from primary key and then add it to another table in ASP.NET via SCOPE_IDENTITY?
For example:
Last generated ID on column NRRENDOR is number 26, I have deleted the rows. Now when I add datas to the database the nexy generated ID on NRRENDOR will be number 27. That number I want it to add to column NRD.
In your INSERT code, assuming it's in a stored procedure, using SCOPE_IDENTITY will get you the last identity that was inserted, which you can either reuse in the stored procedure or return to your app to use in another statement.
Some dummy SQL to demonstrate:
INSERT INTO NRRENDOR(SomeColumn) VALUES(1)
DECLARE #LastID int
// set #LastID to the last id inserted
SELECT #LastID = SCOPE_IDENTITY()
// to use in same procedure
INSERT INTO NRD (SomeColumn) VALUES(#LastID)
// to return it to code - or you could use an output parameter
SELECT #LastID
What has this got to do with ASP.NET? SQL would suffice.
INSERT INTO [Table2]( NRD)
SELECT MAX(NRRENDOR)
FROM Table1
' WITH (ROWLOCK, XLOCK, HOLDLOCK)
The correct way to do it will be to use #SCOPE_IDENTITY after you perform insertion as Tanner suggested. It will be worth noting that there is another way to get the current identity, ie, IDENT_CURRENT. You can use it like this
SELECT IDENT_CURRENT('Table1') + 1 as Current_Identity
Please note this too
Be cautious about using IDENT_CURRENT to predict the next generated
identity value. The actual generated value may be different from
IDENT_CURRENT plus IDENT_INCR because of insertions performed by other
sessions.
This comment from marc_s sums it all. How to get the next identity value from SQL Server
I am inserting records through a query similar to this one:
insert into tbl_xyz select field1 from tbl_abc
Now I would like to retreive the newly generated IDENTITY Values of the inserted records. How do I do this with minimum amount of locking and maximum reliability?
You can get this information using the OUTPUT clause.
You can output your information to a temp target table or view.
Here's an example:
DECLARE #InsertedIDs TABLE (ID bigint)
INSERT into DestTable (col1, col2, col3, col4)
OUTPUT INSERTED.ID INTO #InsertedIDs
SELECT col1, col2, col3, col4 FROM SourceTable
You can then query the table InsertedIDs for your inserted IDs.
##IDENTITY will return you the last inserted IDENTITY value, so you have two possible problems
Beware of triggers executed when inserting into table_xyz as this may change the value of ##IDENTITY.
Does tbl_abc have more than one row. If so then ##IDENTITY will only return the identity value of the last row
Issue 1 can be resolved by using SCOPE__IDENTITY() instead of ##IDENTITY
Issue 2 is harder to resolve. Does field1 in tbl_abc define a unique record within tbl_xyz, if so you could reselect the data from table_xyz with the identity column. There are other solutions using CURSORS but these will be slow.
SELECT ##IDENTITY
This is how I've done it before. Not sure if this will meet the latter half of your post though.
EDIT
Found this link too, but not sure if it is the same...
How to insert multiple records and get the identity value?
As far as I know, you can't really do this with straight SQL in the same script. But you could create an INSERT trigger. Now, I hate triggers, but it's one way of doing it.
Depending on what you are trying to do, you might want to insert the rows into a temp table or table variable first, and deal with the result set that way. Hopefully, there is a unique column that you can link to.
You could also lock the table, get the max key, insert your rows, and then get your max key again and do a range.
Trigger:
--Use the Inserted table. This conaints all of the inserted rows.
SELECT * FROM Inserted
Temp Table:
insert field1, unique_col into #temp from tbl_abc
insert into tbl_xyz (field1, unique_col) select field1, unique_col from tbl_abc
--This could be an update, or a cursor, or whatever you want to do
SELECT * FROM tbl_xyz WHERE EXISTS (SELECT top 1 unique_col FROM #temp WHERE unique_col = tbl_xyz.unique_col)
Key Range:
Declare #minkey as int, #maxkey as int
BEGIN TRANS --You have to lock the table for this to work
--key is the name of your identity column
SELECT #minkey = MAX(key) FROM tbl_xyz
insert into tbl_xyz select field1 from tbl_abc
SELECT #maxkey = MAX(key) FROM tbl_xyz
COMMIT Trans
SELECT * FROM tbl_xyz WHERE key BETWEEN #minkey and #maxkey
I have a stored procedure with a SELECT statement that outputs one row. It is something like this:
CREATE PROCEDURE [dbo].[CreateCustomer]
...
INSERT INTO Customers values(, , , ,)
SELECT CustomerID, FirstName, LastNam.....
INSERT Roles values(, , , .....
This selects the newly stored values back from the Customers table. The second insert uses the new CustomerID to insert a new row to the Roles table.
Is there a way to just get the customerID from the above select statement without querying again for the CustomerID?
I have tried to declare a variable and do it like this:
SELECT takenCustomerID = CustomerID, FirstName, LastNam....(rest of query statement)
But I have to declare all the variables and do it this way:
SELECT takenCustomerID, takenFirstName, takenLastNa... = CustomerID, FirstName, LastNam... (rest of query statement)
But, I think this is bad because it wastes lot of memory on the server side.
So, is there an easy way of getting individual values right away without declaring all the variables in the select statement, such as an inbuilt TEMP-like variable where I can call TEMP("customerID") and get that value?
Also, Can there be more than one SELECT statement in a stored procedure? How can we get the select values from the select statement we want?
I am asking more out of curiosity because I already know a way to get the value. I just want to know if there is a more elegant way.
Accessing Inserted Values
It is simple. Use the OUTPUT clause to return the values you just created.
DECLARE #Customers TABLE (
CustomerID uniqueidentifier,
FirstName varchar(100),
LastName varchar(100)
);
INSERT dbo.Customers
OUTPUT Inserted.*
INTO #Customers
SELECT newsequentialid(), #FirstName, #LastName, ...;
-- now you have all the values of the new row in the `#Customers` table variable.
Then you can do this:
INSERT dbo.Roles
SELECT
CustomerID,
#OtherValue,
#AnotherValue,
AnyotherColumnFrom#Customers
FROM #Customers;
If you have no further use for the values from the inserted Customer row, you could even do away with the table variable and just OUTPUT directly into the Roles table, assuming that all the values that go into that come from variables.
The OUTPUT clause gives access to the inserted values using the special meta-table Inserted. However, you can use variables and expressions with constants as well.
The good thing about using this method is that you can handle many inserted rows at once. If you are inserting only one row, you need only the CustomerID afterward, and you need to use it more than once, then instead do it this way:
DECLARE #CustomerID uniqueidentifier = newsequentialid();
INSERT #Customer VALUES (#CustomerID, ...);
INSERT #Roles VALUES (..., #CustomerID ...);
By creating the GUID in advance, you don't need to get it back out of the table. By the way, newsequentialid() is probably superior to newid() if it is the clustered index (which is probably true), because you will avoid the page splits that newid would cause.
Returning Multiple Result Sets
This is always possible. Whatever means you are using to query will have a method that advances your data access object to the next recordset. If you're using a DataReader then look into the NextResult method. In Classic ADO, recordsets have a NextRecordset method.
Unless you redirect it manually to a table, the SELECT will go only to the output stream, so no: you can't automatically access values from a previous select.
You might just be looking for SCOPE_IDENTITY():
declare #id int
insert ....
values (...)
set #id = SCOPE_IDENTITY()
In the general case of DML, another candidate is the OUTPUT clause.
For more general composite selects based on existing selects, a table-variable may help:
declare #foo table (id int not null, name nvarchar(100) not null) // etc
insert #foo (id, name)
select id, name from Foo where ...
select * from #foo // for output
// but we still have the #foo data available for subsequent query
... // more TSQL here
With multiple select statements, it depends entirely on what API you are using; however, the raw ADO.NET API here is IDataReader, which has the NextResult() method. Typical usage for multi-grid would be:
using(var reader = cmd.ExecuteReader()) {
do {
while(reader.Read()) {
// i.e. for each row in this grid
...
}
} while (reader.NextResult()); // <== for each grid
}
Note the difference between while(...) {...} and do {...} while(...) here is because you automatically start in the first grid, but you need to progress to the first row in that grid manually.
I'm new to SQL and C# and am currently trying to create a library software. I'm facing a bit of a problem and would appreciate your input.
I have three tables:
Books (BookID, Title)
Author (AuthorID, AuthorFname, AuthorLname)
WrittenBy (BookID, AuthorID)
BookId in the table Books and AuthorID in the table Author are indexed and are the primary keys.
What I need to do is,
get the bookId from the books table,
get the authorID from the author table,
insert these two values into the writtenby table
My solution is to write two separate SQL statements to select the id columns and then enter it into the third table.
But what if there are two books with the same title?
Is there a way to get the last inserted values in SQL?
If those ID columns are of type INT IDENTITY and you're using SQL Server, then yes - you can get the last inserted value:
INSERT INTO dbo.Books(Title) VALUES('New Book')
DECLARE #NewBookID INT
SELECT #NewBookID = SCOPE_IDENTITY()
INSERT INTO dbo.Author(AuthorFname, AuthorLname) VALUES('John', 'Doe')
DECLARE #NewAuthorID INT
SELECT #NewAuthorID = SCOPE_IDENTITY()
INSERT INTO dbo.WrittenBy(BookID, AuthorID) VALUES(#NewBookID, #NewAuthorID)
The SCOPE_IDENTITY() function will return that last inserted IDENTITY value by the previous statement, which should be exactly what you're looking for, correct?
There are different ways are available :
##IDENTITY
OR
SCOPE_IDENTITY()
OR
IDENT_CURRENT(‘tablename’)
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
You should have a column called something like InsertedDate or CreatedDate. That's the best way to order by last inserted.
Other than that, this sounds like a homework question. This isn't want SO is for - search engines are your friends.
Is is possible to get new values for Id (IDENTITY) before inserting data in a table ?
Is is possible to write something like that :
INSERT INTO Table1
SELECT *GET_NEW_IDENTITY*, Field1, Field2 FROM Table2
I need the values of Id because I want to insert data in Table1 and, just after, insert data in another table which has a foreign key linked to Table1 (with Id)
IDENT_CURRENT. Returns the last identity value generated for a specified table or view. The last identity value generated can be for any session and any scope.
SCOPE_IDENTITY. Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch.
OUTPUT. Returns information from, or expressions based on, each row affected by an INSERT, UPDATE, DELETE, or MERGE statement. [...] The OUTPUT clause may be useful to retrieve the value of identity or computed columns after an INSERT or UPDATE operation.
you can also have the insert statement return the newly inserted value for later use. for example
create table demo( Id int identity primary key, data varchar(10))
go
insert into demo(data) output inserted.Id values('something')
No, because it is the act of adding a row which creates the new identity value.
To do what you want,
SELECT newid = ##identity FROM table
just after the INSERT
Why would you need to get the identity value before doing the insert? Just do the insert to Table2 returning SCOPE_IDENTITY() and then use the resulting Id value for your insert to Table1.
This is just fast demo. You can use new ID for insert for update, insert into another table, query, etc. in another way. Hoping I did not insert errors into script during formatting, editing post
-- run [1] before this script once to have environment
--create temporary table once if not dropped after
-- really only ID field is needed, the others are for illustration
create table #temp_id (Id int, d1 int, d2 int)
select * from Table2;-- this is read-only, filled once here source
select * from Table1;--interesting for following runs
insert into Table1
OUTPUT INSERTED.id
-- really only ID is needed, the rest is for illustration
, inserted.d1, inserted.d2 INTO #temp_id
select field1, field2, null-- null to be merged later
-- or inserted/updated into another table
from Table2;
select * from Table1;
select * from #temp_id;
MERGE Table1 AS TARGET
USING #temp_id AS SOURCE
ON (TARGET.id = SOURCE.id)
WHEN MATCHED
--AND OR are redundant if Table1.ID is PK
THEN
UPDATE SET TARGET.IDnew = SOURCE.id;
select * from Table1;
--drop table #temp_id
--drop table table1
--drop table table2
[1]
Reproducing the tables from question and filling with data
create table Table1( Id int identity primary key, d1 int, d2 int, IDnew int)
create table Table2( field1 int, field2 int)
insert into table2 values(111,222)
insert into table2 values(333,444)
IDENT_CURRENT('tableName') returns the current value of the identity for the given table. The identity value that will be assigned on Insert will be IDENT_CURRENT('tableName') + IDENT_INCR('tableName').
SELECT IDENT_CURRENT('tableName') + IDENT_INCR('tableName')