[an error occurred while processing this directive]

Использование одного автоинкрементального счетчика для нескольких таблиц в MySQL
Решение задачи сохранения единого для нескольких таблиц автоинкрементального счетчика. 

Иными словами, как реализовать в MySQL аналог SEQUENCE в PostgreSQL, работающих примерно так:

   CREATE SEQUENCE next_contraсt start 1 increment 1 maxvalue 2147483647 minvalue 1 cache 1;
   CREATE TABLE contract (
    "id"  integer NOT NULL DEFAULT nextval('next_contraсt') PRIMARY KEY,
   ...
   );


Метод 1. 

Создаем таблицу:

   CREATE TABLE option1 (id int not null primary key auto_increment) engine=innodb;

При необходимости получения очередного номера счетчика выполняем (фиктивная
вставка данных, необходимая для срабатывания auto_increment):

   INSERT INTO option1 VALUES (NULL);

Получаем текущее значение идентификатора через API-вызов $connection->insert_id(), например, в PHP:

   $last_id = mysql_insert_id();


Метод 2:

Создаем таблицу из одного столбца:

   CREATE TABLE option2 (id int not null primary key) engine=innodb;

Инициализируем первое значение:

   INSERT INTO option2 VALUES (1); # начинаем последовательность с 1

Для получения очередного значения счетчика выполняем:

   UPDATE option2 SET id=@id:=id+1;
   SELECT @id;

По производительности первый метод заметно быстрее второго:

   Метод 1 с использованием транзакций: 19 сек на выполнение 10000 итераций
   Метод 1 без использования транзакций: 13 сек на выполнение 10000 итераций
   Метод 2 с использованием транзакций: 27 сек на выполнение 10000 итераций
   Метод 2 без использования транзакций: 22 сек на выполнение 10000 итераций

Метод 3.

Использовать функцию LAST_INSERT_ID(), которая возвращает последний
сгенерированный через AUTO_INCREMENT на сервере идентификатор.

   UPDATE option3 SET id = LAST_INSERT_ID(id+1);

Метод 4.

Использование хранимых процедур и триггеров.

Создаем таблицу sequences для хранения счетчика и функцию  nextval('seqname')
для возвращения следующего номера:

   CREATE TABLE IF NOT EXISTS sequences
   (name CHAR(20) PRIMARY KEY,
   val INT UNSIGNED);

   DROP FUNCTION IF EXISTS nextval;

   DELIMITER //

   CREATE FUNCTION nextval (seqname CHAR(20))
   RETURNS INT UNSIGNED
   BEGIN
   INSERT INTO sequences VALUES (seqname,LAST_INSERT_ID(1))
   ON DUPLICATE KEY UPDATE val=LAST_INSERT_ID(val+1);
   RETURN LAST_INSERT_ID();
   END
   //

   DELIMITER ;

Создаем тестовую таблицу data для последующего подключения генератора последовательности:

   CREATE TABLE IF NOT EXISTS data
   (id int UNSIGNED NOT NULL PRIMARY KEY DEFAULT 0,
   info VARCHAR(50));

Создаем триггер для автоматизации инкрементирования счетчика в таблице data:

   DROP TRIGGER nextval;
   CREATE TRIGGER nextval BEFORE INSERT ON data
   FOR EACH ROW SET new.id=IF(new.id=0,nextval('data'),new.id);
   TRUNCATE TABLE data;

Экспериментируем:

   INSERT INTO data (info) VALUES ('bla');
   INSERT INTO data (info) VALUES ('foo'),('bar');
   SELECT * FROM data;

   +----+------+
   | id | info |
   +----+------+
   |  1 | bla  |
   |  2 | foo  |
   |  3 | bar  |
   +----+------+
 
Ключи: mysql, sequence / Лицензия: CC-BY
Раздел:    Корень / Программисту и web-разработчику / SQL и базы данных / MySQL специфика / Оптимизация и администрирование MySQL

[an error occurred while processing this directive]

[an error occurred while processing this directive]