SQL-在一个insert语句中获取或创建外部表

SQL-在一个insert语句中获取或创建外部表,sql,sql-server,foreign-keys,sql-insert,Sql,Sql Server,Foreign Keys,Sql Insert,我有两张桌子 Session - Id - UserId - CodeId (foreign key to Code.Id) 及 当然,我可以做到以下几点: 尝试从代码中获取Id 如果返回空,则插入新行并获取Id 插入会话 你们一起会得到类似的结果: DECLARE @codeId INT; SET @codeId = (SELECT Id FROM Code WHERE [Text] = @code); IF ( @codeId IS NULL ) BEGIN INSERT IN

我有两张桌子

Session
- Id
- UserId
- CodeId (foreign key to Code.Id)

当然,我可以做到以下几点:

尝试从代码中获取Id 如果返回空,则插入新行并获取Id 插入会话 你们一起会得到类似的结果:

DECLARE @codeId INT;

SET @codeId = (SELECT Id FROM Code WHERE [Text] = @code);

IF ( @codeId IS NULL )
BEGIN
    INSERT INTO Code ([Text]) VALUES (@code)
    SET @codeId = SCOPE_IDENTITY()
END

INSERT INTO Session (UserId, codeId) VALUES(@userId, @codeId)
是否也可以在更高效的通话中实现这一点? 我应该关心比赛条件吗? 免责声明: 在一个拥有大量用户的生产站点上,这将被称为很多,在这种环境中,性能已经被证明是至关重要的

附加说明

在Code.Text上会有一个唯一的索引 我预计在会话中会有数百万行 我预计大约有50000到200000行代码
这是一个棘手的问题-我肯定会创建一个测试工具来验证您的假设

我要做的第一件事是颠倒顺序——如果你有数百万个孩子,几十万个父母,你的孩子很有可能已经有了匹配的父母行

比如说:

INSERT INTO Session (UserId, codeId) 
SELECT @userId, [Text]
FROM Code
where [Text] = @code

if @@ROWCOUNT = 0
begin
    INSERT INTO Code ([Text]) VALUES (@code)
    SET @codeId = SCOPE_IDENTITY()

    INSERT INTO Session (UserId, codeId) VALUES(@userId, @codeId)
END

我不认为会有更有效的方法,假设你有正确的索引

你应该关心比赛情况吗?好吧,使用给定的代码,那么是的,但这很容易解决。从唯一索引开始,以便数据库对文本强制唯一性:

然后,代码应该如下所示:

DECLARE @codeId INT;

SET @codeId = (SELECT Id FROM Code WHERE [Text] = @code);

IF ( @codeId IS NULL )
BEGIN TRY
    INSERT INTO Code ([Text]) VALUES (@code)
        SET @codeId = SCOPE_IDENTITY();
END TRY
BEGIN CATCH
    -- you can check or just assume that the issue the unique constraint
END CATCH;

INSERT INTO Session (UserId, codeId)
    VALUES (@userId, @codeId);

TRY/CATCH块处理争用条件。

代码中大约需要多少行?你会有文本索引吗?该索引可以是唯一的吗?我建议将nolock添加到您的select Id中,其中[Text]=@Code;您好@SerkanArslan,谢谢您的消息-您能详细说明原因吗?@DirkBoer它防止由于插入而导致select if代码表有锁时等待。由于潜在的会话数,这看起来是可能的。
CREATE UNIQUE INDEX unq_code_text ON Code(Text);
DECLARE @codeId INT;

SET @codeId = (SELECT Id FROM Code WHERE [Text] = @code);

IF ( @codeId IS NULL )
BEGIN TRY
    INSERT INTO Code ([Text]) VALUES (@code)
        SET @codeId = SCOPE_IDENTITY();
END TRY
BEGIN CATCH
    -- you can check or just assume that the issue the unique constraint
END CATCH;

INSERT INTO Session (UserId, codeId)
    VALUES (@userId, @codeId);