【问题标题】:Checking record with a foreign key exists存在外键检查记录
【发布时间】:2014-04-19 23:04:44
【问题描述】:

我应该使用 sql 请求检查外键是否存在,还是应该尝试插入并在失败时捕获?

我可以检查我引用的密钥是否存在。

我的问题更多是理论上的:捕获异常与每次插入时再查询一次 db。

例如,假设您有两张桌子,Cats 和 Humans。 Cats 有一个引用 Human 的外键。在尝试插入猫之前,我应该检查是否存在具有给定猫所有者列的人,还是应该尝试盲目插入并在失败时捕获。

【问题讨论】:

  • 您能否编辑问题以提供有关您面临的问题的更多详细信息,即:它是您无法控制的外部数据库吗?钥匙?数据库模式/实体模型如何?为什么在您尝试插入新记录时会失败(fk 通常会阻止更新/删除现有记录,除非您尝试插入不存在的依赖项)
  • 我已经更新了问题(=

标签: scala slick


【解决方案1】:

这不是一个简单的答案,它实际上取决于您的应用程序要求。

虽然作为一般经验法则,您应该避免将异常作为正常应用程序流程的一部分而引发,并且使用异常存在一些问题。

  • 首先,当接收到 SQL 异常时,您需要确定异常的来源,这可能很复杂且特定于数据库(请参阅此处了解详细信息:How to catch a specific exception in JDBC?

  • 其次,即使您设法将异常代码限制为 引用完整性,如果 Cat 引用两者,您仍将面临识别问题根源的任务一个Human 和它最喜欢的Food

  • 此外,即使您设法确定错误的根源是缺少参照完整性,也可能有一些原因(因此,您需要进行一些额外的调查,而不是简单地插入新行)。想象一下,你想为'Dorothy Smith'插入一只猫,而你正试图这样做,Dorothy 结婚了(很可能这只猫是恶毒婆婆的结婚礼物; ) 并将她的名字改为'Dorothy Griffith'。所以现在当你尝试插入猫时,如果你只是盲目地插入一条新记录,你会在数据库中复制 Dorothy。

  • 此外,由于上述原因,使用人为创建的 id 作为外键(而不是一组唯一标识用户的字段)是有意义的。在这种情况下,您需要首先获取此内部 id(如果您不希望应用程序知道标识符,则有几种方法可以解决它,使用存储过程和使用诸如 Hibernate 之类的 ORM 框架最常见的一种)。

话虽如此,我仍然可以想象处理异常会带来好处的情况,主要是当您需要满足特定的性能要求时。这种情况的例子可以是一个交易系统,其中你有货币和快速的汇率。由于这种情况很少发生,以至于引入了新货币,因此可以将其视为一种特殊情况,检查它是否存在没有意义(尽管在正确设计的系统中,这只会使您免于调用散列用于检查货币是否存在的函数,因为您肯定会在内部缓存所有货币,实际上这可能比使用 try ... catch ... 块包装 db 调用更快)。

因此,总而言之,尽量不要使用异常,而是通过正确定义应用程序逻辑来解决该问题,并在确实需要时回退到使用异常。

【讨论】:

  • 我不明白为什么要复制多萝西。
【解决方案2】:

这一段出现在问题中

例如,假设您有两张桌子,Cats 和 Humans。 Cats 有一个引用 Human 的外键。在尝试插入猫之前,我应该检查是否存在具有给定猫所有者列的人,还是应该尝试盲目插入并在失败时捕获。

这里提到了 CAT 有一个引用 HUMAN 的外键。

因此,无需检查 HUMAN 是否有您作为外键插入 CAT 表中的键(记录)。

因为 DB 抛出

违反完整性约束 (FK_T_NAME) - 未找到父键异常

假设如果您使用的是 Oracle DB,那么它会引发以下异常

ORA-02291:违反完整性约束 - 未找到父密钥

因此,每当您遇到此异常时,这意味着您在 CAT 表中作为外键插入的值在 HUMAN 表中不存在。

同样我使用 JDBC 测试它给出以下错误

原因:java.sql.SQLIntegrityConstraintViolationException:ORA-02291:违反完整性约束 (FK_T_NAME) - 未找到父键

【讨论】:

    猜你喜欢
    • 2014-01-19
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2013-05-23
    • 2015-01-21
    • 2012-08-13
    相关资源
    最近更新 更多