使用主键将数据插入SQL表。对于欺骗 - 允许插入错误或首先选择?

StackOverflow https://stackoverflow.com/questions/411575

  •  03-07-2019
  •  | 
  •  

给出如下表:

CREATE TABLE dbo.MyTestData (testdata varchar(50) NOT NULL) 

ALTER TABLE dbo.MyTestData WITH NOCHECK ADD CONSTRAINT [PK_MyTestData] PRIMARY KEY  CLUSTERED (testdata) 

考虑到我们需要一个唯一的'testdata'列表,当我们完成收集要从已知重复的外部数据列表中添加的项目时......执行插入存储过程时应该编写过程来测试存在还是只是允许错误?什么是最常见的做法?我总是进行存在测试,但昨晚正在辩论......

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON

  IF NOT EXISTS(SELECT testdata FROM dbo.MyTestData WHERE testdata=@ptestdata)
  BEGIN
    INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
  END

RETURN 0

或者只是在执行这个错误时捕获/忽略PK违规错误?

CREATE PROCEDURE dbo.dmsInsertTestData @ptestdata VarChar(50)
AS
  SET NOCOUNT ON
  INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
RETURN 0
有帮助吗?

解决方案

我总是在一个声明中这样做:

INSERT INTO dbo.MyTestData (testdata ) VALUES (@ptestdata)
WHERE NOT EXISTS(SELECT 1 FROM dbo.MyTestData WHERE testdata=@ptestdata)

其他提示

您的错误检查(即“IF NOT EXISTS ...”)可能会也可能不会起作用,因为存在潜在的竞争条件(如果另一个事务在您的IF NOT EXISTS语句之后但在您的INSERT语句之前插入记录)。

因此,无论您之前是否检查过,您都应该将INSERT语句编码为可能失败。

您是否要同时检查 (而非<)>取决于您和您的用户界面。

我认为大多数程序员会建议避免异常。我不确定从T-SQL的性能角度来看,但在.NET中,我相信抛出的异常比额外的if / else语句更昂贵。

我对您给出的第一个示例的关注是它没有向用户返回错误。可以修复它,但我不会使用它,除非它返回错误。

如果你对两个可能性的关注是对大表的表现,我建议你测试它们,看看是否比另一个快得多。如果if选择特别复杂并且插入需要在大多数时间内发生,那么在大多数情况下简单地让它失败可能会更快。另一方面,如果输入错误的可能性很高,并且if如此处所示相对简单,那么另一个过程可能是更好的过程。但是,只有对您的真实数据结构和数据以及真实查询进行真正的测试才能告诉您哪个是性能更好的,因为它可能在deiffernt situaltions中有所不同。

我认为这取决于存储过程的性质。其他基本上,你应该处理错误,如果你有与它们有关的事情(或为程序的客户封装它们),如果你没有任何关系,就让它们传播,并且不能使它更友好。应用层。

如果存储过程旨在插入原始数据,我认为它应该让应用程序处理可能的错误。如果存储过程被设计为一个抽象层(并且执行特定的任务而不是运行特定的语句)并且可以处理错误并对其执行某些操作或者可以以优雅的方式(例如,明确定义的错误代码)向应用程序报告,它应该这样做。否则,应该由应用程序来确保它没有插入重复数据,而不是数据库(数据库已经使用主键强制执行此操作)。

为了方便用户,执行SELECT通常是一种好习惯,如果记录已经存在,则为用户提供查看和/或编辑它的机会。

例如,如果用户正在添加新的客户记录,他们可能希望查看已为该客户显示的信息。他们可能有其他信息要添加到记录中,例如电话号码。

在这种情况下,拒绝添加记录比提供查看现有副本的能力要小。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top