MySQL эквивалент Oracle SEQUENCE.NEXTVAL - PullRequest
14 голосов
/ 28 января 2012

Мне нужно иметь возможность сгенерировать запрос, который вернет следующее значение идентификатора в следующей таблице:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
)

В Oracle вы можете вызвать NEXTVAL для последовательности, и это даст вам следующую последовательность (примечание: без необходимости вставлять таблицу).

После поиска в Google я обнаружил, что вы можете найти текущее значение auto_increment с помощью следующего запроса:

SELECT Auto_increment 
FROM information_schema.tables 
WHERE table_name='animals';

Проблема в том, что я хотел бы, чтобы значение увеличивалось при каждом запросе значения. В Oracle, когда вы вызываете nextval, значение последовательности увеличивается, даже если вы не вставляете строку в таблицу.

Можно ли каким-либо образом изменить вышеуказанный запрос, чтобы возвращаемое значение всегда отличалось от последнего вызова запроса? т.е. Auto_increment увеличивается каждый раз, когда проверяется, и при использовании в запросе будет использоваться новое значение.

Я использую Spring JDBCTemplate, так что, если это можно сделать одним запросом, тем лучше.

Ответы [ 7 ]

12 голосов
/ 09 ноября 2012

http://docs.oracle.com/cd/E17952_01/refman-5.5-en/example-auto-increment.html

3.6.9.Использование AUTO_INCREMENT

Атрибут AUTO_INCREMENT может использоваться для создания уникального идентификатора для новых строк:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
);

INSERT INTO animals (name) VALUES
    ('dog'),('cat'),('penguin'),
    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;
Which returns:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+

Не указано значение для столбца AUTO_INCREMENT,поэтому MySQL присваивает порядковые номера автоматически.Вы также можете явно присвоить NULL или 0 столбцу для генерации порядковых номеров.

Вы можете получить самое последнее значение AUTO_INCREMENT с помощью функции SQL LAST_INSERT_ID () или API-функции mysql_insert_id () C.Эти функции зависят от соединения, поэтому на их возвращаемые значения не влияет другое соединение, которое также выполняет вставки.

Используйте наименьший целочисленный тип данных для столбца AUTO_INCREMENT, который достаточно велик для хранения максимального значения последовательности, которое выпонадобится.Когда столбец достигает верхнего предела типа данных, следующая попытка сгенерировать порядковый номер не удалась.Если возможно, используйте атрибут UNSIGNED, чтобы увеличить диапазон.Например, если вы используете TINYINT, максимально допустимый порядковый номер равен 127. Для TINYINT UNSIGNED максимум равен 255. См. Раздел 11.2.1, «Целочисленные типы (точное значение) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT”Для диапазонов всех целочисленных типов.

Примечание Для многострочной вставки LAST_INSERT_ID () и mysql_insert_id () фактически возвращают ключ AUTO_INCREMENT из первой из вставленных строк.Это позволяет корректно воспроизводить вставки из нескольких строк на других серверах в настройке репликации.

Если столбец AUTO_INCREMENT является частью нескольких индексов, MySQL генерирует значения последовательности, используя индекс, начинающийся со столбца AUTO_INCREMENT, если естьэто один.Например, если таблица животных содержит индексы PRIMARY KEY (grp, id) и INDEX (id), MySQL будет игнорировать PRIMARY KEY для генерации значений последовательности.В результате таблица будет содержать одну последовательность, а не последовательность на значение grp.

Чтобы начать со значения AUTO_INCREMENT, отличного от 1, установите это значение с помощью CREATE TABLE или ALTER TABLE, например так:

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;Примечания InnoDB

Для таблиц InnoDB будьте осторожны, если вы изменяете столбец, содержащий значение автоинкремента в середине последовательности операторов INSERT.Например, если вы используете оператор UPDATE, чтобы поместить новое, большее значение в столбец с автоинкрементом, последующий INSERT может столкнуться с ошибкой «Duplicate entry».Проверка того, присутствует ли уже значение автоинкремента, выполняется, если вы выполняете команду DELETE, после которой следуют дополнительные операторы INSERT, или когда вы фиксируете транзакцию, но не после оператора UPDATE.

MyISAM Notes

Для таблиц MyISAM вы можете указать AUTO_INCREMENT для вторичного столбца в индексе из нескольких столбцов.В этом случае сгенерированное значение для столбца AUTO_INCREMENT рассчитывается как MAX (auto_increment_column) + 1 префикс WHERE = данный префикс.Это полезно, когда вы хотите поместить данные в упорядоченные группы.

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

В этом случае (когда столбец AUTO_INCREMENT является частью индекса из нескольких столбцов) значения AUTO_INCREMENT используются повторно.если вы удалите строку с наибольшим значением AUTO_INCREMENT в любой группе.Это происходит даже для таблиц MyISAM, для которых значения AUTO_INCREMENT обычно не используются повторно.

Дальнейшее чтение

Дополнительная информация об AUTO_INCREMENT доступна здесь:

