SQL Server标识功能是否可重现

时间:2018-03-23 15:19:39

标签: sql sql-server identity-column

我想使用

将标识列添加到目前没有ID列的表中
Alter Table Names
    Add Id_new Int Identity(1, 1)
编辑:我的问题似乎导致了一些混乱,所以我试着澄清: 我们从客户那里得到了几千张表进行分析。他们中的大多数没有和ID列。 我们从客户端加载表,但不知道里面是什么。 为了进一步分析,我们想要添加自己的ID列。

可能会发生,编辑过的表可能会被意外删除。 发生这种情况时,我们需要能够重新加载数据,再次添加ID列,ID列必须与我们第一次加载数据时的顺序完全相同。 否则,如果我们在下游分析中引用ID,我们将引用与之前不同的行。

那么:是不是这样,添加到表中的ID号始终是相同的顺序,因为表中的数据是相同的?

备注:我和同事一起讨论了我们可以在所有列上使用order by子句的可能性。这将创造我们想要的东西。但是,我们有数千个表,所以这将是一个非常痛苦。数据是我们要为客户端分析的转储。所以问题是,如果有一种更容易,可重现的方法来添加和ID到所有表中的所有行。

3 个答案:

答案 0 :(得分:1)

问题是为什么要重新添加Add Id_new Int Identity(1, 1)

未订购表格。该命令无法保证重复。

如果您希望重复,您的数据需要提供自己的PK。

如果您先创建身份,然后插入身份将在插入顺序中,但它可能有间隙。

如果所有行都产生了唯一的排序,那么这应该有效

select col1, col2, col3 
     , row_number() over (order by col1, col2, col3) as rn 
 from table;

如果要重新加载表,则可以截断。

答案 1 :(得分:1)

IDENTITY为特定表生成递增数字。您无法确保添加到不同表中的行将获得相同的数字。无论如何,这不是IDENTITY的目的。

SQL Server可以为这种情况生成sequence numbers。您可以使用SEQUENCE来生成可在多个表中使用的递增数字,甚至可以确保表中的唯一数字

如何使用序列取决于您插入数据的方式。最简单的方法是获取一个新值并使用它在多个表中插入行:

SET @myID = NEXT VALUE FOR Test.CountBy1 ; 
INSERT INTO Table1 (ID,....) VALUES(@myID,....);

但是在批量导入方案中这并不是很有帮助。

另一种选择是使用sp_sequence_get_range存储过程保留整个数字范围。您可以要求例如10个号码,该功能将返回起始号码,并确保不会为其他任何人生成接下来的10个号码:

DECLARE @range_first_value sql_variant ,   
        @range_first_value_output sql_variant ;  

EXEC sp_sequence_get_range  
@sequence_name = N'RangeSeq'  
, @range_size = 10  
, @range_first_value = @range_first_value_output OUTPUT ;  

SELECT @range_first_value_output AS FirstNumber ; 

这可以在ETL脚本或代码中使用,以生成递增的数字并将它们分配给行。

在表格中生成唯一数字要容易得多。只需使用NEXT VALUE FOR ...作为ID列的默认值

答案 2 :(得分:0)

这是一项复杂的任务,可以通过多种方式解决。我将尝试解释如何解决它。

第1步: 为所有表生成脚本:how do i generate scripts for all tables with single stroke in sql server 2000

第2步: 将Identity列添加到所有表。为此,我们需要编辑在第1步中生成的脚本,并将) ON [PRIMARY]的所有实例替换为, IdCol int IDENTITY(1,1)) ON [PRIMARY]

第3步: 我们需要更改表名,使其与原始名称不同。将所有].[替换为].[temp1234_

第4步: 运行脚本。这将创建所有表的空副本,并将IdCol作为标识列。

第5步: 为所有表生成INSERT脚本。运行以下查询:

select 'INSERT INTO ['+name+'] SELECT * from ['+REPLACE(name, 'temp1234_', '')+'] order by column_name' 
from sys.all_objects where name like 'temp1234_%'

这将为您提供每个表的INSERT脚本的行列表。将column_name替换为可用作order by子句的列的名称。如果列的名称因表而异,则必须为每个表指定正确的列名称。

第6步: 复制所有行,运行,等待完成,检查结果。

正如其他人已经说过的那样 - 无法控制Identity为每一行分配的值,因此要控制您需要将数据重新插入到新表中。

IF 您的表已经拥有了您希望用作标识的列,而无需重新分配值,可能有办法执行此操作。如果是这样,请告诉我。