Функция 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 .

Другие вопросы по тегам