Search code examples
mysqlsqldatabase-designrelational-databaseinnodb

MySQL second auto increment field based on foreign key


I've come across this problem numerous times but haven't found a "MySQL way" to solve the issue as such - I have a database that contains users and reports. Each report has an id which I display as a report number to my users.

The main complaint is that users are confused as to why reports have gone missing from their system. This is not actually the case. It is actually that they are recognizing a gap between their IDs and assume that these are missing reports, when in actual fact, it is simply becasue another user has filled in this auto-incrementing gap.

I need to know if there is a way to do this in MySQL:

Is it possible that I can have a second auto-increment field called report_number which is based on a user_id field which has a different set of auto-increments per user?

e.g.

|------|---------|---------------|
|  id  | user_id | report_number |
|------|---------|---------------|
|  1   |    1    |       1       |
|  2   |    1    |       2       |
|  3   |    1    |       3       |
|  4   |    2    |       1       |
|  5   |    1    |       4       |
|  6   |    1    |       5       |
|  7   |    2    |       2       |
|  8   |    3    |       1       |
|  9   |    3    |       2       |
|------|---------|---------------|

I am using InnoDB for this as it is quite heavily weighted with foreign-keys. It appears to complain when I add a second auto increment field, but I wasn't sure if there was a different way to do this?


Solution

  • MyISAM supports the second column with auto increment, but InnoDB doesn't.

    For InnoDB you might create a trigger BEFORE INSERT to get the max value of the reportid and add one to the value.

    DELIMITER $$
    CREATE TRIGGER report_trigger
    BEFORE INSERT ON reports
    FOR EACH ROW BEGIN
        SET NEW.`report_id` = (SELECT MAX(report_id) + 1 FROM reports WHERE user_id = NEW.user_id);
    END $$
    DELIMITER ;
    

    If you can use MyISAM instead, in the documentation of MySQL page there is an example:

    http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

    CREATE TABLE animals (
        grp ENUM('fish','mammal','bird') NOT NULL,
        id MEDIUMINT NOT NULL AUTO_INCREMENT,
        name CHAR(30) NOT NULL,
        PRIMARY KEY (grp,id)
    ) ENGINE=MyISAM;
    
    INSERT INTO animals (grp,name) VALUES
        ('mammal','dog'),('mammal','cat'),
        ('bird','penguin'),('fish','lax'),('mammal','whale'),
        ('bird','ostrich');
    
    SELECT * FROM animals ORDER BY grp,id;
    

    Which returns:

    +--------+----+---------+
    | grp    | id | name    |
    +--------+----+---------+
    | fish   |  1 | lax     |
    | mammal |  1 | dog     |
    | mammal |  2 | cat     |
    | mammal |  3 | whale   |
    | bird   |  1 | penguin |
    | bird   |  2 | ostrich |
    +--------+----+---------+