Sql 插入到具有序列号的表中

Sql 插入到具有序列号的表中,sql,sql-server,Sql,Sql Server,如果我有以下资料: Begin transaction numberOfRecords = select count from table where foreignKey = "some value" Insert into table (set SequenceNumber = numberOfRecords + 1) End Transaction 如果有多个用户正在执行上述代码,那么每个插入都会有一个唯一的递增数吗 换句话说,begin事务队列是否将其他事务(甚至是读取)排队,

如果我有以下资料:

Begin transaction
 numberOfRecords = select count from table where foreignKey = "some value" 

 Insert into table (set SequenceNumber = numberOfRecords + 1)
End Transaction
如果有多个用户正在执行上述代码,那么每个插入都会有一个唯一的递增数吗

换句话说,begin事务队列是否将其他事务(甚至是读取)排队,以便每个插入都具有正确的序列号?或者我需要Insert into..Select语句来实现我想要的吗


谢谢。

不,事务不排队命令,它不像锁


通常,您希望使用标识列,但在某些情况下,当您希望生成无间隙的SequenceNumber时,您需要在SequenceNumber列上使用具有唯一约束的上述代码,并准备在提交事务引发异常时重试。

否,事务不排队命令,它不像锁


通常,您希望使用标识列,但在某些情况下,当您希望生成SequenceNumber而没有间隙时,您需要在SequenceNumber列上使用具有唯一约束的上述代码,并准备在提交事务引发异常时重试。

我曾经使用SQL DB作为大规模数据导出的记录器,为了获得顺序标识,我创建了一个on-insert触发器,处理下一个数字的发出。 对我来说效果很好,但是它只是一个用户数据库,所以不确定多个用户是否有任何问题以及我做了什么

现在我已经重读了这个问题,这可能不是你想要的,但我认为你也可以为一个选择做一个触发

USE [ExportLog]
GO

