我总是使用类似于下面的方法来实现它:
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WHERE
PrimaryKey = @primaryKey)
...but一旦加载,就会发生主键冲突。这是唯一一个插入到这个表中的语句。那么这是否意味着上面的陈述不是原子的呢?
问题是,这几乎不可能随意重新创建。
也许我可以将其更改为如下所示:
INSERT INTO TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
WHERE
PrimaryKey = @primaryKey)
虽然,也许我使用了错误的锁,或者使用了太多的锁或其他什么。
我在stackoverflow.com上看到过其他问题,答案是"IF (SELECT COUNT(*) ... INSERT“等),但我总是假设(可能是错误的)一条SQL语句是原子的。
有谁有什么想法吗?
发布于 2010-08-05 01:45:14
您可以使用MERGE:
MERGE INTO Target
USING (VALUES (@primaryKey, @value1, @value2)) Source (key, value1, value2)
ON Target.key = Source.key
WHEN MATCHED THEN
UPDATE SET value1 = Source.value1, value2 = Source.value2
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, ReasonType) VALUES (@primaryKey, @value1, @value2)
发布于 2017-05-04 04:28:31
首先,向我们的man @gbn致敬,感谢他对社区的贡献。甚至无法解释我发现自己有多频繁地听从他的建议。
不管怎么说,追星族已经玩够了。
稍微补充一下他的答案,也许可以“增强”它。对于那些像我这样的人来说,在<> 2627
场景中做什么会让人感到不安(不,空的CATCH
不是一个选择)。我从technet那里找到了这个小金块。
BEGIN TRY
INSERT etc
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
BEGIN
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (
@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
END
END CATCH
发布于 2010-08-05 00:59:47
我不知道这是否是“官方”的方式,但你可以尝试INSERT
,如果失败了,可以退回到UPDATE
。
https://stackoverflow.com/questions/3407857
复制相似问题