Mysql autoincrement column that resets every month

By | July 26, 2020

The autoincrement feature in mysql allows us to create numeric fields that automatically increment by 1 for every row inserted. It does it atomically so we don't have to worry about any duplicates or collision.

However, there are situations when we need an autoincrement field to reset at regular intervals like every month or so.

For example if you are generating batch numbers, call numbers or invoice numbers that you want to track month-wise, then you need numeric ids that reset every month.

Take for example invoice Numbers:

Month of october

2011-10-01
2011-10-02
...
...
2011-10-800

Month of november

2011-11-01
2011-11-02
...
...

The autoincrement numbers are basically grouped for each month separately.

Example of Group-wise autoincrement:
P1 , P2 , Q1 , Q2 , Q3 , Q4 , P3 , R1 , P4 ...

Resetting autoincrement in mysql

There is no standard feature or specification in database systems to implement such a column that resets on certain conditions. However there is a way to create such an autoincrement field in mysql.

The trick is to use a Myisam table with a composite primary key made of a text column and an autoincrement numeric column.

The MyIsam storage engine has a feature where , if a primary key contains 2 columns where one is an autoincrement and other is a varchar , then for each value of the text column the autoincrement column will create separate sequence of autoincrement numbers.

Table Structure

CREATE TABLE IF NOT EXISTS `vt_sequences` (
  `type` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
  `created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`type`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

In the above table type and id columns form a composite primary key.

Now if we insert different values in the type column repeatedly, then the id column shall have autoincrement values that are grouped by each unique value of the type column.

INSERT INTO `vt_sequences` (`type`) VALUES
('A'),
('A'),
('B'),
('B'),
('A');

The resulting values for the type and id columns should be:

A 1 
A 2 
B 1 
B 2 
A 3

So the id column has a 1 for A and B separately. So now if we want autoincrement numbers resetting every month we could insert 2011-10 and 2011-11 in the type field and the autoincrement numbers would be independant.

Another very useful thing about this technique is that if a particular entry is deleted , say A 3 is deleted , then next time when A is insert 3 would be reused , so autoincrement numbers get reused.

Helper Functions

We can write some easy to use helper functions to manage multiple groups of autoincrements very easily. The first function will help us to get the next autoincrement for a particular group.

/*
	Get a sequence id
*/
function get_sequence( $type )
{
	//Database class object
        static $db = false;
	
	if($db == false)
	{
		$db = load_class('Database');
	}
		
	if(! $db->query("INSERT INTO vt_sequences(type , id ) VALUES( '$type' , NULL )") )
	{
		die( 'Sequence Generation failed' );
	}
	
	return $db->get_last_insert_id();
}

The function get_last_insert_id is nothing but output of "SELECT LAST_INSERT_ID();" query.

The next function will delete a particular id value for a group.

/**
	Delete a sequence id
*/
function del_sequence($type , $id)
{
	static $db = false;
	
	if($db == false)
	{
		$db = load_class('Database');
	}
	
	$db->query( "DELETE FROM vt_sequences WHERE type = '$type' AND id = '$id'" );
        return true;
}

A particular id should always be deleted , if not used , so that it is reused in the next call to get_sequence.

Now lets see how the functions perform :

get_sequence('2011-10'); //1
get_sequence('2011-10'); //2
get_sequence('2011-10'); //3
get_sequence('2011-10'); //4

get_sequence('2011-11'); //1
get_sequence('2011-11'); //2
get_sequence('2011-11'); //3

get_sequence('2011-10'); //5

//Delete a sequence
del_sequence('2011-10' , 5);

//Get it back
get_sequence('2011-10'); //5 - reused again !!

The get_sequence method inserts the type and NULL for the id , and this generates the next autoincrement number.
$db->get_last_insert_id(); could be your implementation of the sql query LAST_INSERT_ID().

Conclusion

There are other ways to implement autoincrement columns that reset every month. The above shown method actually relies on a database feature that is specific to mysql only and may not be available in other database systems like Oracle or Postgresql. This could pose a portability issue.

Another way to implement similar field is by using table locking. You could have a separate table that is used to generate and store autoincrement ids only. Simply lock the table, check the highest id number for the current month and then add 1 to it and write a new row as well as use the number in application.

With this approach there is no dependency on the Myisam feature that was used above.

If you have any questions or feedback, let us know in the comments below.

References :

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

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

One thought on “Mysql autoincrement column that resets every month

Leave a Reply

Your email address will not be published. Required fields are marked *