我需要从SQL Server
中获取下一个身份值。
我使用这段代码:
SELECT IDENT_CURRENT('table_name') + 1
这是正确的,但当 table_name
为空(且下一个标识值为“1”)时返回了“2”,但结果应该是“1”
我需要从SQL Server
中获取下一个身份值。
我使用这段代码:
SELECT IDENT_CURRENT('table_name') + 1
这是正确的,但当 table_name
为空(且下一个标识值为“1”)时返回了“2”,但结果应该是“1”
我认为你需要寻找一种替代方法来计算下一个可用值(例如将列设置为自动增量)。
从IDENT_CURRENT文档中可以看到,对于空表:
当IDENT_CURRENT值为NULL(因为该表从未包含过行或已被截断),IDENT_CURRENT函数将返回种子值。
这甚至似乎并不是很可靠,特别是如果你最终设计的应用程序有多个人同时写入该表。
谨慎使用IDENT_CURRENT来预测下一个生成的标识值。由于其他会话执行的插入操作,实际生成的值可能与IDENT_CURRENT加上IDENT_INCR不同。
IDENTITY
工作的方式。 - marc_s如果您的表为空,则此查询将完美运行。
SELECT
CASE
WHEN (SELECT
COUNT(1)
FROM tablename) = 0 THEN 1
ELSE IDENT_CURRENT('tablename') + 1
END AS Current_Identity;
我知道已经有一个答案,但让我感到不爽的是,所有搜索"获取下一个SQL Server身份认证"的结果都是靠不住的解决方案(比如仅选择当前身份认证值并加1)或者说 "无法可靠地完成"。
实际上有几种方法可以做到这一点。
CREATE SEQUENCE dbo.seq_FooId START WITH 1 INCREMENT BY 1
GO
CREATE TABLE dbo.Foos (
FooId int NOT NULL
DEFAULT (NEXT VALUE FOR dbo.seq_FooId)
PRIMARY KEY CLUSTERED
)
GO
// Get the next identity before an insert
DECLARE @next_id = NEXT VALUE FOR dbo.seq_FooId
在SQL Server 2012中,出现了SEQUENCE对象。每次调用“NEXT VALUE FOR”时,序列都会递增,因此您不必担心并发问题。
CREATE TABLE dbo.Foos (
FooId int NOT NULL
IDENTITY (1, 1)
PRIMARY KEY CLUSTERED
)
GO
// Get the next identity before an insert
BEGIN TRANSACTION
SELECT TOP 1 1 FROM dbo.Foos WITH (TABLOCKX, HOLDLOCK)
DECLARE @next_id int = IDENT_CURRENT('dbo.Foos') + IDENT_INCR('dbo.Foos');
DBCC CHECKIDENT('dbo.Foos', RESEED, @next_id)
COMMIT TRANSACTION
你很可能想要将所有这些内容封装在存储过程中,特别是因为DBCC
语句需要提升访问权限,你可能不希望每个人都拥有这种访问权限。
这并不像NEXT VALUE FOR
那么优雅,但应该是可靠的。请注意,如果表中没有行,则第一个值为2
,但如果您打算始终使用此方法来获取下一个身份标识,则可以在IDENTITY(0,1)
中将标识初始化为0
而不是1
,如果您一定要从1开始,请忽略此建议。
我无法代表问题的发布者发言,但书籍“领域驱动设计”和官方DDD示例使用此技术(或至少暗示了这种技术)来强制实体始终具有有效的标识符。如果您的实体具有虚假的标识符(例如-1
或default(int)
或null
),直到它被INSERT
到数据库中,它可能会泄漏持久化问题。
SELECT isnull(IDENT_CURRENT('emp') + IDENT_INCR('emp'),1)
DECLARE @nextId INTEGER = IDENT_CURRENT('myTable')
IF (SELECT COUNT(*) FROM myTable) > 0
OR @nextId > 1
SET @nextId += 1
我曾经这样使用它来计算下一个ID,当表为空时也能很好地工作。
select isnull(max(ID),0)+1 from yourTable
我可以提供另一种情况,知道下一个值会很有用。 我在Excel中使用线路中的数据,例如:
A B C X1 X2 Y1 Y2 Z1 Z2我想将A B C放入一个数据库表中,并在另一个表中使用该记录的新主键来放置X1和X2,然后是Y1和Y2,然后是Z1和Z2。 因此,这一行将在第一个表中生成一条记录:
xxx A B C并在第二个表中生成三个记录
yyy xxx X1 X2
yyy+1 xxx Y1 Y2
yyy+2 xxx Z1 Z3
如果我能在开始过程之前确定xxx,我可以为正在处理的每条记录递增它。 我也犯了一个错误,就是找到最高值M并假设M + 1将是下一个值。 这不起作用是因为一些上传由于错误而未完成,事务被回滚,但已分配索引的PK不会被重用。 删除最高值PK记录需要手动删除,否则会导致类似问题。
我的简单解决方案是编写一个 SP,在上传第一个案例后获取 PK 的最大值。
CREATE PROCEDURE [MIRR].[GetLast_CasesIndexID]
@GroupNumber as int Output
AS
BEGIN
SELECT @GroupNumber = max(CasesIndexID)
FROM MIRR.Cases
END
GO
INSERT INTO #A(Col1)
OUTPUT inserted.IdentityColumn, inserted.Col1
INTO #B (DestinationPrimaryKey, SourceRowId)
SELECT SourceRowID FROM #ThingToRecord
SELECT DestinationPrimaryKey, SourceRowId
FROM #B
identity
值。 - marc_s