我怎样才能从表中获得第一个免费ID

时间:2014-05-08 17:53:24

标签: sql sql-server

我有一个包含主键字段ID的表。我不想使用Identity,因为我需要为用户提供手动选择新对象的ID的可能性。所以我的想法是:

  1. 默认情况下,在编辑视图中,ID字段将为0.
  2. 如果用户不更改,我需要找到第一个免费ID并使用它。
  3. 如果用户更改了ID,我首先需要检查是否有另一个具有该ID的对象,并且在这种情况下会抛出错误。
  4. 如果没有,请使用用户选择的ID。
  5. 创建新对象
  6. 问题是如何查询和SQL Server表获取第一个免费ID号?

    示例1:

    ID
    --
    1
    2
    10
    

    第一个免费ID是3

    示例2:

    ID
    --
    1
    2
    3
    4
    

    首个免费ID为5

    有办法吗? 我能想到的是获取最小值和最大值,为可能的值创建一个循环,然后与表数据进行比较,但它涉及到数据库的太多查询。 谢谢!

2 个答案:

答案 0 :(得分:7)

您可以找到第一个免费ID作为第一个ID,其中没有" next"值:

select coalesce(min(t.id) + 1, 0)
from table t left outer join
     table t2
     on t.id = t2.id - 1
where t2.id is null;

编辑:

如果你想处理" 1"作为潜在的缺失值:

select (case when min(minid) > 1 then 1 else coalesce(min(t.id) + 1, 0) end)
from table t left outer join
     table t2
     on t.id = t2.id - 1 cross join
     (select min(id) as minid from table t) const
where t2.id is null;

答案 1 :(得分:1)

测试表

CREATE TABLE ID_TABLE(ID INT)
INSERT INTO ID_TABLE VALUES
(1),(2),(10)

存储过程

ALTER PROCEDURE dbo.usp_GetNextValue
@nxt_ID_Wanted INT = 0,
@nxt_ID_Available INT  OUTPUT
AS
BEGIN
  SET NOCOUNT ON;

  -- If user hasnt passed any value get next avilable value
IF (@nxt_ID_Wanted = 0)   
 BEGIN 
          SELECT TOP 1 @nxt_ID_Available  =  ID + 1 
        FROM 
         (
          SELECT   ID , ROW_NUMBER() OVER (ORDER BY ID ASC) AS rn
         FROM ID_TABLE
         )Q
        WHERE ID = rn
        ORDER BY ID DESC

      IF (@nxt_ID_Available IS NULL)
        BEGIN
          SET @nxt_ID_Available = 1;
        END
 END
     -- If user has passed a value check if it exists and raise error
ELSE  IF EXISTS(SELECT 1 FROM ID_TABLE WHERE ID = @nxt_ID_Wanted)
 BEGIN

       RAISERROR('Selected ID value already exists',16,1)
       SET @nxt_ID_Wanted = 0;
       RETURN;
 END 
ELSE      -- else just let the user have the value he/she wanted
 BEGIN 
   SET @nxt_ID_Available = @nxt_ID_Wanted;
 END

END

执行程序

DECLARE @ID INT;
EXECUTE dbo.usp_GetNextValue @nxt_ID_Wanted = 6
                             ,@nxt_ID_Available = @ID OUTPUT

SELECT @ID