I am using mysql/php.
my table looks like
id (int autoincrement)
voucher(varchar 25)
开发者_如何学JAVAI am generating voucher codes where the code is:
- 1 random number (eg 64)
- 1 fixed number (eg 352)
- value of id field (1,2,3,4,5...)
- 1 checkdigit (luhn algorithm).
The obvious issue in doing this with php is that I have to do a select, get the next autoincrement value, calculate the code, insert, by which time another row could have been inserted.
What I want to do is instead,
do insert into vouchers (voucher) value('64352')
and have it generate the rest of me.
How can I do this? function/trigger?
If you are using InnoDB, an easy fix would just be to use your existing code and wrap it in a MySQL transaction. i.e. in pseudocode:
mysql_query("START TRANSACTION");
# get next autoincrement value into: $next
# do your INSERT query
# get the actual last inserted ID into: $actual
if ($next === $actual) {
mysql_query("COMMIT");
} else {
mysql_query("ROLLBACK");
# and raise an Exception or return an error
}
EDIT/ADD:
Since you mentioned triggers, I looked into that and believe it's doable. A couple of issues.
Accessing the "next autoincrement ID" from the trigger ... I don't know a "good" way to do this. In INSERT queries you have access only to NEW and not OLD (existing rows) values (see Trigger syntax). What I'm doing to do in the example is just maintain a separate counter @vcount on the server. To initialize this value to whatever the ID currently is, you would just do "SET @vcount = 42;"
Luhn algorithm. You will have to implement this as a SQL function. Here's a Luhn validator in SQL you could crib from. Alternately you could hash/checksum with a native MySQL function like MD5 (and use only the first X chars if you need a short voucher code). In any case you need to make a hash function ... I'll just use "Luhn" below.
Anyway here's what the trigger would look like:
delimiter //
CREATE TRIGGER make_voucher_code BEFORE INSERT ON vouchers
FOR EACH ROW
BEGIN
SET @vcount = @vcount + 1;
SET NEW.voucher = CONCAT(
NEW.voucher,
CAST(@vcount AS CHAR),
Luhn(CONCAT(NEW.voucher, CAST(@vcount AS CHAR))));
END;
//
delimeter ;
Then, in your INSERTs, you would put just '64352' in the query, as you've suggested. The trigger would append the rest.
Personally, unless you or someone else can solve the autoincrement/@vcount problem better, I would still prefer doing the MySQL transaction, which will do a better job than this of keeping everything atomic and keeping all your app code in PHP.
Or do the insert with value 0, then get the insert id, compute the value and update the record at .
精彩评论