【问题标题】:Number of SQL operation in IF NOT EXISTS statement vs SQL server engine Primary key check in SQL Server [duplicate]IF NOT EXISTS 语句中的 SQL 操作数与 SQL Server 引擎 SQL Server 中的主键检查 [重复]
【发布时间】:2020-10-07 04:11:18
【问题描述】:

考虑一个表A,其主键为column1,column2。

现在让 column1 成为 uniqueidentifier 类型的主键。

现在,如果您想避免使用存储过程向表中重复插入,哪种方法更好?

案例#1:

IF NOT EXISTS (SELECT 1 FROM TABLE A WHERE column1 = @insertValue)
BEGIN
    INSERT INTO Table A
     ....
END

或案例#2:

TRY
BEGIN
    INSERT INTO TABLE A
END
CATCH
BEGIN
    IF(ErrorNumber() = 2627)--Erro number of primary key violation
    BEGIN
        ---------- deal with the error
    END
END

我觉得 case #2 更好,因为只执行了 1 次 SQL 检查操作,但 case #1 发生了 2 次。

我了解当我们在表上创建主键时,SQL 在插入之前检查重复,使用这种现有的 SQL 检查重复机制不是很好吗?而不是使用 IF NOT EXISTS

请添加您的答案,请考虑所有参数深入解释答案

请大家帮助我理解对表的 sql 操作。这里的目的是了解sql主键违例检查的内部机制,

【问题讨论】:

  • 我认为 #1 是“更好的” - 因为您正在检查以 避免 错误 - 而不是让它发生并不得不对其做出响应。通过首先检查,您可以避免必须为即将失败的INSERT 做所有工作 - 所以即使在性能方面,我相信 #1 会更可取。
  • 为什么这是一个问题?您使用的是合成 ID,那么为什么您的应用程序逻辑会尝试插入具有相同 ID 的行?即使是这样,您的代码也必须始终正确处理错误 - PK 冲突只是这些错误之一。还在用2008吗?你有更重要的事情要担心。
  • @SMor 为什么我要问这个问题?答案是这样的,我的许多同事,包括 SQL 专家,都告诉我案例#2 是一种 hacky 的实现方式,这并不属于标准模式,所以为了让全球社区清楚,我很感兴趣
  • 我认为您应该重新表述您的问题,不要询问哪种方式更好,而是询问一种方式与另一种方式相比的好处。原因是策展人会看到它并认为你在问一个基于意见的问题。见What types of questions should I avoid asking?
  • 当然,更改措辞不会阻止您的问题重复。但至少你现在还有 11 个答案:)

标签: sql-server tsql sql-server-2008 database-design primary-key


【解决方案1】:

应用数据修改时,您可以使用以下块:

SET XACT_ABORT, NOCOUNT ON;

BEGIN TRY

    BEGIN TRANSACTION;
    -- CODE BLOCK GOES HERE
    COMMIT TRANSACTION;

END TRY
BEGIN CATCH 

   IF @@TRANCOUNT > 0
   BEGIN
      ROLLBACK TRANSACTION
   END;

   -- GET ERRORS DETAILS OR THROW ERROR

END CATCH;

SET XACT_ABORT, NOCOUNT OFF;

此外,如果您的主键是UNIQUEIDENTIFER,并且您正在使用NEWID() 函数生成新值,您可以放心——CATCH 块将不会被执行。

但是,使用primary key这样的值并不好,因为:

  • 它比 (smallint, int, bigint) 等数字类型占用更多空间
  • 如果使用NEWID() 生成值,它们将被插入到索引的随机页面中,这将导致碎片;对于IDENTITY 列,新行插入到最后一页;您可以使用NEWSEQUENTIALID 解决此问题

【讨论】:

  • 我不明白这是如何回答这个问题的。
  • 它提供了第二个选项的改进变体。第一个变体是有风险的,因为在IF 执行期间记录可能不存在,但在INSERT 期间已经提交并再次引发错误。此外,正如我所写 - 如果使用 NEWIDNEWSEQUENTIALID,则无需担心。
  • 我同意 GUID 占用更多空间,但这将属于完全不同的问题,这里我的问题是针对重复项的 sql 检查操作,在案例#1 中 - 正在对表进行 2 次 sql 检查,
  • @PavanBhat 正如我对我所说的,最好使用案例 2,就好像您正在使用内部函数来生成值一样,重复的可能性很小。
  • @gotqn 假设同一 ID 的插入不会以并发方式发生,即使那样你会更喜欢使用 case#2 吗?跨度>
猜你喜欢
  • 1970-01-01
  • 2010-11-13
  • 2011-09-25
  • 2018-01-28
  • 2010-10-15
  • 2019-05-18
  • 2014-05-27
  • 2010-11-10
相关资源
最近更新 更多