如何避免事务中 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 1ORDER BY

当然,如图所示,您可能会获得一个 @import_id,其中 created is null 但您的其他线程甚至可以在 @import_id 返回给客户端之前将其设置为 GETDATE()。但我想你已经想到了。