测试数据库中重复键的最佳方法

时间:2009-06-16 15:25:33

标签: mysql database dao

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

所以在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;
  }

7 个答案:

答案 0 :(得分:6)

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

我认为这可能会表现得更好,这取决于抛出异常的成本与两次击中db的成本。

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

答案 1 :(得分:3)

在我看来,这是使用异常的一个很好的例子(因为副本是例外的),除非你指望那里,大多数时候,已经是一行(即,你正在做“插入” ,但如果存在“逻辑,则更新。”

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

答案 2 :(得分: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.

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

答案 3 :(得分:2)

第二个因为第一个选项击中了db两倍而第二个选项只击中一次。

答案 4 :(得分:0)

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

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

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

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

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

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

答案 5 :(得分: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是否有插件有效。

答案 6 :(得分:0)

现在我已经在网上找到了Martin Fowler的书,一个体面的方法是使用key table - 请参阅第222页了解更多信息。