Последовательность Oracle, но затем в MS SQL Server

В Oracle существует механизм для генерации порядковых номеров, например.

CREATE SEQUENCE supplier_seq

    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

И затем выполните оператор

supplier_seq.nextval

чтобы получить следующий порядковый номер.

Как создать такую ​​же функциональность в MS SQL Server?

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

Ответы

Ответ 1

Точного соответствия нет.

Эквивалент - это IDENTITY, который вы можете установить в качестве типа данных при создании таблицы. SQLSERVER автоматически создаст номер последовательности при вставке. Последнее вставленное значение можно получить, вызвав SCOPE_IDENTITY() или, обратившись к системной переменной @@IDENTITY (как указано Франсом)

Если вам нужен точный эквивалент, вам нужно будет создать таблицу, а затем написать процедуру для перенастройки следующего значения и других операций. См. Ответ Marks на подводных камнях на этом.

Edit:
SQL Server реализовал последовательность, похожую на Oracle. Пожалуйста, обратитесь к этому вопросу для получения более подробной информации.

Как реализовать последовательности в Microsoft SQL Server?

Ответ 2

Идентификация - лучшее и наиболее масштабируемое решение, НО, если вам нужна последовательность, которая не является инкрементирующим int, например 00A, 00B, 00C или какой-либо специальной последовательностью, существует второй вариант. Если оно выполнено правильно, оно масштабируется нормально, но если оно плохо реализовано, оно плохо масштабируется. Я не рекомендую это делать, но вы делаете это:

  • Вам нужно сохранить "следующее значение" в таблице. Таблица может быть простой, одной строкой, одной таблицей столбцов с таким значением. Если у вас есть несколько последовательностей, они могут совместно использовать таблицу, но вы можете получить меньше раздумий, имея отдельные таблицы для каждого.
  • Вам нужно написать одно выражение об обновлении, которое увеличит это значение на 1 интервал. Вы можете поместить обновление в сохраненный proc, чтобы сделать его простым в использовании и предотвратить повторение его в коде в разных местах.
  • Используя последовательность правильно, чтобы она масштабировалась разумно (нет, не так, как Identitiy:-) требует двух вещей: a. оператор update имеет специальный синтаксис, сделанный для этой точной проблемы, которая будет увеличивать и возвращать значение в одном выражении; б. вы должны получить значение из пользовательской последовательности до начала транзакции и вне области транзакции. Это одна из причин, по которой идентичность масштабируется - она ​​возвращает новое значение независимо от области транзакции, для любой попытки вставки, но не откатывается при сбое. Это означает, что он не будет блокироваться, а также означает, что у вас будут пробелы в неудачных транзакциях.

Синтаксис специального обновления немного меняется по версии, но суть в том, что вы выполняете назначение переменной и обновление в том же самом выражении. В 2008 году у Itzik Ben-Gan есть это опрятное решение: http://www.sqlmag.com/Articles/ArticleID/101339/101339.html?Ad=1

Метод старой школы 2000 и более выглядит следующим образом:

UPDATE SequenceTable SET @localVar = value = значение + 5 - изменить конец хвоста на логику прироста

Это увеличит и вернет вам следующее значение.

Если у вас абсолютно не может быть пробелов (сопротивляйтесь этому требованию:-), тогда технически можно поставить это обновление или proc в сторону остальной части вашего trnsaction, но вы берете BIG concurrency, так как каждая вставка ждет перед тем, как совершить.

Я не могу поверить в это; Я узнал все это от Ицика.

Ответ 3

введите поле Поле Идентичность. Поле автоматически получит свое значение. Вы можете получить последнее вставленное значение, вызвав SCOPE_IDENTITY() или, обратившись к системной переменной @@IDENTITY

Предпочтительна функция SCOPE_IDENTITY().

Ответ 4

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

Последовательности Oracle очень масштабируемы.

Хорошо, я немного верну его. Если вы действительно хотите сосредоточиться на concurrency, и вы готовы вывести цифры из строя, как это возможно с последовательностью, у вас есть шанс. Но так как вы, похоже, не знакомы с t-sql для начала, я бы начал искать другие варианты, когда (перенос приложения Oracle в MSSS - это то, что вы делаете)

Например, просто сгенерируйте GUID в функции "nextval". Это будет масштабироваться.

