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);