sql server 2005:is it safe to use ##identity? - sql-server

i have a procedure in which i am inserting record in employee table.nad getting empid by using ##identity ? when this procedure will be called by more than one user at same time,there can be possibility that it returns identity of some other employee inserted at same time.because there is no lock on identity by system?
--code
--identity on for empid column
insert into employee (name) values ('sahil');
return ##identity
refer sql server 2005:is it safe to use ##identity?
for lock on identity issue

You should be using SCOPE_IDENTITY() instead. However, ##IDENTITY refers to the current connection so other users won't affect you but there are other issues to consider.
More information here.

##identity is not safe to use. If the table has a trigger with an insert to a differnt table with an identity that is the value that will be returned. Never use it to get the idnetity value you just inserted. You may think well I don't have a trigger now, but you never know when one might be added and you can go a long time before realizing that your data is hopelessly messed up.

Related

Issue ##IDENTITY AND IDENT_CURRENT(tableName) SQL SERVER

After INSERT record to the table with an identity column
I try to get identified by the way SELECT ##IDENTITY but it returns NULL,
but I try to use ;
SELECT IDENT_CURRENT ('tableName')
this statement return I'm expected value
You shouldn't use ##Identity, nor should you use ident_current().
The first answers a question that you probably don't want to ask, and the second is unreliable, according to SQL Server expert Aaron Bertrand (or, at least, that was the case back in January 2014, when this article was published).
You should be using the output clause if you're inserting more than one record, or scope_identity() if you're only inserting one.
Note that the output clause doesn't play nice with triggers, and scope_identity() will have problems if your target table have an instead of insert trigger.
For more information, you can read Use the right tool to get identity values back after an insert over on my blog.
IDENT_CURRENT() returns the last inserted identity value for a given table.
SCOPE_IDENTITY() returns the last identity value inserted into an identity column in any table in the current session and current scope.
Probably you execute SCOPE_IDENTITY() in the other session

Inserting a identity column value into another table

