如何在 SQL Server 表中插入 auto_increment 键

问题描述 投票:0回答:6

我想将行插入到具有唯一的、非自动递增主键的表中。

是否有一个原生 SQL 函数来评估最后一个键并递增它,或者我是否必须分两步完成:

key = select max(primary.key) + 1

INSERT INTO dbo.TABLE (primary.key, field1, fiels2) VALUES (KEY, value1, value2)
sql sql-server
6个回答
32
投票

由于它是自动生成的,因此无需提供它:

INSERT INTO bo.TABLE (field1, fiels2) VALUES (value1, value2)

更新:如果您的专栏是

IDENTITY
专栏,那么这将起作用。

要向标识列提供显式值,您必须执行以下操作:

set identity_insert bo.TABLE on

INSERT INTO bo.TABLE (primary_key, field1, fiels2) VALUES ((SELECT ISNULL(MAX(id) + 1, 0) FROM bo.Table), value1, value2)

set identity_insert bo.TABLE off

但是没有令人信服的理由这样做。


14
投票

从您整个评论来看,表上的主键不是标识列。

如果您的 SQL Server 版本是 SQL 2012,您应该查看序列:http://msdn.microsoft.com/en-us/library/ff878091.aspx

在其他版本中,您需要使用主键列的 IDENTITY 属性 (http://msdn.microsoft.com/en-us/library/aa933196(v=sql.80).aspx) 重新创建表,或者使用两步走的方法。

如果您采用两步方法,您需要确保并发运行的插入最终不会使用相同的新值。最简单的方法是将选择和插入组合成一个值并使用可序列化表提示:

CREATE TABLE dbo.Tbl1(id INT PRIMARY KEY, val1 INT, val2 INT)

INSERT INTO dbo.Tbl1(id, val1, val2)
VALUES((SELECT ISNULL(MAX(id)+1,0) FROM dbo.Tbl1 WITH(SERIALIZABLE, UPDLOCK)), 42, 47);

SELECT * FROM dbo.Tbl1;

4
投票

在我看来,最好的答案是修复你的表,使 PK 列成为身份列。 (请参阅我对 Sebastian Meine 的答案的评论,了解为什么您当前选择的答案不是最好的。)使现有 PK 成为标识列的唯一方法是交换表。大致:

BEGIN TRAN;
-- Rename all constraints in original table
EXEC sp_rename 'dbo.YourOriginalTable.PK_ConstraintName', 'PKConstraint_Backup';
EXEC sp_rename 'dbo.YourOriginalTable.OtherConstraintName', 'OtherConstraintName_Backup';
CREATE TABLE dbo.WorkTable (
    YourPKColumn int identity(1, 1) NOT NULL -- your PK converted to identity
    CONSTRAINT PK_YourOriginalTableConstraintName PRIMARY KEY CLUSTERED,
    AllOtherColumns -- all your other columns exactly as in the original table
);

SET IDENTITY_INSERT dbo.WorkTable ON;
INSERT dbo.WorkTable (YourPKColumn, AllOtherColumns)
SELECT YourPKColumn, AllOtherColumns
FROM dbo.YourOriginalTable WITH (TABLOCKX, HOLDLOCK);

SET IDENTITY_INSERT dbo.WorkTable OFF;

-- Drop all FK constraints from other tables pointing to your table
ALTER TABLE dbo.TableWithFK_1
DROP CONSTRAINT FK_TableWithFK_1_YourOriginalTableSomethingID;

-- Swap out the tables
EXEC sp_rename 'dbo.YourOriginalTable', 'YourOriginalTableBackup';
EXEC sp_rename 'dbo.WorkTable', 'YourOriginalTable';

-- If you didn't add them in the WorkTable creation,
-- add all other removed or needed constraints creation
ALTER TABLE dbo.YourOriginalTable
ADD CONSTRAINT OriginalConstraint (OriginalConstraintColumns);
-- Add back FK constraints from other tables to this one.
COMMIT TRAN;

您现在有一个表,其中包含一个带有集群 PK 的标识列。你可以插入它没有问题。不再有并发问题和愚蠢的

SELECT Max() + 1
垃圾,而且很容易出错


2
投票

插入一条记录:

我这样做只是为了向具有非自动递增主键的表中插入一行:

DECLARE @myKey int
SET @myKey = (SELECT  ISNULL(MAX(primaryKey),0) FROM dbo.myTable)

INSERT INTO dbo.myTABLE (primaryKey, field1, fiels2) VALUES (@myKey + 1, value1, value2)

插入多条记录:

在另一种情况下,我需要复制表中的多条记录。为此,我使用了来自 SELECT 结果的 INSERT。 我的目的是从 myTable 中复制一些满足特定条件的记录。 但我需要弄清楚如何使用唯一的主键复制表中的记录,而不重复 ID。 我是这样解决的:

DECLARE @myKey int 
SET @myKey = (SELECT  ISNULL(MAX(primaryKey),0) FROM dbo.myTable)

INSERT INTO dbo.myTABLE (primaryKey, field1, fiels2) 
SELECT 
     (primaryKey + @myKey, value1, value2) 
        FROM dbo.myTable 
        WHERE value2 = especific_Condition

ID 中存在一些间隙,但我强制执行主键唯一性。


0
投票

如果 Emp 不存在则创建表 ( eid int(10) 非空主键自动增量, 名称 varchar(45) 不为空, 年龄 int(5) 默认 20, 工资整数(5) ) 插入 emp 值(102,'Ranjan',21,450000);

然后尝试下面的sql查询。它将自动将 eid 增加到下一个数字。

插入emp(姓名,薪水)值('Lisma',118500);

从员工中选择*;


0
投票
CREATE TABLE dbo.Tbl1(id INT PRIMARY KEY, val1 INT, val2 INT)
INSERT INTO dbo.Tbl1(id, val1, val2)
SELECT 
(SELECT ISNULL(MAX(id),0) FROM dbo.Tbl1 WITH(SERIALIZABLE, UPDLOCK)+ROW_NUMBER()over(order by (select 0))
, val1
, val2
FROM dbo.Tbl2;
© www.soinside.com 2019 - 2024. All rights reserved.