Is IDENTITY_INSERT session-specific? Say there is an application using table "Test" and is entering some data in it. If i set IDENTITY_INSERT on and insert a row manually, will the application be able to keep on entering rows if it DOES NOT specify any PK?
Yes, Identity_insert is session specific. The next insert done by an application will use the most recent value as the starting point to calculate the next PK value.
See more at MSDN: https://msdn.microsoft.com/en-us/library/ms188059.aspx#Anchor_2
I think you confuse what IDENTITY_INSERT on means - you must manually specify a value. You must always specify a value for PK.
Related
To insert values into the identity column manually, I use:
SET identity_insert product ON
INSERT INTO product (PID, ProdName, Qty, Unitprice)
VALUES (10, 'soap', 5400, 22)
Firstly I have deleted the 10th row/record, then I have used this command to insert the identity value and record it manually.
this command is inserting the record. It's fine
Where should I write the command SET identity_insert product OFF? And what is the use of the SET identity_insert product OFF command?
From the documentation:
At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.
So, if you are in a batch where you want to override the auto-generated identity values on two different tables, you would set the first one to OFF before setting the second one to ON.
(Also, like a lot of things, if you change something from the default, it's never a bad idea to change it back.)
from https://learn.microsoft.com/en-us/sql/t-sql/statements/set-identity-insert-transact-sql?view=sql-server-ver15
At any time, only one table in a session can have the IDENTITY_INSERT
property set to ON. If a table already has this property set to ON,
and a SET IDENTITY_INSERT ON statement is issued for another table,
SQL Server returns an error message that states SET IDENTITY_INSERT is
already ON and reports the table it is set ON for.
so you should set it off before you set it on to another table in your session.
I have a table filled with data and one of the columns - TrackingNumber - is an integer value. I have gotten a request to change it to auto-increment and to have it start the identity seed at 1000000. I know that I cannot alter a column to be an identity column in an existing table with data, so I have two options: either create an entirely new table and then move data from the old table into that new table or add an new identity column and update it with data from the old column.
The problem is that I need to retain all the existing values in column TrackingNumber. I have tried the following:
1) ALTER TABLE [dbo].[Table1]
ADD [TrackingNumber2] [bigint] IDENTITY (1000000, 1) NOT NULL
2) UPDATE [dbo].[Table1]
SET [TrackingNumber2]=[TrackingNumber]
3) ALTER TABLE [dbo].[Table1]
DROP COLUMN [TrackingNumber]
GO
4) EXEC sp_rename 'Table1.TrackingNumber2', 'TrackingNumber','COLUMN'
I got an error on step 2 - Updating new column with the value from the old column: "Cannot update identity column 'TrackingNumber2'"
Can anyone recommend a workaround?
You just need to set identity_insert on for this table so you can update the values. Make sure you turn it back off when you complete the update. :)
https://msdn.microsoft.com/en-us/library/ms188059.aspx
Are you sure you need to use an identity column? There are alternatives. For example, since SQL Server 2012 (and azure, too), there are these things called sequences. You can define a sequence to start at any number you like:
create sequence dbo.TrackingSequence
as int
start with 1000000
increment by 1
no maxvalue
no cycle
no cache
Then, you can alter the table such that the default value for the column in question defaults from the sequence:
alter table dbo.MyTable
add constraint [MyTable.TrackingNumber.Default.TrackingSequence]
default( next value for dbo.TrackingSequence ) for TrackingNumber
(If the column already has a default value, you need to remove that first - in a separate statement.)
A sequence works a lot like an identity, but you don't have to disrupt existing values or the column definition per se.
The only trick is to remember to not specify the value for TrackingNumber, and let the DB do its thing.
Sequences are cool in that you can have one sequence that is used by multiple tables, giving you somewhat shorter db-wide unique IDs than alternatives in the past. For such an application, you'd probably be better off with a bigint column - or know that the tables in question aren't going to be terribly long.
I ended up creating a new table and moving data in there
I have an insert statement in a stored procedure who's primary key is a serial id. I want to be able to populate an additional field in the same table during the same insert statement with the serial id used for the primary key. Is this possible?
Unfortunately this is a solution already in place... I just have to implement it.
Regards
I can't imagine a reason why you would want a copy of the key in another column. But in order to do it, I think you'll need to follow your update with a statement to get the value of the identity key, and then an update to put that value in the other column. Since you're already in a stored procedure, it's probably ok to have a few extra statements, instead of doing it in the very same one.
DECLARE #ID INT;
INSERT INTO TABLE_THINGY (Name, Address) VALUES ('Joe Blow', '123 Main St');
SET #ID = SCOPE_IDENTITY();
UPDATE TABLE_THINGY SET IdCopy = #Id WHERE ID = #ID
If it's important that this be done every single time, you might want to create a Trigger to do it; beware, however, that many people hate triggers because of the obfuscation and difficulty in debugging, among other reasons.
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
I agree, it is odd that you would replicate the key within the same table but with that said you could use a trigger, thus making it have no impact to current insert statements.
The below trigger is "After Insert" so technically it happens milliseconds after the insert if you truly wanted it to happen at the same time you would use a FOR INSERT instead and just replicate the logic used to create the serial id field into the new field.
CREATE TRIGGER triggerName ON dbo.tableName
AFTER INSERT
AS
BEGIN
update dbo.tableName set newField = inserted.SerialId where serialId = inserted.SerialId
END
GO
You could have a computed column that just returns the id column.
CREATE TABLE dbo.Products
(
ProductID int IDENTITY (1,1) NOT NULL
, OtherProductID AS ProductID
);
Having said that, data should only live in one place and to duplicate it in the same table is just a wrong design.
No, you cannot use the same insert statement for identity Id and copy that auto generated Id to the same row.
Multi-Statement using OUTPUT inserted or Trigger is your best bet.
Here's what I'm trying to do:
SELECT * INTO new_table FROM old_table WHERE 1=2;
ALTER TABLE new_table ADD CONSTRAINT pk_new_table_id PRIMARY KEY(id);
SET IDENTITY_INSERT new_table ON
Basically, I want to create a new table based on the structure of an existing one, then turn on autoincrementing for the ID field. However, when I try to insert rows I get this:
Table 'new_table ' does not have the identity property. Cannot perform SET operation.
Can anyone enlighten me as to what I'm doing wrong or how I should actually be going about this?
The table you create doesn't have an identity column. If you inspect the code you posted, you will notice that nowhere is an identity declared. I think you are confusing the concept of PRIMARY KEY and IDENTITY. They are distinct and unrelated. You cannot create a table with identity column using SELECT ... INTO ...
the column needs to be specified with " identity(1,1)" option. First 1 is the starting point and second is the increment.
set identity_insert on does not actually do what you think it does. It disables autoincrement (temporarily) so that you can hard code values in there.
Here's more info on that... http://msdn.microsoft.com/en-us/library/aa259221(v=sql.80).aspx
First, you have to create the new table without the use of "select ... into" and specify the column as an identity column.
Use the "set identity_insert .. on" before you copy the data over. Then, "set identity_insert ... off" when you're done.
If you want to cheat on the first part, you can use the management studio. Right click original table... goto the designer. Add identity option for the desired column. Then save off the script but do not commit. Might want to manipulate the newly generate script to create the new table. There are other more sophisticated solutions if you're going to have to do this repeatedly. But this by far is the simplest.
Here could be the problem:
ALTER TABLE new_table ADD CONSTRAINT pk_new_table_id PRIMARY KEY(id, idColumn);
Specify the id column.
Is there a way to reserve or skip or increment value of identity column?
I Have two tables joined in one-to-one relation ship. First one has IDENTITY PK column, and second one int PK (not IDENTITY). I used to insert in first, get ID and insert in second. And it works ok.
Now I need to insert values in second table without inserting into first.
Now, how to increment IDENTITY seed, so I can insert it into second table, but leave "hole" in ID's of first table?
EDIT: More info
This works:
-- I need new seed number, but not table row
-- so i will insert foo row, get id, and delete it
INSERT INTO TABLE1 (SomeRequiredField) VALUES ('foo');
SET #NewID = SCOPE_IDENTITY();
DELETE FROM TABLE1 WHERE ID=#NewID;
-- Then I can insert in TABLE2
INSERT INTO (ID, Field, Field) VALUES (#NewID, 'Value', 'Value');
Once again - this works.
Question is can I get ID without inserting into table?
DBCC needs owner rights; is there a clean user callable SQL to do that?
This situation will make your overall data structure very hard to understand. If there is not a relationship between the values, then break the relationship.
There are ways to get around this to do what you are looking for, but typically it is in a distributed environment and not done because of what appears to be a data model change.
Then its no more a one-to-one relationship.
Just break the PK constraint.
Use a DBCC CHECKIDENT statement.
This article from SQL Server Books Online discusses the use of the DBCC CHECKIDENT method to update the identity seed of a table.
From that article:
This example forces the current identity value in the jobs table to a value of 30.
USE pubs
GO
DBCC CHECKIDENT (jobs, RESEED, 30)
GO
I would look into the OUTPUT INTO feature if you are using SQL Server 2005 or greater. This would allow you to insert into your primary table, and take the IDs assigned at that time to create rows in the secondary table.
I am assuming that there is a foreign key constraint enforced - because that would be the only reason you would need to do this in the first place.
How do you plan on matching them up later? I would not put records into the second table without a record in the first, that is why it is set up in a foreign key relationship - to stio that sort of action. Just why do you not want to insert records into the first table anyway? If we knew more about the type of application and why this is necessary we might be able to guide you to a solution.
this might help
SET IDENTITY_INSERT [ database_name . [ schema_name ] . ] table { ON | OFF }
http://msdn.microsoft.com/en-us/library/aa259221(SQL.80).aspx
It allows explicit values to be inserted into the identity column of a table.