views:

2563

answers:

5

In SQL Server 2000 or above is there anyway to handle an auto generated primary key (identity) column when using a statement like the following?

Insert Into TableName Values(?, ?, ?)

My goal is to NOT use the column names at all.

+1  A: 

You have 2 choices:

1) either specify the column name list (without the identity column).

2) SET IDENTITY_INSERT tablename ON, followed by insert statements that provide explicit values for the identity column.

If you are avoiding a column name list, perhaps this 'trick' migh help?:

-- Get a comma separated list of a table's column names
SELECT STUFF(
(SELECT 
',' + COLUMN_NAME AS [text()]
FROM 
INFORMATION_SCHEMA.COLUMNS
WHERE 
TABLE_NAME = 'TableName'
Order By Ordinal_position
FOR XML PATH('')
), 1,1, '')
Mitch Wheat
Just to clarify, by explicit values you mean you have to query the database to see what the next identity in the sequence would be and insert it manually?
James McMahon
No, you can use any value that is not already there, but the next in sequence will start from the greatest plus one....
Mitch Wheat
It tends only to be used when you have something like reference data that is required to have the exact same ID values across different application installations
Mitch Wheat
Do NOT ever use Set identity_insert on in a production environment! Not unless you want other users inserting to the table to have issues. This is only to be used when transferring large amounts of data from one system to another and should only be done in single-user mode.
HLGEM
@HLGEM: I'm not suggesting you leave it turned on! But you are correct that it should ideally be done when there is no activity on that table. We use it mainly on reference data tables, when there is never any insert activity during normal use.
Mitch Wheat
+4  A: 

By default, if you have an identity column, you do not need to specify it in the VALUES section. If your table is:

ID    NAME    ADDRESS

Then you can do:

INSERT INTO MyTbl VALUES ('Joe', '123 State Street, Boston, MA')

This will auto-generate the ID for you, and you don't have to think about it at all. If you SET IDENTITY_INSERT MyTbl OFF, you can assign a value to the ID column and it will pick it up.

Eric
Oh really? That is fantastic. I had just assumed that wouldn't work. Let me give that try.
James McMahon
@Eric is correct that what's I meant in point 1 above (have edited to show my intent), +1
Mitch Wheat
Eric this isn't working for me at all. It is complaining that I have, identity insert off, I assume because it is trying to insert the first item in values into ID. Anything specific you have to set to get it to ignore the first column?
James McMahon
Don't put the ID column in the insert statement if you want SQL Server to autogenerate the ID for you.
Eric
don't set identity insert off when leaving identity column out of the coolumn list, otherwise a value will not be generated for it
Mitch Wheat
@Eric, I didn't specify any columns. I ran INSERT INTO MyTbl VALUES ('TEST1', 'TEST2', 'TEST3', 'TEST4') on a table with 5 columns, the first being an autogenerated ID column. The database is trying to put 'TEST1' into the ID column.
James McMahon
I am testing this out on SQL Server 2005 express, just FYI.
James McMahon
I think my issue is that when I run the query in the SQL server query window it translates it into INSERT INTO (ColumnName, ColumnName ... etc), anyway to avoid this?
James McMahon
This does work, I was just hitting some SQL Server GUI strangeness.
James McMahon
+1  A: 

Since it isn't practical to put code in a comment, in response to your comment in Eric's answer that it's not working for you...

I just ran the following on a SQL 2005 box (sorry, no 2000 handy) with default settings and it worked without error:

CREATE TABLE dbo.Test_Identity_Insert
(
    id INT IDENTITY NOT NULL,
    my_string VARCHAR(20) NOT NULL,
    CONSTRAINT PK_Test_Identity_Insert PRIMARY KEY CLUSTERED (id)
)
GO

INSERT INTO dbo.Test_Identity_Insert VALUES ('test')
GO

SELECT * FROM dbo.Test_Identity_Insert
GO

Are you perhaps sending the ID value over in your values list? I don't think that you can make it ignore the column if you actually pass a value for it. For example, if your table has 6 columns and you want to ignore the IDENTITY column you can only pass 5 values.

Tom H.
Your statement works fine for me as well, very strange.
James McMahon
+2  A: 

Another "trick" for generating the column list is simply to drag the "Columns" node from Object Explorer onto a query window.

Aaron Bertrand
+1  A: 

The best practice is to explicitly list the columns:

Insert Into TableName(col1, col2,col2) Values(?, ?, ?)

Otherwise your original insert will break if you add another column to your table.

AlexKuznetsov
Yeah my boss actually said the same thing. Both of you are completely right, but the data in this database is in-permit (i.e. wiped out and regenerated daily) so if something like this happened it wouldn't be the end of the world.
James McMahon