假设我有两列CategoryId和SubcategoryId。 SubcategoryId从每个CategoryId的1开始。插入新的子类别时,我需要为给定的CategoryId计算MAX(SubcategoryId)+1。
以下是否正确?
BEGIN TRANSACTION
DECLARE @NextId bigint;
SELECT @NextId = ISNULL(MAX(SubcategoryId),0) + 1
FROM Subcategory WITH (UPDLOCK, HOLDLOCK)
WHERE CategoryId = @CategoryId;
INSERT INTO Subcategory
(
CategoryId,
SubcategoryId
)
VALUES
(
@CategoryId,
@NextId
);
COMMIT
WITH(UPDLOCK,HOLDLOCK)是否也阻止了具有相同CategoryId的新行的并发插入,还是仅锁定SELECT时匹配的现有行?如果是后者我应该把它改成TABLOCK吗?是否还需要某种独家锁?
答案 0 :(得分:1)
一般来说,除非您有特殊要求,否则不建议使用锁定级别。根据我的理解,SQL Server服务器引擎可以处理并发问题而无需锁定提示。
所以你的表定义是:
CREATE TABLE Subcategory
(
CategoryId bigint,
SubcategoryId bigint
)
如果您将表格定义更改为:
CREATE TABLE Subcategory
(
CategoryId bigint NOT NULL,
SubcategoryId bigint IDENTITY(1,1) NOT NULL
) ON [PRIMARY];
ALTER TABLE Subcategory
ADD CONSTRAINT pk_Subcategory PRIMARY KEY (CategoryId,SubcategoryId )
子类别ID将成为自动编号。此数字将在每个插入时递增。因此,您不需要在插入期间指定子类别,这将允许SQL服务器处理并发。最好让SQL处理表的锁定并处理并发。
如果您将表格结构更改为我的建议,您的查询也会变得更简单。
BEGIN TRAN
INSERT INTO Subcategory
(
CategoryId,
)
VALUES
(
@CategoryId,
);
COMMIT TRAN
这可能是您的解决方案。抱歉,我的语法可能有误,因为我几个月没有碰过SQL服务器。