views:

349

answers:

10

What is the best, DBMS-independent way of generating an ID number that will be used immediately in an INSERT statement, keeping the IDs roughly in sequence?

A: 

Use an auto-incrementing id column.

Matt
I think that by "DBMS-independent" he means that autoincrement columns are out of the question. The syntax for generating such a column is AFAIK not the same for all common databases.
Adrian Grigore
Which is DMBS-dependent.
Milen A. Radev
Lots of popular DBMS don't have an auto-increment column type of any kind.
Paul Tomblin
+10  A: 

DBMS independent? That's a problem. The two most common methods are auto incrementing columns, and sequences, and most DBMSes do one or the other but not both. So the database independent way is to have another table with one column with one value that you lock, select, update, and unlock.

Usually I say "to hell with DBMS independence" and do it with sequences in PostgreSQL, or autoincrement columns in MySQL. For my purposes, supporting both is better than trying to find out one way that works everywhere.

Paul Tomblin
This is really, really painful. I don't have a better DBMS independant solution, but I've seen this in use in some places and this sort of design just won't scale nicely (or at least I've not seen it work well).
Andrew Flanagan
I like my SQL scripts to be as portable as possible. I guess I was looking for a level of standardisation that simply does not exist.
Liam
+1  A: 

There is auto increment or sequence

What is the point of this, that is the least of your worries?

How will you handle SQL itself? MySQL has Limit,

SQL Server has Top,

Oracle has Rank

Then there are a million other things like triggers, alter table syntax etc etc

SQLMenace
+5  A: 

If you can create a Globally Unique Identifier (GUID) in your chosen programming language - consider that as your id.

They are harder to work with when troubleshooting (it is much easier to type in a where condition that is an INT) but there are also some advantages. By assigning the GUID as your key locally, you can easily build parent-child record relationships without first having to save the parent to the database and retrieve the id. And since the GUID, by definition, is unique, you don't have to worry about incrementing your key on the server.

Doug L.
A: 

Is there really a reason that they have to be in sequence? If you're just using it as an ID, then you should just be able to use part of a UUID or the first couple digits of md5(now()).

ryeguy
A: 

You could take the time and massage it. It'd be the equivalent of something like

DateTime.Now.Ticks

So it be something like YYYYMMDDHHMMSSSS

MunkiPhD
Be sure to include some type of machine id also for the rare event when two users insert a record at exactly the same time. Improbable, but still possible. And bulk inserts could be a problem if the clock resolution isn't fast enough. Many records could have the same tick.
Doug L.
@ Doug L. - Correct, it really depends on what kind of transactions you're doing and how likely a collision is to occur. This pretty much boils over into the GUID vs INT discussion, which is a heated debate.
MunkiPhD
+1  A: 

Yep, the obvious ways in raw SQL (and in my order of preference) are a) sequences b) auto-increment fields. The better, more modern, more DBMS-independent way is to not touch SQL at all, but to use a (good) ORM.

Lee B
+1  A: 

There's no universal way to do this. If there were, everyone would use it. SQL by definition abhors the idea - it's an antipattern for set-based logic (although a useful one, in many real-world cases).

The biggest problem you'd have trying to interpose an identity value from elsewhere is when a SQL statement involves several records, and several values must be generated simultaneously.

If you need it, then make it part of your selection requirements for a database to use with your application. Any serious DBMS product will provide its own mechanism to use, and it's easy enough to code around the differences in DML. The variations are pretty much all in the DDL.

le dorfier
A: 

I'd always go for the DB specific solution, but if you really have to the usual way of doing this is to implement your own sequence. Your RDBMS has to support transactions.

You create a sequence table which contains an int column and seed this with the first number, your transaction logic then looks something like this

begin transaction
update tblSeq set intID = intID + 1
select @myID = intID from tblSeq

inset into tblData (intID, ...) values (@myID, ...)
end transaction

The transaction forces a write lock such that the then next queued insert cannot update the tblSeq value before the record has been inserted into tblData. So long as all inserts go though this transaction then your generated ID is in sequence.

Cruachan
A: 

It may be of a bit lateral approach, but a good ORM-type library will probably be able to at least hide the differences. For example, in Ruby there is ActiveRecord (commonly used in but not exclusively tied to the Ruby the Rails web framework) which has Migrations. Within a table definition, which is declared in platform-agnostic code, implementation details such as datatypes, sequential id generation and index creation are pushed down below your vision.

I have transparently developed a schema on SQLite, then implemented it on MS SQL Server and later ported to Oracle. Without ever changing the code that generates my schema definition.

As I say, it may not be what you're looking for, but the easiest way to encapsulate what varies is to use a library that has already done the encapsulation for you.

Mike Woodhouse