如何避免事务中 IF EXISTS 语句中的 NULL 值?
How to avoid NULL value in IF EXISTS statement within transaction?
我有数千个线程并发执行。 第一类线程是T-SQL这样的查询:
DECLARE @import_id int
IF EXISTS (
SELECT [id]
FROM [dbo].[Import]
WHERE created IS NULL
)
SELECT @import_id = [id]
FROM [dbo].[Import]
WHERE created IS NULL
ELSE
BEGIN
INSERT INTO [dbo].[Import] ([startdate])
SELECT GETDATE()
SELECT @import_id = @@IDENTITY
END
线程的第二种是T-SQL这样的查询:
UPDATE [dbo].[Import] SET created = GETDATE() WHERE created IS NULL
所有这些类型的 T-SQL 查询在 事务 中执行,类型为 Read Commited。
问题:有时,第一个查询,returns @import_id = NULL
,但我期待一些@import_id
.
中的值
问题是如何使用 Read Commited 事务类型来避免这种情况?
这似乎是一个奇怪的设计,但我想你遗漏了很多东西。
解决此问题的一种方法是删除 IF
测试,因为数据似乎在 IF
测试和 SELECT
之间发生变化。所以改为:
SELECT @import_id = [id]
FROM [dbo].[Import]
WHERE created IS NULL;
IF @import_id IS NULL BEGIN
INSERT INTO [dbo].[Import] ([startdate])
SELECT GETDATE();
SELECT @import_id = SCOPE_IDENTITY(); -- SCOPE_IDENTITY() is recommended over @@IDENTITY
END;
请注意,您的 SELECT
可能需要 TOP 1
和 ORDER BY
。
当然,如图所示,您可能会获得一个 @import_id
,其中 created is null
但您的其他线程甚至可以在 @import_id
返回给客户端之前将其设置为 GETDATE()
。但我想你已经想到了。
我有数千个线程并发执行。 第一类线程是T-SQL这样的查询:
DECLARE @import_id int
IF EXISTS (
SELECT [id]
FROM [dbo].[Import]
WHERE created IS NULL
)
SELECT @import_id = [id]
FROM [dbo].[Import]
WHERE created IS NULL
ELSE
BEGIN
INSERT INTO [dbo].[Import] ([startdate])
SELECT GETDATE()
SELECT @import_id = @@IDENTITY
END
线程的第二种是T-SQL这样的查询:
UPDATE [dbo].[Import] SET created = GETDATE() WHERE created IS NULL
所有这些类型的 T-SQL 查询在 事务 中执行,类型为 Read Commited。
问题:有时,第一个查询,returns @import_id = NULL
,但我期待一些@import_id
.
问题是如何使用 Read Commited 事务类型来避免这种情况?
这似乎是一个奇怪的设计,但我想你遗漏了很多东西。
解决此问题的一种方法是删除 IF
测试,因为数据似乎在 IF
测试和 SELECT
之间发生变化。所以改为:
SELECT @import_id = [id]
FROM [dbo].[Import]
WHERE created IS NULL;
IF @import_id IS NULL BEGIN
INSERT INTO [dbo].[Import] ([startdate])
SELECT GETDATE();
SELECT @import_id = SCOPE_IDENTITY(); -- SCOPE_IDENTITY() is recommended over @@IDENTITY
END;
请注意,您的 SELECT
可能需要 TOP 1
和 ORDER BY
。
当然,如图所示,您可能会获得一个 @import_id
,其中 created is null
但您的其他线程甚至可以在 @import_id
返回给客户端之前将其设置为 GETDATE()
。但我想你已经想到了。