Функция SQL Server для генерации последовательных чисел
Я хотел бы иметь функцию SQL Server dbo.GetNextNumber()
, который будет генерировать последовательные номера для каждого звонка. Насколько я понимаю, это невозможно с нативной функцией T-SQL, поскольку SQL Server настаивает, что функции должны быть детерминированными. Но, если бы вы могли показать мне встроенную функцию T-SQL, которая делает это, я бы действительно сделал это.
Я думал, что, возможно, это можно было бы написать с помощью функции CLR. Поскольку функции CLR являются статическими, порядковые номера должны храниться в контексте вызова операции set, так как сохранение их в качестве статической переменной приведет к тому, что несколько соединений будут использовать одну и ту же последовательность, что приведет к не очень последовательным числам. Я не знаю достаточно о встроенном CLR, чтобы увидеть, доступен ли контекст вызова операции set (select, update, delete, insert) со стороны CLR.
В конце дня следующий запрос
select dbo.GetNextNumber() from sysobjects
должен вернуть результат
1
2
3
4
5
Это нормально, если необходим другой вызов функции для сброса контекста, например
exec dbo.ResetSequenceNumbers()
Во избежание недоразумений и снижения вероятности потери времени на ответ на неправильный вопрос, обратите внимание, что я не ищу функцию генерации идентификатора для таблицы, и мне известны некоторые хаки (хотя и с использованием proc, а не функции), которые связаны с некоторыми временные таблицы со столбцами идентификаторов. ROW_NUMBER()
Функция близка, но она также не обрезается.
Большое спасибо за любые ответы
Кемаль
PS Удивительно, что в SQL Server есть встроенная функция для этого. Функция (при условии, что она не может использоваться в соединениях и выражениях), действительно проста и чрезвычайно полезна, но по какой-то причине она не включена.
5 ответов
Поскольку вы реализовали последовательность CLR на основе моей статьи, касающейся расчета промежуточных итогов, вы можете добиться того же, используя ROW_NUBER()
функция.
ROW_NUMBER()
функция требует ORDER BY
в OVER
Однако, есть хороший обходной путь, как избежать сортировки из-за ORDER BY
, Вы не можете поместить выражение в порядке, но вы можете поставить SELECT aConstant
там. Таким образом, вы можете легко добиться генерации чисел, используя приведенную ниже инструкцию.
SELECT
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNumber,
*
FROM aTable
В следующей версии SQL Server вы можете использовать ПОСЛЕДОВАТЕЛЬНОСТЬ для этого. В более ранних версиях это достаточно просто сделать, вставив в отдельную "таблицу последовательностей" (таблицу только с столбцом IDENTITY), а затем получив значение с помощью функции SCOPE_IDENTITY(). Вы не сможете сделать это в функции, но вы можете использовать хранимую процедуру.
Можете ли вы дать больше информации о том, почему ROW_NUMBER()
не режет это? В конкретном примере, который вы даете, ROW_NUMBER()
(с соответствующим уточнением OVER(ORDER BY)
) наверняка соответствует вашим критериям.
Но есть, конечно, случаи, когда ROW_NUMBER()
может быть бесполезным, и в этих случаях обычно есть другие методы.
Возможно, эта общая функция кажется вам полезной, но в большинстве случаев я считаю, что решение, лучше приспособленное к рассматриваемой проблеме, - это лучшая идея, чем функция общего назначения, которая в конечном итоге вызывает больше трудностей - как утечка абстракции, над которой вы постоянно работаете вокруг. Вы специально упоминаете о необходимости иметь функцию сброса. С этим ничего не нужно ROW_NUMBER()
учитывая, что он имеет OVER(PARTITION BY ORDER BY)
которые позволяют указать группировку.
SQL Server Denali имеет новую структуру последовательностей для разработчиков. Простота управления и обслуживания порядковых номеров в SQL Server после Denali. Подробные сведения о порядковых номерах в SQL Server можно найти.
Для других версий, кроме Denali, вы можете использовать таблицы последовательностей. Вот пример таблицы последовательности в SQL Server. Для чтения номера последовательности из таблицы последовательности необходимо вставить фиктивные записи из этой таблицы sql с автоматическим определением
Начиная с SQL Server 2022 для решения этой проблемы появился новый оператор:
GENERATE_SERIES ( start, stop [, step ] )
Для получения полной информации см. https://learn.microsoft.com/en-us/sql/t-sql/functions/generate-series-transact-sql?view=sql-server-ver16 .