Последовательность 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
Ответ 8
Не совсем ответ, но похоже, что в SQLServer в 2012 году будут появляться последовательности.
http://www.sql-server-performance.com/2011/sequence-sql-server-2011/
Ответ 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(), поскольку идентификатор области дает нам уникальный номер, сгенерированный в нашем сеансе, а уникальность предоставляется самой идентичностью.