create table with_id (
id int identity(1,1),
val varchar(30)
);
众所周知,这
在copy_from_with_id_1中也具有ID。
以下堆栈溢出问题提到显式列出所有列。
糟糕,即使在这种情况下,id也是一个标识列。
#1 楼
来自联机丛书new_table的格式通过评估选择列表中的表达式来确定。 new_table中的列是按选择列表指定的顺序创建的。 new_table中的每一列与选择列表中的相应表达式具有相同的名称,数据类型,可空性和值。除非在“备注”部分中的“使用身份列”中定义的条件下,否则将转移列的IDENTITY属性。 br />当将现有的Identity列选择到新表中时,除非满足以下条件之一,否则新列将继承IDENTITY属性:
SELECT语句包含一个联接,GROUP BY子句或聚合函数。
使用UNION连接多个SELECT语句。
在选择列表中多次列出了identity列。
identity列是一部分
Identity列来自远程数据源。
如果满足以下任一条件,则创建该列NOT NULL而不继承IDENTITY属性。如果新表中需要标识列,但该列不可用,或者您想要的种子或增量值与源标识列不同,请使用IDENTITY函数在选择列表中定义该列。请参阅下面的示例部分中的“使用IDENTITY函数创建标识列”。
因此...从理论上讲,您可以摆脱:
select id, val
into copy_from_with_id_2
from with_id
union all
select 0, 'test_row'
where 1 = 0;
注释此代码以对其进行解释很重要,以免下次有人查看时将其删除。
#2 楼
受Erics答案的启发,我发现以下解决方案仅取决于表名,而不使用任何特定的列名:select * into without_id from with_id where 1 = 0
union all
select * from with_id where 1 = 0
;
insert into without_id select * from with_id;
编辑
甚至可以将其改进为
select * into without_id from with_id
union all
select * from with_id where 1 = 0
;
#3 楼
您可以使用联接一口气创建和填充新表:由于这是一个外部联接,因此也不会消除左侧的行。最后,因为这是一个联接,所以消除了IDENTITY属性。因此,仅选择左侧的列,将产生dbo.TableWithIdentity的精确副本,仅在数据方面,即具有IDENTITY属性话虽如此,Max Vernon在评论中提出了一个有效的观点,值得牢记。如果查看上述查询的执行计划:
,您会注意到在执行计划中仅提及了源表一次。优化程序已消除了另一种情况。版本的SQL Server,也许可以弄清楚IDENTITY属性也不需要删除,因为根据查询计划,源行集中不再有另一个IDENTITY列。这意味着上述查询可能会在某些时候停止按预期的方式工作。
但是,正如ypercubeᵀᴹ正确指出的那样,到目前为止,该手册已明确指出如果存在联接,则IDENTITY属性为未保留:
当将现有标识列选择到新表中时,新列将继承IDENTITY属性,除非SELECT语句包含连接。
因此,只要手册不断提及它,我们就可以放心,其行为将保持不变。
对Shaneis和ypercube表示敬意用于在聊天中显示相关主题。
#4 楼
尝试使用此代码。评论
是ISNULL()还是+0?还是两者都需要?
–超立方体ᵀᴹ
16年5月14日在8:12
仅添加0个作品。只要您明确列出列而不使用select *,这是最简单的解决方案。
–伊恩·霍威尔(Ian Horwill)
19年11月21日在12:56
#5 楼
只是为了展示一种不同的方式:您可以使用链接服务器。
SELECT *
INTO without_id
FROM [linked_server].[source_db].dbo.[with_id];
您可以使用以下方法临时创建到本地服务器的链接服务器:点,您将运行
select * into
代码,并引用localserver
链接服务器的四部分名称: :DECLARE @LocalServer SYSNAME
SET @LocalServer = @@SERVERNAME;
EXEC master.dbo.sp_addlinkedserver @server = N'localserver'
, @srvproduct = ''
, @provider = 'SQLNCLI'
, @datasrc = @LocalServer;
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'localserver'
, @useself = N'True'
, @locallogin = NULL
, @rmtuser = NULL
, @rmtpassword = NULL;
或者,您可以使用
localserver
语法SELECT *
INTO without_id
FROM [localserver].[source_db].dbo.[with_id];
#6 楼
如果select语句包含联接,则不会传输identity属性,因此select a.* into without_id from with_id a inner join with_id b on 1 = 0;
也将给出所需的行为(复制的
id
列不保留IDENTITY
属性,但是,它的副作用是根本不复制任何行(与其他方法一样),因此您需要执行以下操作:insert into without_id select * from with_id;
(感谢AakashM!)
#7 楼
最简单的方法是使列成为表达式的一部分。示例:
如果表dbo.Employee在ID列上具有标识,则在下面的示例中,临时表#t在ID列上也具有IDENTITY。
--temp table has IDENTITY
select ID, Name
into #t
from dbo.Employee
对此进行更改以将表达式应用于ID,您#t将不再在ID列上具有IDENTITY。在这种情况下,我们对ID列进行简单的添加。
--no IDENTITY
select ID = ID + 0, Name
into #t
from dbo.Employee
其他数据类型的表达式的其他示例可能包括:convert(),字符串连接或Isnull()
评论
从docs.microsoft.com/zh-cn/sql/t-sql/queries/…:“将现有标识列选择到新表中时,除非满足以下条件之一,否则新列将继承IDENTITY属性。 …identity列是表达式的一部分…将该列创建为NOT NULL而不是继承IDENTITY属性。”
–曼戈
19年8月19日在22:13
#8 楼
有时,您想从不知道(或不在乎)该表是否是使用IDENTITY创建的表中插入。它甚至可能不是您正在使用的整数列。在这种情况下,下面的方法将起作用:使它不能为空。 TOP(0)将创建一个空表,然后您可以使用该表将选定的行插入其中。如果需要,还可以在插入数据之前压缩表。#9 楼
select convert(int, id) as id, val
into copy_from_with_id_without_id
from with_id;
将删除身份。
缺点是
id
可以为空,但您可以添加该约束。评论
您可以使用ISNULL来解决此问题。
–埃里克·达林(Erik Darling)
17-10-15在16:21
#10 楼
请尝试以下查询:我发现此查询正常工作。这将选择没有标识= 1的列中的数据DECLARE @Temp NVARCHAR(MAX);
DECLARE @SQL NVARCHAR(MAX);
SET @Temp = '';
SELECT @Temp = @Temp + COLUMN_NAME + ', ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='Person' AND columnProperty(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') != 1
SET @SQL = 'SELECT ' + SUBSTRING(@Temp, 0, LEN(@Temp)) +' FROM [Person]';
EXECUTE SP_EXECUTESQL @SQL;
您可以从sys.columns表中获取列名详细信息
尝试以下查询:
评论
这不是问题所在。
–必须
20-09-22在19:24
为了明确起见,问题在于要复制所有列,但要使身份列成为新表中的常规(非身份)列。
– Andriy M
20/09/22在20:56
#11 楼
你不知道select * into
保留身份。评论
问题中没有要求使用*。
–马丁·史密斯
16年5月12日在16:49
正如其他答案指出的那样,身份属性并不总是被保留。
–超立方体ᵀᴹ
16年5月12日在17:20
评论
JOIN(SELECT 1)AS dummy ON 1 = 1也可以工作吗?
–超立方体ᵀᴹ
18-2-28在22:29
交叉联接(选择1),内部联接(选择1)打开1 = 1,左联接(选择1)打开1 = 0或打开1 = 1 –没有一个会剥夺身份。似乎它必须是已声明或创建的对象。
– Andriy M
18 Mar 1 '18 at 10:28