IDENTITY
您在应用程序表单上可靠地显示值的唯一方法是INSERT IT FIRST。IDENT_CURRENT
当您是唯一测试它的人时,这似乎对您有所帮助,但我可以向您保证,一旦多个用户使用您的应用程序,这将很快分崩离析。这也很容易证明。创建下表:
CREATE TABLE dbo.whatever(ID INT IDENTITY(1,1), blat CHAR(1));
现在,在两个单独的 Management Studio 窗口中,首先运行此代码,如果您遵循接受的答案和您所说的“有效”,它会模拟您将在表单上显示的内容:
SELECT IDENT_CURRENT('dbo.whatever');
注意输出(两者都应该是1
)。这是对的。到目前为止。
现在,在一个窗口中,运行以下命令:
INSERT dbo.whatever(blat) SELECT 'x';
SELECT SCOPE_IDENTITY();
输出应该是1
(这也是正确的SO FAR)。
现在,在另一个窗口中,运行相同的操作,但更改x
为y
. 这个输出现在是2
. 呃-哦。这与您在该用户的表单上显示的内容不符。您还可以通过查看表中有两行来验证这一点,其中1
和2
作为IDENTITY
值:
SELECT ID, blat FROM dbo.whatever;
正确的方法,也是唯一的方法是插入一行,检索值,然后将其显示在表单上。如果您需要事先向他们显示一些代理值(不知道为什么需要这样做,或者为什么您的最终用户无论何时检索它都需要知道这个值 - 为什么用户关心 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
现在,当您想在表单上显示“下一个”ID 时,您可以使用以下方法:
INSERT dbo.dummy_table DEFAULT VALUES;
SELECT SCOPE_IDENTITY();
然后,当用户填写其余信息时,您可以使用从 中检索到的值插入dbo.real_table
该列并将其包含ID
在插入列表中dbo.dummy_table
。请注意,如果用户看到一个 ID 并且没有点击保存,这仍然会导致空白,但该 ID 现在没有意义,因为它从未进入真实表格 - 并且其他任何人都不可能已经看到了(与 和其他考虑不周的“首先检查值”技术可能发生的情况不同IDENT_CURRENT
)MAX+1
。
如果您的实际目标是将书的三份副本插入到另一个表中,则解决方案非常简单,仍然需要您先插入书。假设您有参数来表示书名和副本数(以及我确定的其他参数):
DECLARE @Copies INT, @name NVARCHAR(32);
SELECT @Copies = 3, @name = N'Moby Dick';
现在,我们可以插入到dbo.Books
表中,并使用输出将多行插入到另一个表中(dbo.Accession
?)。无需盲目猜测BookID
first 的“下一个”值。
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;
这使用了从目录视图生成多行的技巧,但您也可以使用内置Numbers
表(如果有的话)以提高效率(并减少限制性权限)。