只有插入一行,如果它不在那里

我一直使用类似于以下的东西来实现它:

INSERT INTO TheTable SELECT @primaryKey, @value1, @value2 WHERE NOT EXISTS (SELECT NULL FROM TheTable WHERE PrimaryKey = @primaryKey) 

…但是一旦发生负载,就会发生主键违例。 这是根本插入这张桌子的唯一声明。 那么这是否意味着上述说法不是primefaces的?

问题是这几乎不可能随意重新创build。

也许我可以把它改成如下的东西:

 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上的其他问题,其中答案是build议“IF(SELECT COUNT(*)… INSERT”等,但我总是在(也许是不正确的)假设一个单一的SQL语句将primefaces。

有没有人有任何想法?

7 Solutions collect form web for “只有插入一行,如果它不在那里”

那么“JFDI”模式呢?

 BEGIN TRY INSERT etc END TRY BEGIN CATCH IF ERROR_NUMBER() <> 2627 RAISERROR etc END CATCH 

严重的是,这是最快和最没有锁的并发,特别是在大量的情况下。 如果UPDLOCK升级并且整个表被locking呢?

阅读第四课

我加了最初不存在的HOLDLOCK。 请忽略没有这个提示的版本。

就我而言,这应该够了:

 INSERT INTO TheTable SELECT @primaryKey, @value1, @value2 WHERE NOT EXISTS (SELECT 0 FROM TheTable WITH (UPDLOCK, HOLDLOCK) WHERE PrimaryKey = @primaryKey) 

另外,如果你真的想更新一行,如果它不存在,你可能会发现这个问题很有用。

你可以使用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) 

我不知道这是否是“正式”的方式,但是你可以尝试INSERT ,如果失败,可以回到UPDATE

你能把这个陈述包装在一个交易中吗? 这应该阻止任何其他语句尝试插入,直到提交第一个事务。

首先,对我们的男人@gbn大力呼吁,感谢他对社区的贡献。 根据他的build议,我甚至无法解释我经常发现自己。

无论如何,足够的fanboy。

稍微补充一下他的回答,也许“增强”它。 对于像我这样的人来说,在<> 2627情况下,应该怎么办(而且没有一个空的CATCH是不可选的)。 我从technetfind这个小块。

  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 

过去我使用不同的方法做了类似的操作。 首先,我声明一个variables来保存主键。 然后,我使用select语句的输出填充该variables,该语句用这些值查找logging。 然后我和IF声明。 如果主键为空,则插入,否则返回一些错误代码。

  DECLARE @existing varchar(10) SET @existing = (SELECT primaryKey FROM TABLE WHERE param1field = @param1 AND param2field = @param2) IF @existing is not null BEGIN INSERT INTO Table(param1Field, param2Field) VALUES(param1, param2) END ELSE Return 0 END 
  • 使用sp_addlinkedserver添加服务器
  • 如何获得sp_executesql结果到一个variables?
  • 如何计算SQL varchar中某个子string的出现次数?
  • 确定SQL Server中用户创build的对象
  • T-SQL datetime使用函数四舍五入到最接近的分钟和最近的小时数
  • 为什么我不能在SQL Management Studio的开始/结束块中使用“创build模式”?
  • 使用select将行添加到查询结果
  • 删除大表中的所有数据的最快方法
  • T-SQL转换与转换
  • 将SQL列中的分隔值拆分为多行
  • SQL Server:对象名称的最大字符长度