仅将一个IDENTITY列插入表中的行


83

我有一个表Administrator,只有一个列adminId,这是主键。由于业务规则,必须采用这种方式。

我想一劳永逸地理解如何编写存储过程,以便在这样的表中插入值。我正在使用SQL Server和T-SQL,并尝试使用SCOPE_IDENTITY(),但由于该表的INSERT_IDENTITY为false或off,因此无法正常工作。

我真的不希望仅为了能够插入新行而插入虚拟值。谢谢!


1
澄清一下:您的问题是“如何在具有单个IDENTITY列的SQL Server表中插入行”?
gbn

是的,您是对的,感谢您的澄清
Phil

2
对于在这里着陆的人们,这是以前曾被问过的,正确的答案在这里:stackoverflow.com/questions/850327/…–
BJury

Answers:


140

如果您有一列是IDENTITY,则只需执行此操作

INSERT MyTable DEFAULT VALUES;  --allows no column list. The default will be the IDENTITY
SELECT SCOPE_IDENTITY();

如果没有身份,可以设置吗?这是最好的方法..并使用上面的SQL。

如果没有,您要插入新行

INSERT MyTable (admidid)
OUTPUT INSERTED.admidid --returns result to caller
SELECT ISNULL(MAX(admidid), 0) + 1 FROM MyTable

笔记:

  • 在高负载下,MAX解决方案可能会因重复而失败
  • SCOPE_IDENTITY事实之后,而不是之前
  • SCOPE_IDENTITY仅适用于IDENTITY列。同理使用IDENT_CURRENT的任何愚蠢行为
  • 输出子句将SCOPE_IDENTITY替换为MAX解决方案

1

您需要将IDENTITY_INSERT添加到您的选择语句中:

SET IDENTITY_INSERT MyTable ON

INSERT INTO MyTable
(AdminCol)

SELECT AdminColValue

 FROM Tableb

完成后,请确保记住

SET IDENTITY_INSERT MyTable OFF

这是从BOL对其工作方式的良好描述:http : //msdn.microsoft.com/zh-cn/library/aa259221( SQL.80) .aspx


我是否应该这样做:SET IDENTITY_INSERT管理员打开插入管理员(SCOPE_IDENTITY())SET IDENTITY_INSERT管理员关闭?
Phil

是。这就是您需要做的。SET ON,编写您的代码,最后SET OFF。
DataWriter 2010年

我认为这不是正确的答案。如果它是一个标识列,则不应在其中添加值。接受的答案是正确的答案。
毫米

0

@Phil:您不是说您的表有两(2)列,即自动递增PK列和AdminName列吗?如果只有一列AdminName进入,则AdminName是PK,并且您当然不能自动增加字符串。业务规则是否期望您将标准Windows用户名用作主键?这将是可行的并且有意义,因为这样您就不需要在AdminName列上使用替代的唯一索引。

但是,如果您的表有两列,则不会是一列:

在SQLServer中,自动增量是表/列定义的一部分。您可以将列定义为整数,然后再使其成为标识列,指定增量,通常为1,但可以为2或5或10或其他值。要插入行,只需插入其他列的值,而对PK列不做任何事情:

insert into T
(foo)   -- column(s) list
values('bar') -- values list

执行插入操作的存储过程可以使SCOPE_IDENTITY成为RETURN值,或者SCOPE_IDENTITY可以作为OUT参数传递回客户端。

PS SCOPE_IDENTITY()返回当前作用域中最近生成的自动递增的标识值;它不会生成下一个标识值。

编辑:

大概,您的管理员表包含一组管理员。但是,如果除了整数主键列之外没有任何列,则无法识别管理员;您唯一可以做的就是将它们彼此区分开。这根本不会使您走得太远。但是,如果您的管理员表具有以下任一结构:

ID   INTEGER PRIMARY KEY AUTOINCREMENT
windowsusername   varchar(50)  (unique index)

要么

windowsusername varchar(50) primary key

您将能够从其他表中引用管理员的表,并且外键是MEANINGFUL。而这正是包含单个整数列的表所缺少的-的含义。

有两列,然后可以有一个存储过程来执行此操作:

insert into Administrators
(windowsusername)
values('mydomain\someusername');
return SCOPE_IDENTITY();

并且您的客户端程序将返回自动生成并分配给新插入的行的自动递增ID作为返回值。这种方法是通常的做法,我甚至可以说它被认为是“最佳实践”。

PS:您提到如果您“没有要插入的内容”,您将不知道如何“插入值”。那里有一个矛盾。如果您没有要插入的内容,为什么要插入?如果您完全不了解客户,为什么还要创建新的客户记录?不是他们的名字,他们的城市,他们的电话号码,什么都没有?


2
我的表有一个列adminId,它是int的增量值
Phil,2010年

这是我见过的最奇怪的设计,我从事这项业务已经20多年了,并且在我这一天中看到了一些奇怪的东西。因此,您的问题是,当一个表仅包含定义为自动递增标识列的主键列,而该表仅包含该PK列而没有其他列时,如何将其插入到该表中呢?
Tim

那么什么是反对票呢?某个地方存在事实错误,还是表达了对设计缺乏价值的看法?
蒂姆(Tim)2010年

1
只是为了阐明数据库设计背后的原因。我们在一张桌子上有用户。用户和管理员之间是否存在关系;他们被视为管理员。除了实际的唯一ID外,在管理表中仅保留其他内容。“真实”数据位于用户表和has-relation关系中(带有时间戳和授予者等)。
菲尔(Phil)

1
@Phil:因此,您正在使用表和外键关系来表示简单的布尔/位列可以做什么。您可能无法将这样的位列添加到表中,并且必须提出一些解决方法。But an autoincrementing integer whose autoincrementation must be disabled is a poor solution.您需要做的是一个与用户表具有一对一关系的并行表,并在该表中创建一个bit列。当该列为true时,表示用户具有has-admin。清洁。标准。设计。
蒂姆(Tim)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.