Каков наилучший способ создания идентификатора для вставки SQL? - PullRequest
3 голосов
/ 24 февраля 2009

Каков наилучший, независимый от СУБД способ генерации идентификационного номера, который будет немедленно использоваться в операторе INSERT, сохраняя идентификаторы примерно в последовательности?

Ответы [ 11 ]

10 голосов
/ 24 февраля 2009

СУБД независимая? Это проблема. Двумя наиболее распространенными методами являются автоинкрементные столбцы и последовательности, и большинство СУБД выполняют одно или другое, но не оба. Таким образом, независимый от базы данных способ состоит в том, чтобы иметь другую таблицу с одним столбцом с одним значением, которое вы блокируете, выбираете, обновляете и разблокируете.

Обычно я говорю «к черту независимость от СУБД» и делаю это с последовательностями в PostgreSQL или со столбцами автоинкремента в MySQL. Для моих целей лучше поддерживать оба, чем пытаться найти один способ, который работает везде.

6 голосов
/ 24 февраля 2009

Если вы можете создать Глобальный уникальный идентификатор (GUID) на выбранном вами языке программирования - считайте это своим идентификатором.

С ними сложнее работать при устранении неполадок (гораздо проще ввести условие where, которое является INT), но есть и некоторые преимущества. Назначив GUID в качестве вашего ключа локально, вы можете легко построить отношения между родителями и дочерними записями без необходимости сначала сохранять родителя в базе данных и получать идентификатор. А поскольку GUID, по определению, является уникальным, вам не нужно беспокоиться об увеличении ключа на сервере.

1 голос
/ 24 февраля 2009

Я бы всегда использовал конкретное решение для БД, но если у вас действительно есть , то обычный способ сделать это - реализовать собственную последовательность. Ваша СУБД должна поддерживать транзакции.

Вы создаете таблицу последовательности, которая содержит столбец int, и заполняете ее первым номером, тогда ваша логика транзакции выглядит примерно так

begin transaction
update tblSeq set intID = intID + 1
select @myID = intID from tblSeq

inset into tblData (intID, ...) values (@myID, ...)
end transaction

Транзакция вызывает блокировку записи, так что следующая затем вставленная в очередь вставка не может обновить значение tblSeq до того, как запись будет вставлена ​​в tblData. Пока все операции вставки проходят через эту транзакцию, ваш сгенерированный идентификатор находится в последовательности.

1 голос
/ 24 февраля 2009

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

Самая большая проблема, из-за которой вы пытаетесь вставить значение идентификатора из другого места, - это когда в SQL-выражении содержится несколько записей, и несколько значений должны генерироваться одновременно.

Если вам это нужно, сделайте это частью ваших требований к выбору базы данных для использования с вашим приложением. Любой серьезный продукт СУБД будет иметь свой собственный механизм использования, и достаточно просто кодировать различия в DML. Вариации почти все в DDL.

1 голос
/ 24 февраля 2009

Да, очевидные пути в сыром SQL (и в моем порядке предпочтений) - это а) последовательности, б) поля автоинкремента. Лучший, более современный и независимый от СУБД способ - вообще не трогать SQL, а использовать (хороший) ORM.

1 голос
/ 24 февраля 2009

Существует автоматическое увеличение или последовательность

Какой смысл в этом, что меньше всего беспокоит вас?

Как вы будете обрабатывать сам SQL? MySQL имеет предел,

В SQL Server есть Top,

Оракул имеет ранг

Есть еще миллион таких вещей, как триггеры, изменение синтаксиса таблиц и т. Д.

0 голосов
/ 08 марта 2011

При использовании только SQL одним из подходов может быть следующее:

  1. Создайте таблицу, содержащую начальный идентификатор для ваших нужд
  2. Когда приложение развертывается в первый раз, приложение должно прочитать значение в его контексте.
  3. После этого увеличивать идентификатор (в поточно-ориентированном режиме) по мере необходимости 3.1 Записать идентификатор в базу данных (в поточно-ориентированном режиме), которая всегда сохраняет обновленное значение 3.2 Не записывайте это в базу данных, просто продолжайте увеличивать в памяти (потокобезопасный способ)
  4. Если по какой-либо причине сервер не работает, запишите текущее значение идентификатора в базу данных
  5. Когда сервер снова включится, он в последний раз выберет, откуда он ушел.
0 голосов
/ 24 февраля 2009

Это может быть немного боковой подход, но хорошая библиотека типа ORM, вероятно, сможет хотя бы скрыть различия. Например, в Ruby есть ActiveRecord (обычно используемый, но не исключительно связанный с веб-фреймворком Ruby the Rails), в котором есть Миграции. В пределах определения таблицы, которое объявлено в коде, не зависящем от платформы, детали реализации, такие как типы данных, последовательная генерация идентификаторов и создание индексов, опускаются ниже вашего видения.

Я прозрачно разработал схему на SQLite, затем реализовал ее на MS SQL Server и позже перенес в Oracle. Не изменяя код, который генерирует мое определение схемы.

Как я уже сказал, это может быть не то, что вы ищете, но самый простой способ инкапсулировать то, что меняется, - это использовать библиотеку, которая уже сделала инкапсуляцию для вас.

0 голосов
/ 24 февраля 2009

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

DateTime.Now.Ticks

Так что это будет что-то вроде ГГГГММДДЧЧММСССС

0 голосов
/ 24 февраля 2009

Есть ли причина, по которой они должны быть в последовательности? Если вы просто используете его в качестве идентификатора, то вы можете просто использовать часть UUID или первые пару цифр md5 (now ()).

...