在 SQL Server 表中,我有以下 2 列:
RowId:主键、数字、标识列和自动插入。
MailId:非密钥、数字、非身份和非自动插入。
邮件 ID 可以重复。如果是新的 MailId,我将检查 max(MailId)+1 并将其插入到新行中,如果出现重复,值将作为参数出现。
逻辑看起来不错,但这里有一个问题,我只是在考虑(但准确性很低)同时可能有两个不同的新 MailId 请求。这会导致逻辑错误吗?例如,当代码检查 max(MailId)+1 为 101 时,我将其存储在变量中,但可能是在下一个插入语句执行插入表中的新记录之前。现在表中的 max(MailId)+1 将是 102,但变量中的值将是 101 ?
请提出任何建议,我也想控制这个错误的机会。
编辑
(我没有使用identity(1,1),因为我还必须在其中传递自定义值)
当 SQL Server 中已有如此出色的自定义滚动
Identity
字段时,为什么还要使用自定义滚动字段?
只需使用
INT Identity (1,1)
作为 ID 字段,每次插入行时它都会自动递增。它还可以比您手动实现的任何东西更好地处理并发性。
编辑:
手动ID值示例:
SET IDENTITY_INSERT MyTable ON
INSERT INTO MyTable (IdField, Col1, Col2, Col3,...)
VALUES
(1234, 'Col1', 'Col2', 'Col3',...)
SET IDENTITY_INSERT MyTable OFF
您需要包含
INSERT
的显式字段列表。
使用插入件上的输出来确保您拥有正确的值。如果您插入然后选择 MAX,则可能有人会“潜入”并最终导致重复。也就是说,你插入MAX + 1,同时其他人插入MAX + 1,然后你选择MAX,他们选择MAX,你们都有相同的值。而如果您 INSERT 并使用 OUTPUT,您将确信您是独一无二的。这很少是一个问题,但如果你有很多活动,它可能会发生(根据经验)。
编辑
USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
@RiaD 如果您使用 Max(pkIdNoIdentityKey)+1,那么您最好锁定表以进行读取,因为您可能会在插入时出现 PrimaryKey 违规错误。由于 SQL 默认为已提交读,因此如果没有序列化锁,对 Max(pkIdNoIdentityKey)+1 的所有并发读取将获得相同的值,直到您提交所有嵌套事务。
最好在带有身份的表上插入行并使用 Select @newId = Scope_Identity
一切都与范围有关!