是否可以吞下DB INSERT的异常

时间:2014-01-31 15:48:26

标签: sql sql-server exception-handling

是否可以吞下INSERTS的重复密钥违例异常,还是应该检查记录是否存在?

所以,让我说我有一个表格Photo with one field:PhotoName。我正在浏览文件目录以向Photo添加项目。在这个过程中,当我找到光子名称时,它可能已经存在于数据库中。所以有两种方法可以解决这个问题:

1) //Look to see if it exists before adding it. Only add it if it does not exist.

bool photoExists = SQLSELECTStatementToCheckIfThePhotoExists(photoName);
if(!photoExists)
  SQLCommandToInsertPhoto(photoName)

or 2) //Assume that it doesn't exist. If it does, catch and ignore.
try
{
  SQLCommandToInsertPhoto(photoName);
}
catch(DuplicateKeyException ex)
{
  //swallow it and continue on as if nothing happened.
}

一方面,我不一定喜欢“吞咽”异常的概念,但另一方面,try ... catch只使用一次DB调用。这恰好发生在S​​QL Server中。

2 个答案:

答案 0 :(得分:5)

你绝对不应该只是“吞下”这个例外。您应该尝试找到这些重复项,而不是在需要时插入它们。

On方法可以检查密钥上不存在的位置。

INSERT INTO TargetTable

SELECT 
    KeyID,
    blah,
    blerg,
FROM SourceTable AS S
WHERE NOT EXISTS (
    SELECT 1
    FROM TargetTable AS T
    WHERE S.KeyID = T.KeyID
    )

此方法允许您只在表中添加INSERT个新行。当然,这种方法并不考虑您对UPDATE可能需要做的任何匹配,但这不在本问题的范围之内,但仍应考虑。大多数用户也可以使用MERGE我会在有空的时候发布一个例子。

答案 1 :(得分:2)

让SQL Server引发异常(即使您只是吞下它们)可能非常昂贵 - 请参阅herehere

所以我的建议是先检查违规行为,然后只在必要时插入。但是,我不会将这些内容分成单独的语句,特别是在完全单独的应用程序往返中,因为您可以使用此方案:

-- connection A, at 12:00:00.0000001:

SELECT FROM TABLE WHERE key = 'x'; -- 0 rows returned

-- connection B, at 12:00:00.0000002:

SELECT FROM TABLE WHERE key = 'x'; -- 0 rows returned

-- connection A, at 12:00:00.0000003:

INSERT dbo.TABLE(key) VALUES('x'); -- succeeds

-- connection B, at 12:00:00.0000003:

INSERT dbo.TABLE(key) VALUES('x'); -- fails

我宁愿在单个INSERT ... WHERE NOT EXISTS语句中执行此操作,正如@Zane's answer所示,尽管我会在SELECT部分添加更高的升级。或者,如果发现密钥违规(I wrote about this here),您可以使用INSTEAD OF INSERT触发器从插入中保释。 顺便说一句,我会MERGE极其谨慎 - 请参阅this article for my reasoning