Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table in DB for generating primary keys?

Do you ever use a separate table for "generating" artificial primary keys for DB (and why)? What I mean is to have a table with two columns, table name and current ID - with which you could get new "ID" for some table by simply locking the row with that table name, getting the current value of the key, increment it by one, and unlock the row. Why would you prefer this over standard integer identity column?

P.S. The "idea" is from Fowlers Patterns of Enterprise Application Architecture, btw...

like image 839
Denis Biondic Avatar asked Mar 12 '10 18:03

Denis Biondic


4 Answers

This is called Hi/Lo assignment.

You would do this having either a trigger on INSERT on your tables getting the ID from this table and incrementing it before or after you get your ID, depending of your choice.

This is commonly used when you have to deal with multiple database engines. The autoincremental identifier in Oracle is through a SEQUENCE, which you increment with SEQUENCE.NEXTVALUE from within a BEFORE INSERT TRIGGER on your data table.

Oppositly, SQL Server has IDENTITY columns, autoincrementing natively and this is managed by the DBE itself.

In order for your software to work on both DBE, you have to come to some sort of a standard, then the most common "standard" used for this is the Hi/Lo assignment to the primary key.

This is one approach amongst others. These days, with ORM Mapping tools such as NHibernate, it is offered through configuration so that you need less to care on both the application and the database sides.

EDIT #1

Because this kind of maneuvre can't be used for a global scope, you'd have to have such a table per database, or database schema. This way, each schema is indenpendant from the other. However, data in one schema can't implicitly be moved toward another with the same key, as it would perhaps be conflicted with an already existing row.

As for a security schema, it accesses the same database as another schema or user, so no additional table should exist for specific security schema.

like image 86
Will Marcouiller Avatar answered Oct 30 '22 22:10

Will Marcouiller


Whenever you can use sql server's identity or guid features, you should. However, there are a few situations where this may not be possible.

One example is that sql server only allows one identity column per table. Rarely, a table will have records that need both a private id and a public id, and a limit of one identity column means generating both as integers can be a pain. You could always use a guid for one, but you want the integer on the private id for speed and you may also want the public id to be more human readable than a guid.

In this situation, an extra table for generating the ids can make sense. However, I'd do it a bit differently. Still have two columns in the table, but make one "shadow" or "Id mapping" table for every real table. One of the columns will be your private id (unique constraint) and one will be your public id (identity with maybe an increment value of '7' or '13' or other number that's less obvious than '1').

The key difference here is that you don't want to do the locking yourself. Let sql server handle it.

like image 30
Joel Coehoorn Avatar answered Oct 30 '22 22:10

Joel Coehoorn


The only time I have ever used this is when I had an application in BTrieve, and it didn't have an identity column. And I should also say when they tried to use this table, it caused a massive slow down when they tried to import data, because of all the extra reads and writes. My friend looked at it and rewrote how they did it to speed it up, but the moral of the story is that if you do something like this incorrectly, there can be brutal consequences.

Personally, I don't think I would ever want to do this. There is too much possibility for error. Two people try and use the same key, because they forgot to lock the table before grabbing the id. This just seems like something that should be left up to the RDBMS if at all possible. As Will brought up, it's easy to minimize this situation, but if you don't know what you are doing it can happen.

like image 38
kemiller2002 Avatar answered Oct 30 '22 22:10

kemiller2002


You wouldn't prefer it at all.

Whatever you gain by using the pattern or becoming DB agnostic, you'll lose in headaches, support and performance.

like image 34
gbn Avatar answered Oct 30 '22 22:10

gbn