Cannot add identity column, using the SELECT INTO statement, to table 'dbo.NewUsers', which already has column 'UserID' that inherits the identity property.
SELECT INTO 语句创建一个新表并用 SELECT 语句的结果集填充它。SELECT INTO 可用于将多个表或视图中的数据组合到一个表中。它还可用于创建包含从链接服务器中选择的数据的新表。 |
新表的结构由选择列表中表达式的属性定义。当计算列包含在选择列表中时,新表中的对应列不是计算列。新列中的值是在执行 SELECT INTO 时计算的值。
如果源表中的列是 IDENTITY 列,则新表将在创建新表时继承该列的 IDENTITY 属性。为了说明,以下脚本将基于 [dbo].[Users] 表创建一个新表,并且新表将继承 [UserID] 列的 IDENTITY 属性:
CREATE TABLE [dbo].[Users] ( [UserID] INT IDENTITY(1, 1) NOT NULL, [UserName] VARCHAR(50) NOT NULL, [FirstName] VARCHAR(100) NOT NULL, [LastName] VARCHAR(100) NOT NULL ) GO SELECT * INTO [dbo].[Users2] FROM [dbo].[Users] GO
如果要将新列定义为 SELECT INTO 语句创建的新表的 IDENTITY 列,则可以使用 IDENTITY 函数。IDENTITY 函数仅在带有 INTO <table> 子句的 SELECT 语句中用于将标识列插入到新表中。虽然相似,但 IDENTITY 函数不是用于 CREATE TABLE 和 ALTER TABLE 语句的 IDENTITY 属性。
IDENTITY 函数的语法如下:
IDENTITY( <data_type> [, <seed>, <increment> ] ) AS <column_name>
<data_type> 参数是标识列的数据类型。标识列的有效数据类型是整数数据类型类别的任何数据类型,位数据类型或十进制数据类型除外。<seed> 参数是要分配给表中第一行的整数值。
不幸的是,使用带有 SELECT INTO 语句的 IDENTITY 函数来创建源表已经包含 IDENTITY 列的新表会产生错误,从以下语句可以看出:
SELECT IDENTITY(INT, 1, 1) AS [NewID], * INTO [dbo].[NewUsers] FROM [dbo].[Users] ORDER BY [UserName] Msg 8108, Level 16, State 1, Line 1 Cannot add identity column, using the SELECT INTO statement, to table 'dbo.NewUsers', which already has column 'UserID' that inherits the identity property.
解决方案/解决方法:
通过从源表中删除列的 IDENTITY 属性可以轻松克服此错误,以便由 IDENTITY 函数创建的新列可以具有新表的 IDENTITY 属性。在 SELECT INTO 语句中使用时,有几种方法可以删除列的 IDENTITY 属性。
第一种方法是使用 IDENTITY 列执行数学函数,从以下脚本可以看出:
SELECT IDENTITY(INT, 1, 1) AS [NewID], [UserID] * 1 AS [OldUserID], [UserName], [FirstName], [LastName] INTO [dbo].[NewUsers] FROM [dbo].[Users] SELECT IDENTITY(INT, 1, 1) AS [NewID], [UserID] + 0 AS [OldUserID], [UserName], [FirstName], [LastName] INTO [dbo].[NewUsers] FROM [dbo].[Users]
有趣的是,如果使用 SELECT INTO 语句创建了一个新表,并且将两个表而不是一个表用作源表并且两个表都包含 IDENTITY 列,则不会生成此错误。新表不继承两个表中 IDENTITY 列的 IDENTITY 属性。为了说明,以下脚本使用 SELECT INTO 语句创建一个新表,其中连接了 2 个表,并且两个表都包含 IDENTITY 列:
CREATE TABLE [dbo].[Customer] ( [CustomerID] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, [FirstName] VARCHAR(50), [LastName] VARCHAR(50) ) CREATE TABLE [dbo].[CustomerAddress] ( [CustomerAddressID] INT IDENTITY(1, 1) NOT NULL, [CustomerID] INT NOT NULL REFERENCES [dbo].[Customer] ( [CustomerID] ), [Address1] VARCHAR(100) NOT NULL, [Address2] VARCHAR(100) NULL, [City] VARCHAR(50) NOT NULL, [State] CHAR(2) NOT NULL, [ZIP] VARCHAR(10) NOT NULL ) SELECT A.[CustomerID], A.[FirstName], A.[LastName], B.[CustomerAddressID], B.[Address1], B.[Address2], B.[City], B.[State], B.[ZIP] INTO [dbo].[AllCustomerAddresses] FROM [dbo].[Customer] A INNER JOIN [dbo].[CustomerAddress] B ON A.[CustomerID] = B.[CustomerID]
结果表将不会继承 [CustomerID] 和 [CustomerAddressID] 的 IDENTITY 属性,并且新表将没有任何 IDENTITY 列。鉴于此,可以使用 IDENTITY 函数为新表生成 IDENTITY 列。
SELECT IDENTITY(INT, 1, 1) AS [AllCompanyAddressesID], A.[CustomerID], A.[FirstName], A.[LastName], B.[CustomerAddressID], B.[Address1], B.[Address2], B.[City], B.[State], B.[ZIP] INTO [dbo].[AllCompanyAddresses] FROM [dbo].[Customer] A INNER JOIN [dbo].[CustomerAddress] B ON A.[CustomerID] = B.[CustomerID] GO
在这种情况下,避免此错误消息(消息 8108)的替代方法是在使用 SELECT INTO 语句时对源表执行 JOIN 以创建新表。如果只有一个表可用并且它不能与任何其他表连接,则它可以连接到自身并仍然生成所需的结果,如下所示:
SELECT IDENTITY(INT, 1, 1) AS [NewID], A.[UserID] AS [OldUserID], A.[UserName], A.[FirstName], A.[LastName] INTO [dbo].[NewUsers] FROM [dbo].[Users] A INNER JOIN [dbo].[Users] B ON A.[UserID] = B.[UserID]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)