I 认为我遇到的问题是并发问题,但我想我不太了解SQL Server事务,以确定要做什么。外键约束冲突并发问题
我有插入新行到一个表中的存储过程,然后使用由INSERT
创建的ID创建另一个表中的记录,这对RID一个外键约束:
INSERT INTO tbl_Registrations ...
DECLARE @RID int;
--get newly-created registration ID
SET @RID=(SELECT MAX(RID) FROM tbl_Registrations WHERE ...);
INSERT INTO tbl_RegistrationCertificates VALUES (@RID, 9);
这个存储过程是从网站上的用户交互中调用的,每次我测试它时,它都可以正常工作。然而,每过一段时间,我会从我们的错误处理一封电子邮件,但以下情况除外:
System.Data.SqlClient.SqlException (0x80131904): The INSERT statement conflicted with the FOREIGN KEY constraint "FK_tbl_RegistrationCertificates_tbl_Registrations".
The conflict occurred in ... table "dbo.tbl_Registrations", column 'RID'.
The statement has been terminated.
但是,无论是我的用户在点击“更新”按钮,持续,直到他们看到变化,或者即使消息显示The statement has been terminated
,交易仍在进行,因为使用来自电子邮件的其他信息,我可以看到这两个表已实际更新。
我知道我不给一吨的信息在这里,但我无法找到答案的大问题是:
- 是否在声明的末尾分号T中做任何事 - SQL?我只注意到在INSERT语句结尾处没有分号。 (我通常会让他们摆脱习惯,但我正在开发其他人制造的系统。)
- 这对于了解SQL Server的人比我更了解的人是否看起来像是一个并发问题?
- 如果看起来像是一个并发问题,我可以使用事务来减轻它,我该怎么做?
编辑:我只是意识到SP是不是什么都抛出了错误。网站还有另一个地方做插入,而不检查是否存在RID。不过,我很高兴我提出了这些问题,因为我仍然不知道其他答案。
啊'SCOPE_IDENTITY()'是不是我以前见过;这非常有帮助。显然,为了简洁起见,我留下了很多代码,但是如果基于SP的参数满足其他条件,则只会执行第二个“INSERT”。在这种情况下交易是否有意义? –
还有一个问题:使用事务和批分隔符有什么区别? 'GO'与'BEGIN TRANSACTION ... COMMIT TRANSACTION'? –
事务逻辑上将多个语句分组在一起,以使它们成功或失败。在我上面的代码中,如果由于某种原因'INSERT' to _tbl_RegistrationCertificates_失败,那么'INSERT' to _tbl_Registrations_也会回滚。当一组报表全部被视为一个操作(BEGIN'和'COMMIT'之间的所有内容)时,事务可帮助您保持逻辑上一致的状态。另一方面,“GO”只是告诉SQL Server工具运行一组语句。 –