Mic*_*oie 41 sql sql-server gaps-and-islands
如何在SQL Server列中找到最小的未使用数字?
我将要将大量手动记录的记录从Excel导入SQL Server表.它们都有一个数字ID(称为文档编号),但由于不再适用的原因,它们没有按顺序分配,这意味着从现在开始我的网站记录新记录时,需要为其分配最小的文档编号(尚未采取的大于零).
有没有办法通过纯SQL执行此操作,或者这是TSQL /代码的问题?
谢谢!
编辑
特别感谢WW提出并发问题.鉴于这是一个Web应用程序,它根据定义是多线程的,任何面临同样问题的人都应该考虑代码或数据库级别锁定来防止冲突.
LINQ
仅供参考 - 这可以通过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();
Run Code Online (Sandbox Code Playgroud)
nextNewNum == 5
Dar*_*ler 57
找到不存在Id + 1行的第一行
SELECT TOP 1 t1.Id+1
FROM table t1
WHERE NOT EXISTS(SELECT * FROM table t2 WHERE t2.Id = t1.Id + 1)
ORDER BY t1.Id
Run Code Online (Sandbox Code Playgroud)
编辑:
要处理最低现有id不是1的特殊情况,这是一个丑陋的解决方案:
SELECT TOP 1 * FROM (
SELECT t1.Id+1 AS Id
FROM table t1
WHERE NOT EXISTS(SELECT * FROM table t2 WHERE t2.Id = t1.Id + 1 )
UNION
SELECT 1 AS Id
WHERE NOT EXISTS (SELECT * FROM table t3 WHERE t3.Id = 1)) ot
ORDER BY 1
Run Code Online (Sandbox Code Playgroud)
WW.*_*WW. 12
到目前为止,在任何答案中都没有提到锁定或并发性.
考虑这两个用户几乎同时添加文档: -
User 1 User 2
Find Id
Find Id
Id = 42
Id = 42
Insert (42..)
Insert (42..)
Error!
Run Code Online (Sandbox Code Playgroud)
您需要:a)处理该错误并再次循环查找下一个可用的Id,或者b)在流程开始时锁定,因此只有1个用户在特定时间查找ID
Bil*_*win 10
SELECT TOP 1 t1.id+1
FROM mytable t1
LEFT OUTER JOIN mytable t2 ON (t1.id + 1 = t2.id)
WHERE t2.id IS NULL
ORDER BY t1.id;
Run Code Online (Sandbox Code Playgroud)
这是使用@Jeffrey Hantlin和@Darrel Miller给出的相关子查询的答案的替代方案.
但是,您所描述的政策并不是一个好主意.ID值应该是唯一的,但不应要求是连续的.
如果您通过电子邮件向某人发送文档#42的链接,然后删除该文档,会发生什么?稍后,您将重新使用id#42作为新文档.现在,电子邮件的收件人将按照指向错误文档的链接进行操作!
declare @value int
select @value = case
when @value is null or @value + 1 = idcolumn
then idcolumn
else @value end
from table
order by idcolumn
select @value + 1
Run Code Online (Sandbox Code Playgroud)
是否执行1个表扫描而不是2个表扫描哈希匹配和联接(如最佳答案)
| 归档时间: |
|
| 查看次数: |
31036 次 |
| 最近记录: |