Как назначить атрибут AUTO_INCREMENTв столбец: Раздел 13.1.17, «Синтаксис CREATE TABLE» и Раздел 13.1.7, «Синтаксис ALTER TABLE».

Как ведет себя AUTO_INCREMENT в зависимости от режима SQL NO_AUTO_VALUE_ON_ZERO: Раздел 5.1.7, «Сервер»Режимы SQL ».

Как использовать функцию LAST_INSERT_ID (), чтобы найти строку, содержащую самое последнее значение AUTO_INCREMENT: Раздел 12.14,« Информационные функции ».

Установка значения AUTO_INCREMENT равнымИспользуется: Раздел 5.1.4, «Системные переменные сервера».

AUTO_INCREMENT и repссылка: Раздел 16.4.1.1, «Репликация и AUTO_INCREMENT».

Системные переменные сервера, связанные с AUTO_INCREMENT (auto_increment_increment и auto_increment_offset), которые можно использовать для репликации: раздел 5.1.4, «Системные переменные сервера».

http://search.oracle.com/search/search?q=auto_increment&group=Documentation&x=0&y=0

6 голосов
/ 28 января 2012

В этом примере с InnoDB демонстрируется способ реализации собственного счетчика с использованием взаимосвязанных запросов:

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

Для чего вам нужно создать разрыв? Зарезервировать идентификаторы? Я бы предпочел «исправить» дизайн любой ценой и обновить другие модули вместо того, чтобы касаться последовательности.

Вместо того, чтобы просто увеличивать последовательность явно, я бы подразумевал ее, вставляя строку по умолчанию (помеченную как недействительную) для каждого идентификатора, чтобы выделить и вернуть идентификатор. Этот подход последовательный и портативный. Позже, вместо принудительного вставления с использованием явного значения последовательности, вы можете обновить эти строки по умолчанию их соответствующими значениями последовательности. Это требует больше памяти, но без блокировок. Здесь может помочь сборка мусора в просроченных строках. Операторы 'insert or update' могут воссоздавать строки, собранные сборщиком мусора, хотя я бы этого не сделал.

4 голосов
/ 28 января 2012

Вы можете добавить свою собственную функцию MySQL - как показано на http://www.microshell.com/database/mysql/emulating-nextval-function-to-get-sequence-in-mysql/ - позволяющую вам сделать что-то вроде этого:

SELECT nextval('sq_my_sequence') as next_sequence;
2 голосов
/ 28 января 2012

MySQL использует AUTO_INCREMENT, который служит целям. Но есть и различия ниже:

MySQL AUTO_INCREMENT в Oracle SEQUENCE Отличия

  • AUTO_INCREMENT ограничено одним столбцом на таблицу
  • AUTO_INCREMENT должен быть присвоен конкретному столбцу table.column (не допускается использование нескольких таблиц)
  • AUTO_INCREMENT вставляется как не указанный столбец или имеет значение NULL

если вы хотите увидеть реализацию SEQUENCE с MySQL, можете сделать с SP.

См. Ссылку ниже объяснил все, что вы хотите.

http://ronaldbradford.com/blog/sequences-in-mysql-2006-01-26/

1 голос
/ 28 января 2012

Требуется следующее значение в таблице ТА, чтобы можно было создавать строки, которые еще не вставлены, не нарушая другие процессы, использующие автоинкремент?

Некоторые параметры:

Идите вперед и просто вставьте строки, чтобы «использовать последовательность», пометьте их как ожидающие, а затем обновите их позже.

Вставьте в транзакцию и отмените транзакцию - последовательность автоматического номера должна быть использована иобычно ставьте «пробел» в таблице - это число теперь свободно для использования.

В Oracle последовательность полностью независима от таблицы, поэтому процессы могут использовать последовательность или нет (и они могут такжеиспользуйте одну и ту же последовательность для разных таблиц).В этом ключе вы могли бы реализовать таблицу только для последовательности, к которой вы обращаетесь через какую-то функцию, а для других процессов, которым необходимо полагаться на автоинкремент, удалить автоинкремент и использовать триггер, который назначает из того жефункция последовательности, если идентификатор не указан.

0 голосов
/ 28 мая 2018
1.) create table query
2.) Insert query
3.) Update query
4.) Select query for that table e.g. SELECT next_val FROM hib_sequence;
5.) Before each select update first, like this you can achieve similar

-- CREATE TABLE hib_sequence (next_val INT NOT NULL);
-- UPDATE hib_sequence SET next_val=LAST_INSERT_ID(next_val+1);
-- select last_insert_id();
-- INSERT INTO hib_sequence VALUES (0);

-- select next_val from hib_sequence;
0 голосов
/ 12 августа 2015

Взгляните на MariaDBs SEQUENCE Двигатель.С его помощью вы можете создавать последовательности так же просто, как

SELECT seq FROM seq_1_to_5;
+-----+
| seq |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
+-----+

Подробности здесь: https://mariadb.com/kb/en/mariadb/sequence/

С этим вы сможете сделать что-то вроде

SELECT min(seq) as nextVal FROM seq_1_to_500 
WHERE seq NOT IN (SELECT ID FROM customers)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...