1

这更像是一个正确性问题。假设我的数据库中有一个带有主键列的表。在我的 DAO 代码中,我有一个名为 insertRow(string key) 的函数,如果表中不存在该键,该函数将返回 true 并使用该键插入一个新行。否则,如果已经存在具有该键的行,则返回 false。让 insertRow 首先检查密钥是否存在更好/更糟,还是继续执行插入并捕获重复的密钥错误?或者节省单个 select 语句太微不足道,甚至不用担心?

所以在 sudo 代码中:

boolean insertRow(String key){
    //potentially a select + insert
    if(select count(*) from mytable where key = "somekey" == 0){
       insert into mytable values("somekey")
       return true;
    }
    return false;
}

或者

  boolean insertRow(String key){
    try{
       //always just 1 insert
       insert into mytable values("somekey")
       return true;
    } catch (DuplicateKeyException ex){}
    return false;
  }
4

7 回答 7

6

插入行,捕获重复键错误。我个人的选择

我认为这可能会表现得更好,这取决于抛出异常的成本与两次访问数据库的成本。

只有通过测试这两种情况你才能确定

于 2009-06-16T15:29:39.003 回答
3

在我看来,这是使用异常的绝佳案例(因为重复项是异常的),除非您在大多数情况下指望那里已经成为一行(即,您正在执行“插入,但更新如果存在”逻辑。)

如果代码的目的是更新,那么您应该使用 select 或INSERT ... ON DUPLICATE KEY UPDATE子句(如果您的数据库引擎支持)。或者,创建一个为您处理此逻辑的存储过程。

于 2009-06-16T15:29:41.297 回答
3

尝试插入,然后捕获错误。

否则,您仍然可能在两个活动 SPID 之间存在并发问题(假设系统上同时存在两个 Web 用户),在这种情况下,您无论如何都必须捕获错误:

User1: Check for key "newkey"? Not in database.
User2: Check for key "newkey"? Not in database.
User1: Insert key "newkey". Success.
User2: Insert key "newkey". Duplicate Key Error.

您可以通过使用显式事务或设置事务隔离级别来缓解这种情况,但使用第二种技术更容易,除非您确定只有一个应用程序线程始终针对数据库运行。

于 2009-06-16T16:28:05.237 回答
2

第二个,因为第一个选项击中数据库的两倍,而第二个选项只击中一次。

于 2009-06-16T15:29:02.047 回答
0

简短的回答是您需要自己测试它。我的直觉是,做一个小的选择来检查是否存在会表现得更好,但你需要自己验证一下,看看哪个表现更好。

一般来说,我不喜欢将我的错误检查完全留给我正在做的任何事情的异常引擎。换句话说,如果我可以检查我正在做的事情是否有效,而不仅仅是抛出异常,那通常就是我所做的。

但是,我建议使用EXISTS查询而不是count(*)

if(exists (select 1 from mytable where key = "somekey"))
    return false
else
    insert the row

说了这么多(从抽象的、与引擎无关的角度来看),我很确定 MySQL 有一些关键字,只有当主键不存在时,才能将行插入表中。这可能是您最好的选择,假设您可以使用 MySQL 特定的关键字。

另一种选择是将逻辑完全放在 SQL 语句中。

于 2009-06-16T15:29:06.023 回答
0

mysql中的另外两个选项是使用

insert ignore into....

insert into .... on duplicate key update field=value

包含on duplicate key update field=field

见:http ://dev.mysql.com/doc/refman/5.0/en/insert.html

编辑:您可以测试affected_rows 是否插入有效果。

于 2009-06-16T15:29:33.823 回答
0

现在我已经在网上找到了 Martin Fowler 的书,一个不错的方法是使用密钥表- 有关更多信息,请参见第 222 页。

于 2009-06-16T15:40:07.297 回答