为啥我必须在这个插入语句中包含主键列?
Posted
技术标签:
【中文标题】为啥我必须在这个插入语句中包含主键列?【英文标题】:Why do I have to include the primary key column in this insert statement?为什么我必须在这个插入语句中包含主键列? 【发布时间】:2013-01-11 05:36:14 【问题描述】:给定一个 SQL Server Express Compact Edition 数据库,其中包含一个名为“Clients”的表,其中包含以下列:
ID, FirstName, MiddleName, Nickname, LastName, Suffix, IsMale
其中 ID 是自动递增的主键/标识值,当我尝试在表上使用此命令时:
INSERT INTO Clients (Title, FirstName, MiddleName, Nickname, LastName, Suffix,
IsMale) VALUES ('', 'John', '', '', 'Smith', '', 'True')
一切正常。但是当我尝试使用这个命令时:
INSERT INTO Clients VALUES ('', 'John', '', '', 'Smith', '', 'True')
出现此错误:
The number of columns in the query and the table must match. [ Number of columns
in query = 7, Number of columns in table = 8 ]
我在 SQL Server 中使用插入语句已经有一段时间了,这从来都不是问题;针对列数的验证始终忽略自动递增的主键/身份类型。在这种情况下,唯一的主要区别是我现在使用的是非常低端的 SQL Server 版本,而我习惯使用更专业的版本。万一这可能很重要,我在 C# 程序中使用它。
这是什么原因造成的?谢谢。
编辑:这个问题的很多焦点是我在使用非免费、非紧凑版本的 SQL Server 时从未遇到过这个问题。我以前使用的 SQL Server 总是足够聪明,可以忽略列计数中的标识/主键列,并且只需找出自动递增的值,而无需我拼出特定的列名。
虽然这里的另一个区别是我以前总是使用 SQL Management Studio 来处理表定义,而在这种情况下我正在使用 VS 2012 和 SQL Server Compact Edition。所涉及的用户界面显然非常不同,所以我想可能是为表指定了某些内容,或者当您在 Management Studio 中执行此操作时,可能会阻止此问题发生?
【问题讨论】:
查看(并关注!):Bad habits to kick : using SELECT * / omitting the column list - 在SELECT
和INSERT
语句中始终明确指定列列表被认为是最佳实践
这个does work。问题一定是别的。 (例如,您的 ID 并不是真正的 IDENTITY,而是由触发器处理。)话虽如此,我同意 @marc_s 的评论。
"我现在使用的是非常低端的 SQL Server 版本,而我习惯使用更专业的版本" - 请详细说明
SQL Server Compact Edition Express,尽管我已经忘记了它的确切名称,但我们倾向于在工作中使用完全成熟的 SQL Server 2012,并配有 SQL Server Management Studio。尽管我不记得确切的名称,但我在这里使用的是精简版的免费版本,而我通常习惯使用非精简版的昂贵版本。我现在不在工作,所以我找不到确切的名字。
这可能是 Compact Edition 特有的(如果这确实是您的服务器版本),但我无法确定。从未使用过精简版,至于我使用过的那些版本,不记得遇到过此类问题。
【参考方案1】:
如果您没有在插入语句中指定列,那么它会考虑所有列。即使其中一列是自动递增的。
Insert - MSDN
column_list 必须在 将显式值插入到 标识列,并且 SET IDENTITY_INSERT 选项必须为 ON 桌子。
【讨论】:
是的,但默认情况下,当您没有提供列列表时,自动增量列被视为与计算列相同,这意味着您必须仅为所有“正常”列指定值。反过来,这意味着 OP 的声明应该起作用 if ID 确实是一个 IDENTITY 列(我目前非常怀疑,否则他们忘记提及的东西)。【参考方案2】:可以用两种形式编写 INSERT INTO 语句。
第一种形式没有指定将插入数据的列名,只指定它们的值:
INSERT INTO table_name
VALUES (value1, value2, value3,...)
这只有在提供的值的数量与列数完全匹配
时才有效第二种形式指定了列名和要插入的值:
INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)
这是必须使用的表单,即使有标识类型的 ID 列。
拉吉
【讨论】:
出于某种原因,我总是看到它在使用昂贵的非紧凑版本的 SQL Server / SQL Management Studio 时仍然有效。【参考方案3】:你忘了提到表Clients
有一个列名Title
。第一个查询有效,因为您已经为语句中指定的列显式定义了值。
第二个失败,因为您使用的是Implicit
类型的INSERT
语句。使用该类型的INSERT
时,您必须为表中的所有列指定所有值。由于表中的第一列是ID
,并且是Auto_Increment
ed,所以可以用NULL
代替值。
INSERT INTO Clients VALUES (NULL, '', 'John', '', '', 'Smith', '', 'True')
【讨论】:
【参考方案4】:我认为''代表一个不能插入整数值的空字符串
所以你可以指定 NULL 而不是 ' '
【讨论】:
以上是关于为啥我必须在这个插入语句中包含主键列?的主要内容,如果未能解决你的问题,请参考以下文章