Oh и НЕ используйте таблицу для всех значений, просто чтобы сохранить максимальное значение в кеше. Вам нужно будет заблокировать его, чтобы обеспечить уникальные значения, и именно здесь вы прекратите масштабирование. Вам нужно выяснить, есть ли способ кэшировать значения в памяти и программный доступ к каким-то легким блокировкам - блокировки памяти, а не блокировки таблиц.

Ответ 5

Я хочу, чтобы SQL Server имел эту функцию. Это облегчит многое.

Вот как я обошел это.

Создайте таблицу с именем tblIdentities. В этой таблице введите строку с минимальными и максимальными значениями и частоту номера последовательности reset. Также поместите имя новой таблицы (назовите ее tblMySeqNum). Выполнение этого упрощает добавление генераторов последовательности последовательно.

tblMySeqNum имеет два столбца. ID (который является идентификатором int) и InsertDate (который является столбцом даты со значением по умолчанию для GetDate()).

Когда вам понадобится новый seq num, вызовите sproc, который вставляет в эту таблицу, и используйте SCOPE_IDENTITY(), чтобы создать созданную личность. Убедитесь, что вы не превысили максимальное значение в tblIdentities. Если вы вернете ошибку. Если не вернуть свой порядковый номер.

Теперь, до reset и очистите. Выполняйте работу, которая выполняется так регулярно, как требуется, которая проверяет все таблицы, перечисленные в tblIdentites (только один на данный момент), чтобы увидеть, нужно ли им быть reset. Если они достигли значения или времени reset, затем вызовите DBCC IDENT RESEED на имя таблицы, указанной в строке (tblMySeqNum в этом примере). Это также хорошее время, чтобы очистить дополнительные строки, которые вам действительно не нужны в этой таблице.

НЕ выполняйте очистку или повторение в вашем sproc, который получает личность. Если вы это сделаете, генератор порядковых номеров не будет хорошо масштабироваться.

Как я уже сказал, это облегчило бы эту функцию в SQL Server, но я обнаружил, что эта работа вокруг функционирует достаточно хорошо.

Vaccano

Ответ 6

Об этом, возможно, уже ответили давно... но с SQL 2005 и далее вы можете использовать функцию ROW_NUMBER... пример:

select ROW_NUMBER() OVER (ORDER BY productID) as DynamicRowNumber, xxxxxx,xxxxx

Оператор OVER использует ORDER BY для уникального первичного ключа в моем случае...

Надеюсь, это поможет... больше нет темповых таблиц или странных объединений!

Ответ 7

Если вы можете обновить SQL Server 2012, вы можете использовать объекты SEQUENCE. Даже SQL Server 2012 Express поддерживает последовательности.

CREATE SEQUENCE supplier_seq
    AS DECIMAL(38)
    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq

Результаты в:

---------------------------------------
1

(1 row(s) affected)


---------------------------------------
2

(1 row(s) affected)


---------------------------------------
3

(1 row(s) affected)


---------------------------------------
4

(1 row(s) affected)


---------------------------------------
5

(1 row(s) affected)

Просто позаботьтесь о правильном типе данных. Если бы я не указал его, MAXVALUE, который вы предоставили, не будет принят, поэтому я использовал DECIMAL с максимальной точностью.

Подробнее о SEQUENCES здесь: http://msdn.microsoft.com/en-us/library/ff878091.aspx

Ответ 9

Неточный ответ, но дополнение к некоторым существующим ответам

SCOPE_IDENTITY (Transact-SQL)

SCOPE_IDENTITY, IDENT_CURRENT и @@IDENTITY - аналогичные функции потому что они возвращают значения, которые вставляются в столбцы идентификаторов.

IDENT_CURRENT не ограничивается областью и сеансом; он ограничен указанная таблица. IDENT_CURRENT возвращает значение, сгенерированное для конкретной таблицы в любой сессии и любой области. Для получения дополнительной информации см. IDENT_CURRENT (Transact-SQL).

Это означает, что два разных сеанса могут иметь одинаковое значение или порядковый номер, чтобы избежать этого и получить уникальный номер для всех сеансов, используя IDENT_CURRENT

Ответ 10

Именно из-за этого IDENT_CURRENT не ограничивается областью и сеансом; он ограничен указанной таблицей. нам нужно использовать SCOPE_IDENTITY(), поскольку идентификатор области дает нам уникальный номер, сгенерированный в нашем сеансе, а уникальность предоставляется самой идентичностью.