sqldatabaseprimary-keyauto-increment

Some sort of “different auto-increment indexes” per a primary key values


I have got a table which has an id (primary key with auto increment), uid (key refering to users id for example) and something else which for my question won’t matter.

I want to make, lets call it, different auto-increment keys on id for each uid entry.

So, I will add an entry with uid 10, and the id field for this entry will have a 1 because there were no previous entries with a value of 10 in uid. I will add a new one with uid 4 and its id will be 3 because I there were already two entried with uid 4.

...Very obvious explanation, but I am trying to be as explainative an clear as I can to demonstrate the idea... clearly.

  1. What SQL engine can provide such a functionality natively? (non Microsoft/Oracle based)
  2. If there is none, how could I best replicate it? Triggers perhaps?
  3. Does this functionality have a more suitable name?
  4. In case you know about a non SQL database engine providing such a functioality, name it anyway, I am curious.

Thanks.


Solution

  • MySQL's MyISAM engine can do this. See their manual, in section Using AUTO_INCREMENT:

    For MyISAM tables you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.

    The docs go on after that paragraph, showing an example.

    The InnoDB engine in MySQL does not support this feature, which is unfortunate because it's better to use InnoDB in almost all cases. I avoid using MyISAM.

    You can't emulate this behavior using triggers (or any SQL statements limited to transaction scope) without locking tables on INSERT. Consider this sequence of actions:

    1. Mario starts transaction and inserts a new row for user 4.
    2. Bill starts transaction and inserts a new row for user 4.
    3. Mario's session fires a trigger to computes MAX(id)+1 for user 4. You get 3.
    4. Bill's session fires a trigger to compute MAX(id). I get 3.
    5. Bill's session finishes his INSERT and commits.
    6. Mario's session tries to finish his INSERT, but the row with (userid=4, id=3) now exists, so Mario gets a primary key conflict.

    In general, you can't control the order of execution of these steps without some kind of synchronization.

    The solutions to this are either:

    It's relatively easy to ensure that inserts get unique values. But it's hard to ensure they will get consecutive ordinal values. Also consider: