【问题标题】:Best way to indicate no change on row update with Java PreparedStatement使用 Java PreparedStatement 指示行更新没有变化的最佳方法
【发布时间】:2011-09-11 02:46:04
【问题描述】:

我正在创建一种方法来更新 SQL Server 2008 数据库中的行。 SQL String 看起来像这样:

private static final String UPDATE_ROW = 
    "UPDATE MyTable SET FieldOne = ?, FieldTwo = ? " +
    "WHERE IDField = ?";

当然是简化了。但问题在于,并非所有领域都必然会改变。我知道,使用直接 SQL,您只需将字段名称放入值中,什么都不会改变;但是,我不知道如何使用 Java PreparedStatement 来做到这一点。

我可以通过为每一行的每个要更改的字段(最多十个)调用一个更新来解决这个问题,但这只是丑陋的,我真的很想避免它。谁能告诉我如何将字段名称作为参数值放入,或者至少给我一个干净的解决方案?

【问题讨论】:

    标签: java sql-server-2008 prepared-statement


    【解决方案1】:

    我找不到一种方法来做我描述的事情,所以我最终读取了我正在更新的东西的值并传递了这些值。

    【讨论】:

      【解决方案2】:

      如果您创建专门的 UPDATE 语句,说明已更改的列,效率会高得多。

      如果您总是更新所有列,则会产生大量开销,例如更新索引列,这将导致相应的索引也被更新(并且实际上不需要这样做)。

      如果我没记错的话,即使你指定UPDATE foo SET bar = bar 也会发生这种情况。我认为 SQL Server 不会优化此类更新。

      【讨论】:

        【解决方案3】:

        您尽量避免为每次更新生成专门的语句,这很好。

        这些领域不是相互关联的吗?因为如果它们是相互关联的,那么更新最好保持字段间的一致性。因此,您需要先读取这些值,然后将它们全部写回——包括已更改和未更改的值。

        如果它们确实彼此完全不相关,则同时提交一系列更新。

        通常,一个结果会介于两者之间——存在相互关联的字段集群。例如,包含与 BillingAddress 相关的多个字段的人员记录。在这种情况下,为每组相关字段准备一个声明。

        如果您试图避免读取成本(以获取当前值),请考虑使用存储过程,其中未更改的字段值使用 NULL 编码。

        如果你没有使用 ORM,你也可以考虑使用游标的 ResultSet,并一个一个地更新字段,然后使用updateRow() 提交更改。见java.sql.ResultSet。要使用PreparedStatement 执行与Javadoc 相同的操作,您需要使用variant of Connection.prepareStatement(...)

        【讨论】:

        • 字段不相关。存储过程可能是一个理想的选择,但特定于应用程序的存储过程是 DBA 棕色衬衫不屑一顾的事情之一。
        • 好的,我已经编辑了答案,并带有使用 ResultSet.updateRow 的选项。这似乎是您真正想要做的,因为您想使用准备好的语句来实际查找行。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多