/****** Object:  Trigger [dbo].[Migration_Update_Event_Date]    Script Date: 02/10/2011                17:06:11 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Migration_Update_LogState]
ON [dbo].[MigrationLog] FOR INSERT NOT FOR REPLICATION
AS
UPDATE [MIGRATION-DATA].dbo.MIGRATIONSTATE
SET LASTPROCESSID = ID
WHERE MACHINENAME IN (SELECT MACHINENAME FROM INSERTED)

GO

我曾经使用SQL DB作为大规模数据导出的记录器,为了获得顺序标识,我在插入时创建了一个处理下一个数字的触发器。 对我来说效果很好,但是它只是一个用户数据库,所以不确定多个用户是否有任何问题以及我做了什么

现在我已经重读了这个问题,这可能不是你想要的,但我认为你也可以为一个选择做一个触发

USE [ExportLog]
GO

/****** Object:  Trigger [dbo].[Migration_Update_Event_Date]    Script Date: 02/10/2011                17:06:11 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Migration_Update_LogState]
ON [dbo].[MigrationLog] FOR INSERT NOT FOR REPLICATION
AS
UPDATE [MIGRATION-DATA].dbo.MIGRATIONSTATE
SET LASTPROCESSID = ID
WHERE MACHINENAME IN (SELECT MACHINENAME FROM INSERTED)

GO

如果您想在unique中插入记录,那么首先要按顺序创建,然后记录应该按顺序插入。如

创建sequence seq_num

现在使用seq_num插入RCORD

insert into <table name>(col1) values(seq_num.nextval);

如果您想在unique中插入记录,那么首先您要在sequence上创建,然后记录应该是insert-thorugh-sequence.like

创建sequence seq_num

现在使用seq_num插入RCORD

insert into <table name>(col1) values(seq_num.nextval);

您需要将事务隔离级别设置为提供正确隔离级别的级别。在代码中,两个进程可以执行第一行,然后执行第二行。两者都将插入相同的值

将隔离级别设置为serializable,并使用UPDLOCK执行select语句。这将减少系统中的并发性,但它是安全的


其他策略也是可能的,但它们的实施和测试更耗时

您需要将事务隔离级别设置为提供正确隔离级别的级别。在代码中,两个进程可以执行第一行,然后执行第二行。两者都将插入相同的值

将隔离级别设置为serializable,并使用UPDLOCK执行select语句。这将减少系统中的并发性,但它是安全的


其他策略也是可能的,但它们的实施和测试更耗时

否,具有默认SQL Server隔离级别READ COMMITTED的事务是不够的。将它放入一个INSERT…SELECT语句也无法修复它。您基本上有两个选项来解决此问题:

选项1:将隔离级别设置为可序列化:将事务隔离级别设置为可序列化。这将确保来自两个不同用户的事务按顺序发生。然而,如果许多这样的事务同时发生,这可能会造成死锁

选项2:在事务开始时以独占方式锁定表,使用TABLOCKX从表中选择*,HOLDLOCK,其中1=0。请注意,如果频繁使用表,这可能会影响性能

在我对以下问题的回答中,对这两种方法进行了详细分析:


否,具有默认SQL Server隔离级别READ COMMITTED的事务是不够的。将它放入一个INSERT…SELECT语句也无法修复它。您基本上有两个选项来解决此问题:

选项1:将隔离级别设置为可序列化:将事务隔离级别设置为可序列化。这将确保来自两个不同用户的事务按顺序发生。然而,如果许多这样的事务同时发生,这可能会造成死锁

选项2:在事务开始时以独占方式锁定表,使用TABLOCKX从表中选择*,HOLDLOCK,其中1=0。请注意,如果频繁使用表,这可能会影响性能

在我对以下问题的回答中,对这两种方法进行了详细分析:

谢谢你的回复。

如果我只是在事务中执行Insert而不是selects,那么也会Insert…Select作为一条语句来执行我想要的操作吗?很抱歉,上面的psuedo代码从foreignKey=somevalue的表中漏掉了numberOfRecords=Select count,在这种情况下identity列可以工作吗?@JD:No.就并发性而言,选择+插入并插入…选择行为类似。如@Heinzi所写,行为取决于事务隔离级别,但对于默认级别READ Committed,答案是正确的。感谢您的回复。如果我只是在事务中执行Insert而不是selects,那么也会Insert…Select作为一条语句来执行我想要的操作吗?很抱歉,上面的psuedo代码从foreignKey=somevalue的表中漏掉了numberOfRecords=Select count,在这种情况下identity列可以工作吗?@JD:No.就并发性而言,选择+插入并插入…选择行为类似。如@Heinzi所写,行为取决于事务隔离级别,但对于默认级别READ Committed,答案是正确的。我有点不明白您在这里想要实现什么。您正在尝试创建自动递增的ID列吗?你能不能只用一个标识列?Count是一个列的特殊名称。如果您计划使用表中的行数,那么您不希望删除任何行。很抱歉,它被认为是伪代码,但有点太接近sql。我有点搞不清楚您在这里试图实现什么。您正在尝试创建自动递增的ID列吗?你能不能只用一个标识列?Count是一个列的特殊名称。如果您计划使用表中的行数,那么您不希望删除任何行。很抱歉,它被认为是伪代码,但有点太接近sql。这不是唯一的Oracle吗?认为sql server不受支持sequences@Charleh-SQL Server 2012有。这不只是Oracle吗?认为sql server不受支持sequences@Charleh-SQL Server 2012有。我认为基本问题与此相同。它只是塞进同一条语句中的两行。不确定它们是原子的。我认为基本问题在这里是一样的。它只是塞进同一条语句中的两行。不确定它们是原子的。那么乐观锁定呢,有没有一种方法可以因为乐观锁定而抛出任何并发事务,然后重试?@JD:乐观锁定通常在行级别使用某种版本号。我不确定它在这里如何应用。您能详细说明一下吗?关于乐观锁定,有没有一种方法可以将任何由于乐观锁定而导致的并发事务抛出,然后重试?@JD:乐观锁定通常在行级别使用某种版本号。我不确定它在这里如何应用。你能详细说明一下吗?