I wrote the count code below with the aim of having it produce auto-serial numbers for my data in place of the MySQL serial number which goes once the row is deleted. But when I
You need to configure your MySQL table so that the sn
column has AUTO_INCREMENT
enabled. Consider this example from the MySQL 5.0 Reference on AUTO_INCREMENT:
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
SELECT * FROM animals;
Returns:
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
In this example, nothing was passed as id
, but the result was automatically generated.
You should define something link this for the sn
column in your table.
Edit: Assuming you absolutely must feel like you have an additional, offset, incrementing column, one option is to make it appear so when you query the table. In the example above, let's say we want an additional column, sn
, and that the difference between id
and sn
is 7. We could do the following:
SELECT *, (`id` + 7) as `sn` FROM animals;
Returns:
+----+---------+----+
| id | name | sn |
+----+---------+----+
| 1 | dog | 8 |
| 2 | cat | 9 |
| 3 | penguin | 10 |
| 4 | lax | 11 |
| 5 | whale | 12 |
| 6 | ostrich | 13 |
+----+---------+----+
Note that although you can use sn
in JOIN
s and other statements, you won't be able to use it as a foreign key in other tables.
In MySQL each table can have one and only one auto increment field. This is the correct way to generate a unique value like you have asked for each row.
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
The method you have used is error prone. When you test it may work, but when it is used by multiple users it will result in duplicate ids. This is because if user and and user be request at the same time, they will both get the count at the same time, add 1 to it and then insert with the same value. Using an autoincrement field avoids this issue. It is also much faster and easier to use.
[Edit]
User asked if there was no other way to do this. There is of course otherways to do this, this however is the correct one in nearly all cases. Even if you need more than one per table, it is likely the best way to do this in MySQL is to create a second table to get another autoincrement.
That said I will propose two of the many alternatives. The crux of the problem is the need for an atomic counter, that is a counter that does not suffer from the race condition described above, and will always return the next unique id. One such source of an atomic counter is memcache. Memcache provides an atomic increment that could be used as the source for a unique id. Like all solutions this has it's downfalls, if your memcache goes down you will loose your state, and the counter will start over, thus not being so unique.
Another approach is to use MySQL locks. This can either be a table lock where in you lock the table, select the max id increment, insert and unlock the table, this requires the use of transactions as well and so will further complicate what could be very simple code. You can alternatively use MySQLs arbitrary application level locking scheme.
https://dev.mysql.com/doc/refman/5.0/en/internal-locking.html https://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock
The complexity of implementing such an alternative is sufficient, that if you did not already know what I just explained, you should stick with autoincrement fields, they are very easy to use and fairly bullet proof.