I have a server and many clients, my application is on clients and database on server, i have one table
Table --> Id --> int Auto-increment,
Name --> nvarchar(50),
So, whenever i insert a new row from client with query
Insert into Table Name Values('NameValue')
It inserts the row and sql auto generates the Id field. So, to fetch its Id, I use the following query
Select max(Id) as maxId from Table
but both queries are on different connections
It works well when only one client is operating at a time, but when multiple clients are working, Many insert queries are requested by clients before i could request the 'getMaxId' query.
You can use the following:
SELECT SCOPE_IDENTITY()
This selects the last-inserted identity.
The best way is to run a command to get the recent inserted value.
There are three commands you can run to do that.
This link will explain them
the best is
SELECT SCOPE_IDENTITY()
because if you have a table A that calls a trigger and this trigger inserts data on a table B, this command will get you the ID of the table A, while ##IDENTITY will get you the id of table B
Try this:
DECLARE #a TABLE (
Id int IDENTITY (1, 1),
b VARCHAR(1000)
)
DECLARE #b TABLE (
Id INT
)
INSERT #a (b)
OUTPUT INSERTED.Id INTO #b
SELECT NAME
FROM sys.objects
SELECT * FROM #a
SELECT * FROM #b
Or, you can always use that for retrieving the latest ident:
SELECT IDENT_CURRENT('TABLE_NAME')
Or use
SELECT SCOPE_IDENTITY()
Rather use:
select ##identity
instead of select max(id)...
It will return the last generated identity for the current connection.
use this, but it works for PHP
$id = mysql_insert_id();
and for c#
Int32 newId = (Int32) myCommand.ExecuteScalar();
Add the following after inserting instead of Max(id) selection.
SELECT SCOPE_IDENTITY()
Make function in sql, where you will add row and get ID by SELECT SCOPE_IDENTITY(). While you call function you will get ID which is exactly added.
try this hope it will may help You
declare #table1 table(id int identity,name varchar(50))
insert into #table1 (name) output inserted.id values('abc')
insert into #table1 (name) output inserted.id values('xyz')
insert into #table1 (name) output inserted.id values('pqr')
for more see here
Related
I am reading from a file and I have to insert it to database. I have tables like:
Persons (name, surname,...)
Jobs (name)
Season (name, year)
And I don't insert ID, it is added automatically in database (Guid). I want to insert data into the table ApplicationsForJobs which has columns (PersonId, JobId, SeasonId) and my question is: how can I get those IDs?
The SQL Server DB has 2 ways for getting identity id field value during the insert process.
-- 1) when inserted many records
insert into tbl_test (NAME, CODE)
OUTPUT inserted.id
select NAME, CODE from tbl_test_data
-- 2) when inserted only one record
insert into tbl_test (NAME, CODE)
VALUES ('Sarah', 'AB154342');
SELECT SCOPE_IDENTITY();
In SQL DB, if table column is uniqueidentifier then you can get the result like:
DECLARE #IDs TABLE([ID] [uniqueidentifier]);
INSERT [Persons] ([name], [surname])
OUTPUT INSERTED.[ID] INTO #IDs
VALUES (N'abc', N'xyz');
--Display the result set of the table variable.
SELECT [ID] FROM #IDs;
Same goes for Jobs and Season and then you will insert all these IDs into ApplicationsForJobs table.
If column is not uniqueidentifier then use the
I'm inserting datatable using stored procedure and created a type table before,
the query is i want to get back all the 'ProdID' that has been inserted in this session.
for the single insertion i can get the scope identity but i want to get all for the recent insertion.
Thanks in advance.
[dbo].[sp_Isert] (#dt_Product Product_Table READONLY, #ProdID int out)
AS
INSERT into tblProduct (Name,Batch,Qty,ExpDate)
SELECT Name, Batch, Qty, ExpDate
FROM #dt_Product;
set #ProdID = Scope_Identity( )
select Scope_Identity( ) ProdID
Do not use scope_identity() - use the output clause instead.
Note that SQL Server does not support table valued parameters as out parameters, meaning the only way to return a record set from a stored procedure is either by using the output clause (not into table) or by executing a select statement.
Also, do not use the sp prefix for stored procedured.
Microsoft is using this prefix for system procedues, so you might get a name collision.
ALTER PROCEDURE [dbo].[stp_Isert] (#dt_Product Product_Table READONLY)
AS
INSERT into tblProduct (Name,Batch,Qty,ExpDate)
OUTPUT Inserted.Id -- This will return a recordset with the inserted ids to the calling application.
SELECT Name, Batch, Qty, ExpDate
FROM #dt_Product;
Update
I've made a sample script for you to check. When I'm running this on my SQL Server instance, I get the expected results:
CREATE TABLE tbl_TestOutputClause (Id int identity(1,1), Col int );
GO
CREATE TYPE udt_TestOutputClauseIntegers AS TABLE (Value int);
GO
CREATE PROCEDURE stp_TestOutputClauseInsert (#Values dbo.udt_TestOutputClauseIntegers READONLY)
AS
INSERT INTO tbl_TestOutputClause(Col)
OUTPUT INSERTED.Id
SELECT Value
FROM #Values;
GO
CREATE PROCEDURE stp_TestOutputClauseGetInsertedValues
AS
DECLARE #Ids AS TABLE (Id int);
DECLARE #Vals dbo.udt_TestOutputClauseIntegers;
INSERT INTO #Vals (Value) VALUES (1), (2), (3);
INSERT INTO #Ids
EXEC stp_TestOutputClauseInsert #Vals;
-- should return three rows with the values 1, 2 and 3.
SELECT *
FROM #Ids;
GO
EXEC stp_TestOutputClauseGetInsertedValues;
-- clean up
DROP TABLE tbl_TestOutputClause;
DROP PROCEDURE stp_TestOutputClauseInsert;
DROP PROCEDURE stp_TestOutputClauseGetInsertedValues
DROP TYPE udt_TestOutputClauseIntegers;
I'm faced with a little problem. The situation is:
I have a MSSQL table which contains IDs (int, identity, primarykey), and names (string).
This table is huge, so i don't want to fill the entire dataset just for one LINQ-query.
I have a search algorithm, which fills a List<int> with more than one ID.
I want to load the matching rows in a datagridview with the following code:
dataGridView1.DataSource = tbl_WorklistTableAdapter.GetDataByID(ids_here);
But i can't handle multiple IDs, just a single. The GetDataByID() code needs to be this (i think):
SELECT [ID]
,[NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (#searchterm)
However WHERE ID IN accepts comma-separated ints, like 1,2,3. But the #variable is just one int.
How should i convert string to ints?
Thank you, and sorry for bad eng. :)
In that case you need to change in sql so you need to generate one temp table for comma separated id and apply condition in the your query.
Like:-
DECLARE #variables VARCHAR(200) = #searchterm -- Your Variable
CREATE TABLE #temp(ID NUMERIC) DECLARE #temp VARCHAR(200)
SET #temp = #variables WHILE LEN(#temp) > 0 BEGIN DECLARE #t1 VARCHAR(200)
IF CHARINDEX(',',#temp) > 0
BEGIN
SET #t1 = SUBSTRING(#temp,0,CHARINDEX(',',#temp))
INSERT INTO #TEMP SELECT #t1
SET #temp = SUBSTRING(#temp,CHARINDEX(',',#temp)+1,len(#temp))
END
ELSE
BEGIN
INSERT INTO #TEMP SELECT #temp
SET #temp = ''
END
END
SELECT [ID]
,[NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT ID FROM #temp)
You can use the built-in function SPLIT_STRING function:
SELECT [ID], [NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT VALUE FROM SPLIT_STRING(#searchterm,','))
This only works on Compatibility level 130 or greater.
If you are on an older version of SQL Server you can follow this answer, which defines an equivalent function:
SELECT [ID], [NAME]
FROM [DataBase].[dbo].[tbl_Namelist]
WHERE ID IN (SELECT VALUE FROM fn_split_string(#searchterm,','))
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
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')