我有这样的存储过程。
CREATE PROCEDURE [dbo].[mysp]
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN
BEGIN TRAN
DECLARE @TrackingCode INT
SELECT @TrackingCode = DefaultsData
FROM dbo.Defaults
WHERE DefaultsID=77
UPDATE dbo.Defaults
SET DefaultsData = @PassedTrackingCode+1
WHERE DefaultsID=77
SELECT @TrackingCode
COMMIT TRAN
END
假设我们同时(并发)两次执行此存储过程,那么同时返回的@TrackingCode
值将是什么。如果我在存储过程中的NOLOCK
语句中使用SELECT
该怎么办?
答案 0 :(得分:0)
1)如果您打算生成唯一的跟踪代码,那么这不是一个好主意。你可以做这个简单的测试:
CREATE TABLE dbo.Defaults (
DefaultsData INT,
DefaultsID INT PRIMARY KEY
);
GO
INSERT INTO dbo.Defaults VALUES (21, 77);
GO
CREATE PROCEDURE [dbo].[mysp]
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN
BEGIN TRAN
DECLARE @TrackingCode INT
SELECT @TrackingCode = DefaultsData
FROM dbo.Defaults
WHERE DefaultsID=77
WAITFOR DELAY '00:00:05' -- 5 seconds delay
UPDATE dbo.Defaults
SET DefaultsData = @TrackingCode+1
WHERE DefaultsID=77
SELECT @TrackingCode -- Maybe it should return the new code
COMMIT TRAN
END;
GO
然后在SQL Server Management Studio中打开一个新窗口(Ctrl + N)并执行(F5)
EXEC [dbo].[mysp]
并打开第二个新窗口并执行(不到5秒钟)
EXEC [dbo].[mysp]
在这种情况下,您将获得相同的值。 NOLOCK
是一个坏主意(一般来说),在这种情况下并不能帮到你。
2)如果(我重复自己 - 抱歉)你的意图是生成唯一的跟踪代码然后你可以使用
ALTER PROCEDURE [dbo].[mysp]
@TrackingCode INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Defaults
SET @TrackingCode = DefaultsData = DefaultsData + 1 -- It generate the new code
WHERE DefaultsID=77;
END;
GO
或者您可以使用sequences(SQL Server 2012 +)。