Сложная вставка

Я использую mysql/php.

мой стол выглядит

id (int autoincrement)  
voucher(varchar 25)

Я генерирую коды ваучеров, где код:

  • 1 случайное число (например, 64)
  • 1 фиксированный номер (например, 352)
  • значение поля id (1,2,3,4,5...)
  • 1 контрольная цифра (алгоритм Луна).

Очевидная проблема при работе с php заключается в том, что мне нужно сделать выбор, получить следующее значение автоинкремента, вычислить код, вставить, к этому времени могла бы быть вставлена ​​другая строка.

То, что я хочу сделать, это вместо этого,

делать insert into vouchers (voucher) value('64352') и пусть это создаст остальную часть меня.

Как я могу это сделать? функция / триггер?

2 ответа

Решение

Если вы используете InnoDB, проще всего будет использовать существующий код и обернуть его в транзакцию MySQL. то есть в псевдокоде:

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:

Поскольку вы упомянули триггеры, я изучил это и считаю, что это выполнимо. Пара вопросов.

  1. Доступ к "следующему автоинкрементному идентификатору" из триггера... Я не знаю "хорошего" способа сделать это. В запросах INSERT у вас есть доступ только к NEW, а не к OLD (существующим строкам) значениям (см. Синтаксис триггера). В этом примере я просто поддерживаю отдельный счетчик @vcount на сервере. Чтобы инициализировать это значение тем идентификатором, который вы используете в данный момент, вы просто должны сделать "SET @vcount = 42;"

  2. Алгоритм Луна. Вы должны будете реализовать это как функцию SQL. Вот валидатор Luhn в SQL, с которого вы могли бы написать. В качестве альтернативы вы можете использовать хэш / контрольную сумму с помощью встроенной функции MySQL, такой как MD5 (и использовать только первые символы X, если вам нужен короткий код ваучера). В любом случае вам нужно сделать хеш-функцию... Я просто буду использовать "Luhn" ниже.

В любом случае вот как будет выглядеть триггер:

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 ;

Затем, в ваших INSERT, вы бы указали в запросе только "64352", как вы и предлагали. Триггер добавит остальные.

Лично, если вы или кто-то другой не сможете лучше решить проблему автоинкремента /@vcount, я все же предпочел бы выполнить транзакцию MySQL, которая лучше справится с задачей, чем хранение всего атомарного и сохранение всего кода вашего приложения на PHP.

Или выполните вставку со значением 0, затем получите идентификатор вставки, вычислите значение и обновите запись по адресу.

Другие вопросы по тегам