Good Morning. I have two tables, and one references the other. When I insert into the primary table, the primary key is auto-generated, viz Identity field. I need to insert this value into the second table.
I found out using the OUTPUT clause will give me the just inserted identity value, ans so I tried this.
insert into owners (pId)
insert into personal (firstName)
output inserted.pId
values ('fn')
It doesn't work though. I get an error:
Incorrect syntax near the keyword 'insert'
The personal table is the primary table, and the owners table contains the foreign key.
How can I do the required in SQL Server?
I've got stuck-up here for the past two days...
I think you just have your syntax slightly off - you can definitely take values inserted into the main table and use the OUTPUT clause to insert those into a secondary table.
INSERT INTO dbo.personal(firstName)
OUTPUT INSERTED.pId INTO dbo.owners(pId)
VALUES('fn')
This will insert a new row into personal and set the column firstName to fn. From that insert, the inserted row's identity column pId is then inserted into the other table, owners, as that table's pId column.
See the MSDN documentation on the OUTPUT clause for more details - you can either output any of the inserted values to the console (e.g. SQL Server Mgmt Studio), or you can output those values into a temporary or a permanent table.
Update: as 'dradu' has pointed out - this approach won't work in your case here, since the column in the owners table is part of a FK constraint (I had missed that point from your question). So you'll need to use some other way to do this - probably outputting the necessary information into a temporary table / table variable in your code
Try the following steps
1) Apply transaction level on insertion
2) Get last inserted id using Scope_Identity() function.
When you apply transaction level it will lock your tables and other/same user cannot insert the value in this time.
try this it will work for you.
Since OUTPUT clause cannot be used directly because of the foreign key, you could add the generated IDs into a temporary table, then insert those values into the owners table:
BEGIN TRANSACTION
CREATE TABLE #ids(ID INT)
INSERT INTO personal(firstName)
OUTPUT inserted.pid INTO #ids
SELECT 'A'
UNION SELECT 'B'
INSERT INTO owners(pid)
SELECT ID FROM #ids
COMMIT TRANSACTION
SCOPE_IDENTITY will work too, but it's limited to one value.
You can use the SCOPE_IDENTITY() function to return the identity value inserted.
DECLARE #id INT
INSERT INTO [Personal] (Colums ....) VALUES (this, that, stuff)
SET #id = SCOPE_IDENTITY()
INSERT INTO [Owners] (Colums ....) VALUES (#id ....)
I think Your option is to use SCOPE_IDENTITY() but the other closest to your option is IDENT_CURRENT(‘tablename’) so I thought, I post detail of detail of other identity options as well which might help you to understand your choice and might helpful some other time
##IDENTITY
It returns the last IDENTITY value produced on a connection, regardless of the table that produced the value, and regardless of the
scope of the statement that produced the value.
SCOPE_IDENTITY() It returns the last IDENTITY value produced on
a connection and by a statement in the same scope, regardless of the
table that produced the value.
IDENT_CURRENT(‘tablename’) 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.
Here is one simple example of using SCOPE_IDENTITY() to get recent Identity Value
http://msdn.microsoft.com/en-us/library/ms190315.aspx

Actual inserted row ID

I have created table in my db in this statement
CREATE TABLE tPerson
(
id INT NOT NULL PRIMARY KEY identity(1,1)
, name NVARCHAR(100) not null
, email NVARCHAR(30) not null
)
GO
Now I insert new value with INSERT. My question is how can I get id of current added row? Any idea ??
Assuming SQL server, you should check out this article to gain a good understanding of retrieving identities.
Here's a snippet:
SELECT ##IDENTITY
It returns the last IDENTITY value produced on a
connection, regardless of the table that produced the value, and
regardless of the scope of the statement that produced the value.
##IDENTITY will return the last identity value entered into a table in
your current session. While ##IDENTITY is limited to the current
session, it is not limited to the current scope. If you have a trigger
on a table that causes an identity to be created in another table, you
will get the identity that was created last, even if it was the
trigger that created it.
SELECT SCOPE_IDENTITY()
It returns the last IDENTITY value produced on
a connection and by a statement in the same scope, regardless of the
table that produced the value. SCOPE_IDENTITY(), like ##IDENTITY, will
return the last identity value created in the current session, but it
will also limit it to your current scope as well. In other words, it
will return the last identity value that you explicitly created,
rather than any identity that was created by a trigger or a user
defined function.
SELECT IDENT_CURRENT(‘tablename’)
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.
It looks like SQL Server, and it that case, just use:
INSERT INTO dbo.tPerson(....) VALUES(.....)
DECLARE #NewID INT
SELECT #NewID = SCOPE_IDENTITY()
SCOPE_IDENTITY returns the last inserted IDENTITY value in this current scope.
Side note: "email" is only 30 characters long!?!? I typically make that the longest column in my table - 200 chars or even more :-)
Use ##IDENTITY or SCOPE_IDENTITY for MS SQL Server :)
Try
SELECT ##IDENTITY AS LastID
after your INSERT
You can also do this through JDBC directly to avoid the need to select, as typically an insert statement will return the number of rows inserted which you may want to validate. Spring supports this through its JdbcTemplate, see here

Help needed with "Cannot insert explicit value for identity column" Error

