ber*_*d_k 45 sql-server-2005 sql-server identity
我有一个带有标识列的表说:
create table with_id (
id int identity(1,1),
val varchar(30)
);
Run Code Online (Sandbox Code Playgroud)
众所周知,这
select * into copy_from_with_id_1 from with_id;
Run Code Online (Sandbox Code Playgroud)
导致 copy_from_with_id_1 在 id 上也带有标识。
以下堆栈溢出问题提到明确列出所有列。
咱们试试吧
select id, val into copy_from_with_id_2 from with_id;
Run Code Online (Sandbox Code Playgroud)
糟糕,即使在这种情况下 id 也是一个标识列。
我想要的是一张像
create table without_id (
id int,
val varchar(30)
);
Run Code Online (Sandbox Code Playgroud)
Eri*_*elp 59
从网上书籍
new_table 的格式通过评估选择列表中的表达式来确定。new_table 中的列按照选择列表指定的顺序创建。new_table 中的每一列都与选择列表中的相应表达式具有相同的名称、数据类型、可为空性和值。除非在备注部分的“使用标识列”中定义的条件下,否则会转移列的 IDENTITY 属性。
在页面下方:
将现有标识列选入新表时,新列将继承 IDENTITY 属性,除非满足以下条件之一:
- SELECT 语句包含连接、GROUP BY 子句或聚合函数。
- 多个 SELECT 语句使用 UNION 连接。
- 标识列在选择列表中多次列出。
- 标识列是表达式的一部分。
- 标识列来自远程数据源。
如果这些条件中的任何一个为真,则将创建 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;
Run Code Online (Sandbox Code Playgroud)
注释此代码以解释它很重要,以免下次有人查看它时将其删除。
ber*_*d_k 35
受 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;
Run Code Online (Sandbox Code Playgroud)
编辑
甚至可以将其改进为
select * into without_id from with_id
union all
select * from with_id where 1 = 0
;
Run Code Online (Sandbox Code Playgroud)
And*_*y M 14
您可以使用联接一次性创建和填充新表:
SELECT
t.*
INTO
dbo.NewTable
FROM
dbo.TableWithIdentity AS t
LEFT JOIN dbo.TableWithIdentity ON 1 = 0
;
Run Code Online (Sandbox Code Playgroud)
由于1 = 0
条件的原因,右侧将没有匹配项,从而防止左侧行的重复,并且由于这是一个外部联接,左侧行也不会被消除。最后,因为这是一个连接,所以消除了 IDENTITY 属性。
因此,仅选择左侧列将仅生成dbo.TableWithIdentity的精确副本,即仅在数据方面,即删除 IDENTITY 属性。
尽管如此,Max Vernon在评论中提出了一个值得记住的有效观点。如果查看上述查询的执行计划:
您会注意到在执行计划中只提到了一次源表。另一个实例已被优化器消除。
因此,如果优化器可以正确地确定计划中不需要连接的右侧,那么可以合理地期望在 SQL Server 的未来版本中它可能能够确定 IDENTITY 属性不需要也删除了,因为根据查询计划在源行集中不再有另一个 IDENTITY 列。这意味着上述查询可能会在某个时候停止按预期工作。
但是,正如ypercube正确指出的那样??,到目前为止,手册已经明确指出,如果有连接,则不保留 IDENTITY 属性:
将现有标识列选入新表时,新列将继承 IDENTITY 属性,除非 [...] [t] SELECT 语句包含联接。
因此,只要手册不断提及它,我们就可以放心,行为将保持不变。
荣誉对Shaneis和ypercube?用于在聊天中提出相关主题。
小智 7
试试这个代码..
SELECT isnull(Tablename_old.IDENTITYCOL + 0, -1) AS 'New Identity Column'
INTO dbo.TableName_new
FROM dbo.TableName_old
Run Code Online (Sandbox Code Playgroud)
该ISNULL
调用可确保创建的新列具有可NOT NULL
空性。
归档时间: |
|
查看次数: |
62738 次 |
最近记录: |