查询以获取下一个身份?

Kar*_*ski 0 sql t-sql identity-column sql-server-2008-r2

查询以获取下一个身份?对于没有删除记录的表,这是可能的:

SELECT TOP 1 EMPID + 1 FROM Employee ORDER BY EMPID DESC
Run Code Online (Sandbox Code Playgroud)

如果有删除的数据,我将如何获得下一个身份?例如,我有一个这样的表:

EMPID    NAME
4001     someName
4002     someName
4003 ----------------------- this is deleted
4004     someName
4005     someName
4006     someName
4007     someName
4008     someName
4009 ----------------------- this is deleted
4010 ----------------------- this is deleted
Run Code Online (Sandbox Code Playgroud)

输出必须是4011

Aar*_*and 11

您可以IDENTITY在应用程序表单上可靠地显示值的唯一方法是首先插入它.IDENT_CURRENT当你是唯一一个测试它的人时,它似乎可以帮助你,但我可以向你保证,一旦多个用户使用你的应用程序,这将很快崩溃.这也很容易证明.创建下表:

CREATE TABLE dbo.whatever(ID INT IDENTITY(1,1), blat CHAR(1));
Run Code Online (Sandbox Code Playgroud)

现在,在两个单独的Management Studio窗口中,首先运行此代码,该代码模拟您在表单上显示的内容,如果您按照接受的答案和您所说的"工作":

SELECT IDENT_CURRENT('dbo.whatever');
Run Code Online (Sandbox Code Playgroud)

注意输出(两者都应该是1).这是对的.太远了.

现在,在一个窗口中运行:

INSERT dbo.whatever(blat) SELECT 'x';
SELECT SCOPE_IDENTITY();
Run Code Online (Sandbox Code Playgroud)

输出应该是1(这也是正确的SO FAR).

现在,在另一个窗口中,运行相同的东西,但x改为y.此输出现在2.UH-OH.这与您在表单上显示此用户的内容不符.您还可以通过查看表中有两行来验证,并使用12作为IDENTITY值:

SELECT ID, blat FROM dbo.whatever;
Run Code Online (Sandbox Code Playgroud)

执行此操作的正确方法,以及执行此操作的唯一方法是插入行,检索值,然后在表单上显示它.如果您需要预先向他们展示一些代理值(不知道为什么你需要这样做,或者为什么你的最终用户需要知道这个值,无论你什么时候检索它 - 为什么用户关心ID是什么?),然后创建一个单独的表并在IDENTITY那里生成您的值.

CREATE TABLE dbo.dummy_table(ID INT IDENTITY(1,1) PRIMARY KEY);
GO
CREATE TABLE dbo.real_table(ID INT PRIMARY KEY, ...other columns...);
GO
Run Code Online (Sandbox Code Playgroud)

现在,当您想在表单上显示"下一个"ID时,您可以使用以下内容执行此操作:

INSERT dbo.dummy_table DEFAULT VALUES;
SELECT SCOPE_IDENTITY();
Run Code Online (Sandbox Code Playgroud)

然后,当用户填写其余信息时,您可以使用从中检索的值插入dbo.real_tableID在插入列表中包含该列dbo.dummy_table.请注意,如果用户看到ID并且没有单击"保存",这仍然会有间隙,但该ID现在没有意义,因为它从未进入实际表格 - 并且其他任何人都不可能已经看到它(不像可能发生的事情IDENT_CURRENT,MAX+1和其他错误构思的"先检查价值"技术).

如果您的实际目标是将该书的三个副本插入到另一个表中,则解决方案非常简单,并且仍然需要您先插入该书.假设你有参数来表示书的名称和副本数量(以及我确定的其他参数):

DECLARE @Copies INT, @name NVARCHAR(32);

SELECT @Copies = 3, @name = N'Moby Dick';
Run Code Online (Sandbox Code Playgroud)

现在,我们可以插入dbo.Books表中,并使用输出将多行插入另一个表(dbo.Accession?).无需盲目猜测第一个"下一个"值BookID.

DECLARE @BookID INT;

INSERT dbo.Books(name, copies, whatever...) SELECT N'Moby Dick', 3, ...;

SELECT @BookID = SCOPE_IDENTITY();

INSERT dbo.Accession(AccessionID, BookID)
  SELECT rn, @BookID
  FROM
  (
    SELECT TOP (@Copies) rn = ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.columns ORDER BY [object_id]
  ) AS y;
Run Code Online (Sandbox Code Playgroud)

这使用技巧从目录视图生成多个行,但是Numbers如果有的话,您还可以使用内置表来提高效率(以及限制性较低的权限).