I'm using this query:
INSERT INTO [LepidoliteDB].[dbo].[EGelLayerWeighingData] ([EGelWeighingDataID], [Amount], [ContainerID], [Portions],
[PortionNumber], [Canceled], [LayerID], [WeighingDone], [InsertDone],
[MeasuresDone], [StartDateAndTime], [EndDateAndTime])
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
SELECT SCOPE_IDENTITY()
But SCOPE_IDENTITY() always returns 1.
What am I missing?
Maybe you have an instead-of / for trigger there? what version of MSSQL are you using? Have you tried doing this without a database name? Have you tried this with a begin-end block?
Have you read this article ##IDENTITY vs SCOPE_IDENTITY() vs IDENT_CURRENT
I know this is an old thread, but I was having this same issue, and I managed to solve it by going into my XSD and on the query, changing the ExecuteMode of the query from NonQuery to Scalar. This stopped it always returning 1 and instead returning the ID of the previously added row.
It was probably down to me trying to add the SELECT to the INSERT afterwards, rather than doing it all at once and the UI making it correctly for me.
Best way to write it is ..
RETURN SCOPE_IDENTITY()
You can also use ##IDENTITY and IDENT_CURRENT for this
SCOPE_IDENTITY, IDENT_CURRENT, and ##IDENTITY are similar functions because they return values that are inserted into identity columns.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the value generated for a specific table in any session and any scope. For more information, see IDENT_CURRENT (Transact-SQL).
SCOPE_IDENTITY and ##IDENTITY return the last identity values that are generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; ##IDENTITY is not limited to a specific scope.
Therefore RETURN SCOPE_IDENTITY() is the best one.
I had this problem and I must admit it was a dumb mistake, but I thought it may happen to someone else. I was using the Execute command that returns the number of rows affected instead of a Query command.
By the way, I was combining my Insert and SELECT SCOPE_IDENTITY() together in one command, which is why I started with the Execute command. I was still able to combine them, but I used ExecuteScalar instead.
Late to the thread, but if someone is using Dapper ORM and they are doing an UPDATE or INSERT a single row and want to know the primary key of that updated record:
var connection = new SqlConnection("ConnectionString");
string sql=#"INSERT INTO [dbo].[Student] ([Name],[Subject])
VALUES (#Name,#Subject)
SET #StudentId=CAST(SCOPE_IDENTITY() as int)";
For the above SQL string, if you execute the SQL connection like:
Result=connection.Execute(sql,new {Name,Subject});
The value of Result will be the number of rows affected, in this case only one since we have inserted only one row.
Instead do this:
Result=connection.Query<int>(sql,new {Name,Subject}).Single();
Now Result will have the primary key value of the newly inserted/updated column.
Remember, this answer is only relevant to single row insertion/update
Related
I have a task that will enter the run-id, table name and row-count into a logging table. I have 6 tables in total, and expecting 15 more tables in the next sprint.
The SQL looks as follows:
INSERT INTO logging_rowcount (RUN_ID, tablename, row_count) values (?, 'hardcoded_name1', ?);
INSERT INTO logging_rowcount (RUN_ID, tablename, row_count) values (?, 'hardcoded_name2', ?);
etc, for a total of 6 INSERT INTO statements.
I mapped the parameters accordingly, using the variable "run-id" for every 2nd parameter. The task itself works, however I fear this becomes little unmaintainable when I have 21 tables (and 42 parameter mappings).
While this particular case can be solved with another loop, generally speaking:
Is there a way to use "speaking" terms for my variables? E.G.
INSERT INTO logging_rowcount (RUN_ID, tablename, row_count) values (#USER:run_id, #USER:tablename, #User:rowCount_table)
You can declare variables in the script task:
DECLARE #RunID INT = ?;
INSERT INTO .... VALUES (#RunID, ?, ...);
INSERT INTO .... VALUES (#RunID, ?, ...);
Now your first parameter will be the RunID and all subsequent ones are the row counts.
You can define a SQL variable in the script for all package variables if you want, so the mapping will be easier to understand (it will be in order in both the mapping and in the script, so easy to match).
You can also have the query as an expression (by having a string variable which stores the query) and in the expression you can use the parameter/variable names, but that will be prone to SQL Injection.
I have a stored procedure where which insert an statement and returns ##Identity.
This ## Identity returns always 1. When removed the ##Idnetity to Identity_Scope it returns the correct expected value, which was always incremented by 1. so this is good. but the question is. Why ## Identity columns is returning 1.
i checked and removed all the trigger and checked all the function but have no idea why i am getting 1 with ##Identity. Seems like there is a table that is being truncated and then a value is being inserted.
Any clue guys why ##Identity is returning 1 all the time. Is there server settings that is doing something?
Please note that:
The ##identity function returns the last identity created in the same
session.
The scope_identity() function returns the last identity
created in the same session and the same scope.
The ident_current(Name) returns the last identity created for a specific
table or view in any session.
So please send us your code for better assistance. You may use ##Identity in a wrong way.
I'm building a small application and I came across an issue that I need to resolve. When I insert a new client into the SQL-SERVER I need to create an ID number to go with the client. I have a value, say - 1000 in a reference table, that gets pulled from the table, incremented by 1, then put back into the ref table, and the value 1001 gets assigned to the client. Before it gets saved to the client, I add 'TOL' to the number - so when save is complete, the ID is TOL1001. The issue I need to resolve is to check the tblClient_TABLE, to make sure that ID TOL1001 doesn't exist already before doing the insert for a new client.
I'm not really sure where I should do it, because on SAVE, I call the function that increments the number, assigns TOL to it and stores the value in an invisible textbox, so when I do my insert, it just pulls the value from the textbox...
strSQL = "INSERT into tblClient_TABLE (ID) values ("txtIDnumber.text")
I obviously have more data to insert, it's just i'm struggling with finding a logic way to check for the already existing ID.
Thanks for any ideas, help!
Your database is able to use identity columns (=autoincrement). So, if you insert a new record, an identity column will get the next value (you can rely on the uniqueness).
How do you get this number? The insert statement has (for mssql) an "output inserted" clause, and if you use ado with executescalar you get your inserted id.
The SQL command (add the vb6 code for ado command you must)
INSERT INTO [TABLENAME] ( [COL1], [COL2] ) OUTPUT INSERTED.MYID VALUES ( #COL1, #COL2 )
... add your Parameter values here ....
result = adoCommand.ExecuteScalar()
(something like that, donĀ“t have VB6 at the office ...)
Anyone knows how to retrieve a new AutoInc that gets written after an ODBC INSERT?
Is there a variable I have access to just like SQL Server?
Right now, I'm using :
SELECT MAX(myautoincfield) AS mylastkey FROM anytable
in order to retrieve my new key.
The scalar function LastAutoinc can retrieve it efficiently:
select LastAutoinc(statement) as mylastkey from system.iota;
The global variable ##identity identifies the last value inserted into an IDENTITY column by the current session.
You may do the following:
select ##identity
in order to retrieve the new key.
I am using a dataset to insert data being converted from an older database. The requirement is to maintain the current Order_ID numbers.
I've tried using:
SET IDENTITY_INSERT orders ON;
This works when I'm in SqlServer Management Studio, I am able to successfully
INSERT INTO orders (order_Id, ...) VALUES ( 1, ...);
However, it does not allow me to do it via the dataset insert that I'm using in my conversion script. Which looks basically like this:
dsOrders.Insert(oldorderId, ...);
I've run the SQL (SET IDENTITY_INSERT orders ON) during the process too. I know that I can only do this against one table at a time and I am.
I keep getting this exception:
Exception when attempting to insert a value into the orders table
System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'orders' when IDENTITY_INSERT is set to OFF.
Any ideas?
Update
AlexS & AlexKuznetsov have mentioned that Set Identity_Insert is a connection level setting, however, when I look at the SQL in SqlProfiler, I notice several commands.
First - SET IDENTITY_INSERT DEAL ON
Second - exec sp_reset_connection
Third to n - my various sql commands including select & insert's
There is always an exec sp_reset_connection between the commands though, I believe that this is responsible for the loss of value on the Identity_Insert setting.
Is there a way to stop my dataset from doing the connection reset?
You have the options mixed up:
SET IDENTITY_INSERT orders ON
will turn ON the ability to insert specific values (that you specify) into a table with an IDENTITY column.
SET IDENTITY_INSERT orders OFF
Turns that behavior OFF again and the normal behavior (you can't specify values for IDENTITY columns since they are auto-generated) is reinstated.
Marc
You want to do SET IDENTITY_INSERT ON to allow you to insert into identity columns.
It seems a bit backwards, but that's the way it works.
It seems that you're doing everything right: SET IDENTITY_INSERT orders ON is the right way on SQL Server's side. But the problem is that you're using datasets. From the code you've provided I can say that you're using typed dataset - the one that was generated in Visual Studio based on the database.
If this is the case (most likely) then this dataset contains a constraint that does not allows you to set values for orderId field, i.e. it's the code that does not allow specifying explicit value, not SQL Server. You should go to dataset designer and edit properties of orderId field: set AutoIncrement and ReadOnly to false. But the same changes can be performed in run time. This will allow you to add a row with explicit value for orderId to a dataset and later save it to SQL Server table (you will still need SET IDENTITY_INSERT).
Also note that IDENTITY_INSERT is a connection-level setting so you need to be sure that you're executing corresponding SET exactly for the same connection that you will be using to save your changes to the database.
I would use Profiler to determine whether your SET IDENTITY_INSERT orders ON;
is issued from the same connection as your subsequent inserts, as well as the exact SQL being executed during inserts.
AlexS was correct, the problem was the Insert_Identity worked, but it is a connection level setting, so I needed to set the Insert_Identity within a transaction.
I used Ryan Whitaker's TableAdapterHelper code
and I created an update command on my tableadapter that ran the Identity_Insert. I then had to create a new Insert command with the Identity column specified. I then ran this code
SqlTransaction transaction = null;
try
{
using (myTableAdapter myAdapter = new myTableAdapter())
{
transaction = TableAdapterHelper.BeginTransaction(myAdapter);
myAdapter.SetIdentityInsert();
myAdapter.Insert(myPK,myColumn1,myColumn2,...);
}
transaction.Commit();
}
catch(Exception ex)
{
transaction.Rollback();
}
finally
{
transaction.Dispose();
}
In case that you still have problems with "insert_identity" , you can try to use a complete insert statement like:
insert into User(Id, Name) values (1,'jeff')