Найдите наименьшее неиспользуемое число в SQL Server - PullRequest
40 голосов
/ 26 марта 2009

Как найти наименьшее неиспользуемое число в столбце SQL Server?

Я собираюсь импортировать большое количество записей, записанных вручную, из Excel в таблицу SQL Server. Все они имеют числовой идентификатор (называемый номером документа), но они не были назначены последовательно по причинам, которые больше не применяются, то есть с этого момента, когда мой веб-сайт записывает новую запись, ему необходимо присвоить ему наименьший возможный номер документа больше нуля), который еще не был взят.

Есть ли способ сделать это с помощью простого SQL или это проблема для TSQL / кода?

Спасибо!

EDIT

Особая благодарность WW за поднятие проблемы параллелизма. Учитывая, что это веб-приложение, оно по определению является многопоточным, и всем, кто сталкивается с этой же проблемой, следует рассмотреть возможность блокировки на уровне кода или БД для предотвращения конфликта.

* LINQ 1018 *

FYI - это может быть выполнено через LINQ со следующим кодом:

var nums = new [] { 1,2,3,4,6,7,9,10};

int nextNewNum = (
    from n in nums
    where !nums.Select(nu => nu).Contains(n + 1)
    orderby n
    select n + 1
).First();

nextNewNum == 5

Ответы [ 14 ]

1 голос
/ 27 февраля 2017

Я столкнулся с подобной проблемой и придумал это:

Select Top 1 IdGapCheck
From (Select Id, ROW_NUMBER() Over (Order By Id Asc) AS IdGapCheck
    From dbo.table) F
Where Id > IdGapCheck
Order By Id Asc
1 голос
/ 30 апреля 2015

Я знаю, что этот ответ опоздал, но вы можете найти наименьшее неиспользуемое число, используя рекурсивное табличное выражение:

CREATE TABLE Test
(
    ID int NOT NULL
)

--Insert values here

;WITH CTE AS
(
    --This is called once to get the minimum and maximum values
    SELECT nMin = 1, MAX(ID) + 1 as 'nMax' 
    FROM Test
    UNION ALL
    --This is called multiple times until the condition is met
    SELECT nMin + 1, nMax 
    FROM CTE
    WHERE nMin < nMax
)

--Retrieves all the missing values in the table. Removing TOP 1 will
--list all the unused numbers up to Max + 1
SELECT TOP 1 nMin
FROM CTE
WHERE NOT EXISTS
(
    SELECT ID
    FROM Test
    WHERE nMin = ID
)
1 голос
/ 26 марта 2009

Вы действительно должны попытаться преобразовать столбец в IDENTITY. Сначала BACKUP, затем используйте ROW_NUMBER, чтобы обновить идентификатор документа, чтобы они начинались с 1 и до количества документов. Вы должны делать это в WHILE по одному, потому что, если числовой столбец используется в качестве ссылки в других таблицах (внешних ключах), SQL Server попытается обновить внешние ключи и, возможно, потерпит неудачу из-за конфликтов. В конце просто включите идентификационные спецификации для столбца.

:) Теперь больше работы, но это избавит вас от многих проблем позже.

0 голосов
/ 05 марта 2019

Для БД Oracle это должно сделать Задание:

SELECT MIN(NI) FROM
        (SELECT ROWNUM AS NI,YOUR_ID
         FROM (SELECT YOUR_ID
               FROM YOUR_TABLE 
               ORDER BY YOUR_ID ASC))
WHERE NI<>YOUR_ID
...