I have a table Table1 on which I have created an insert/update trigger. This trigger insert records of inserts/updates on Table1 into Table1_history. To test whether the trigger is inserting records into Table1_history, I have inserted some test data into Table1 and I am receiving the error:
Cannot insert explicit value for identity column in table 'Table1_history' when IDENTITY_INSERT is set to OFF
Schema of Table1 and Table1_history are identical except an additional 'inserted_on_date' field in Table1_history.
I have set the Identity Insert to ON and the trigger works. But do I have to do this every time I need to insert a new record in Table1?
Put the IDENTITY INSERT ON into the trigger itself, it only needs to be active while you are pushing values into table1_history, because that is where the problem is.
Or, in Table1_history, don't make the pk field an IDENTITY, it does not need to be because you are supplying the values from Table1.
I assume your 'inserted_on_date' field is a datetime. You should be able to turn off the identity insert and set the default value for this column to GETDATE(), which will set any newly inserted records to the datetime the server has when the record is inserted.
You don't mention what database but I assume it's SQL Server 2008.
The set identity on command is session specific. So yes, you need to issue it each time.
Instead, you should remove the identity specification from the history table. You don't need it.

SQL server trigger question

I am by no means a sql programmer and I am trying to accomplish something that I am pretty sure has been done a million times before.
I am trying to auto generate a customer number in sql every time a new customer is inserted, but the trigger (or sp?) will only work if at least the first name, last name and another value called case number is entered. If any of these fields are missing, the system generates an error. If the criteria is met, the system generates and assigns a unique id to that customer that begins with letters GL- and then uses 5 digit number so a customer John Doe would be GL-00001 and Jane Doe would be GL-00002.
I am sorry if I am asking too much but I am basically a select insert update guy and nothing more so thanks in advance for any help.
If I were in this situation, I would:
--Alter the table(s) so that first name, last name and case number are required (NOT NULL) columns. Handle your checks for required fields on the application side before submitting the record to the database.
--If it doesn't already exist, add an identity column to the customer table.
--Add a persisted computed column to the customer table that will format the identity column into the desired GL-00000 format.
/* Demo computed column for customer number */
create table #test (
id int identity,
customer_number as 'GL-' + left('00000', 5-len(cast(id as varchar(5)))) + cast(id as varchar(5)) persisted,
name char(20)
)
insert into #test (name) values ('Joe')
insert into #test (name) values ('BobbyS')
select * from #test
drop table #test
This should satisfy your requirements without the need to introduce the overhead of a trigger.
So what do you want to do? generate a customer number even when these fields arn't populated?
Have you looked at the SQL for the trigger? You can do this in SSMS (SQL Server Managment Studio) by going to the table in question in the Object Explorer, expanding the table and then expanding triggers.
If you open up the trigger you'll see what it does to generate the customer number. If you are unsure on how this code works, then post the code for the trigger up.
If you are making changes to an existing system i'd advise you to find out any implications that changing the way data is inputted works.
For example, others parts of the application may depend on all of the initial values being populated, so after changing the trigger to allow incomplete data to be added, you may inturn break something else.
You have probably a unique constraint and/or NOT NULL constraints set on the table.
Remove/Disable these (for example with the SQL-Server Management Console in Design Mode) and then try again to insert the data. Keep in mind, that you will probably not be able to enable the constraints after your insert, since you are violating conditions after the insert. Only disable or reomve the constraints, if you are absolutely sure that they are unecessary.
Here's example syntax (you need to know the constraint names):
--disable
ALTER TABLE customer NOCHECK CONSTRAINT your_constraint_name
--enable
ALTER TABLE customer CHECK CONSTRAINT your_constraint_name
Caution: If I were you, I'd rather try to insert dummy values for the not null columns like this:
insert into customers select afield , 1 as dummyvalue, 2 as dummyvalue from your datasource
A very easy way to do this would be to create a table of this sort of structure:
CustomerID of type in that is a primary key and set it as identity
CustomerIDPrfix of type varchar(3) which stores GL- as a default value.
Then add your other fields and set them to NOT NULL.
If that way is not acceptable and you do need to write a trigger check out these two articles:
http://msdn.microsoft.com/en-us/library/aa258254(SQL.80).aspx
http://www.kodyaz.com/articles/sql-trigger-example-in-sql-server-2008.aspx
Basiclly it is all about getting the logic right to check if the fields are blank. Experiment with a test database on your local machine. This will help you get it right.

Resources