是否可以吞下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调用。这恰好发生在SQL Server中。
答案 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引发异常(即使您只是吞下它们)可能非常昂贵 - 请参阅here和here。
所以我的建议是先检查违规行为,然后只在必要时插入。但是,我不会将这些内容分成单独的语句,特别是在完全单独的应用程序往返中,因为您可以使用此方案:
-- 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。