Meh*_*ili 24 c# t-sql sql-server
我需要从中获取下一个身份值SQL Server.
我用这个代码:
SELECT IDENT_CURRENT('table_name') + 1
Run Code Online (Sandbox Code Playgroud)
这是正确的,但是当它table_name为空(并且下一个标识值为"1")时返回"2"但结果为"1"
Gra*_*ICA 11
我想你会想要另一种方法来计算下一个可用值(比如将列设置为自动递增).
从IDENT_CURRENT文档中,关于空表:
当IDENT_CURRENT值为NULL(因为表从未包含行或已被截断)时,IDENT_CURRENT函数返回种子值.
它甚至看起来都不可靠,特别是如果你最终设计的应用程序有多个人同时写入桌面.
请谨慎使用IDENT_CURRENT来预测下一个生成的标识值.由于其他会话执行插入,实际生成的值可能与IDENT_CURRENT加IDENT_INCR不同.
小智 6
如果您的表将为空,则此查询将完美地运行.
SELECT
CASE
WHEN (SELECT
COUNT(1)
FROM tablename) = 0 THEN 1
ELSE IDENT_CURRENT('tablename') + 1
END AS Current_Identity;
Run Code Online (Sandbox Code Playgroud)
小智 6
SELECT isnull(IDENT_CURRENT('emp') + IDENT_INCR('emp'),1)
Run Code Online (Sandbox Code Playgroud)
我知道已经有一个答案,但让我感到恼火的是,我所有的搜索都沿着“获取下一个身份 SQL 服务器”提出了不稳定的解决方案(例如仅选择当前身份值并添加 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
您可能希望将所有这些都封装在一个存储过程中,特别是因为该DBCC语句需要提升访问权限,并且您可能不希望每个人都拥有这种访问权限。
不像 那样优雅NEXT VALUE FOR,但它应该是可靠的。请注意,2如果表中没有行,您将获得第一个值,但如果您打算始终使用此方法来获取下一个身份,则可以将身份设置为 at0而不是1(with IDENTITY (0, 1)) 如果您死机了从 1 开始。
我不能代表问题海报,但“领域驱动设计”一书和“官方”DDD 示例使用这种技术(或至少暗示它)作为强制实体始终具有有效标识符的一种方式。如果您的实体在被编入数据库之前有一个伪造的标识符(如-1或default(int)或null)INSERT,则它可能会泄漏持久性问题。
我倾向于同意其他海报,认为这不是正确的方法,但对某些情况来说这可能很方便.几个帖子问为什么要这样做,让我举一个例子,它对我来说很方便,以及如何以及为什么.
我正在实施一个比特币节点.我希望区块链存储在SQL数据库中.每个块都是从其他节点和矿工的网络接收的.你可以在其他地方找到的细节.
当接收块时,它包含一个头,任意数量的事务和每个事务的任意数量的输入和输出.我的数据库中有4个表 - 你猜对了 - 表头,事务表,输入表和输出表.事务,输入和输出表中的每一行都与ID相互链接到标题行.
一些块包含数千个事务.一些交易包括投入和/或产出.我需要将它们存储在DB中,方便调用C#而不影响完整性(所有ID都链接起来)并具有良好的性能 - 当接近10000次提交时,我无法通过逐行提交来获取它们.
相反,我绝对确保在操作期间在C#中同步锁定我的数据库对象(我也不必担心其他进程也访问数据库),所以我可以方便地在所有4个表上执行IDENT_CURRENT,返回来自存储过程的值,填充4 List <DBTableRow>中的近10000行,同时递增ID并调用SqlBulkCopy.WriteToServer方法并设置选项SqlBulkCopyOptions.KeepIdentity,然后将其全部发送到4个简单调用中,每个表集一个.
性能提升(在4-5岁的中档笔记本电脑上)从大约60-90秒下降到真正大块的2-3秒,所以我很高兴了解IDENT_CURRENT().
解决方案可能并不优雅,可能不会出书,但它既方便又简单.我知道,还有其他方法可以实现这一目标,但这只是直截了当,需要几个小时才能实现.只是确保您没有并发问题.
| 归档时间: |
|
| 查看次数: |
34705 次 |
| 最近记录: |