【问题标题】:Why does PreparedStatement.setNull requires sqlType?为什么 PreparedStatement.setNull 需要 sqlType?
【发布时间】:2023-04-04 02:49:01
【问题描述】:
  1. 根据 PreparedStatement.setNull 的 java 文档:“注意:您必须指定参数的 SQL 类型”。方法需要列的SQL类型是什么原因?

  2. 我注意到传递 java.sql.Types.VARCHAR 也适用于非 varchar 列。是否存在不适合 VARCHAR 的场景(某些列类型或某些 DB 提供程序)?

谢谢。

【问题讨论】:

  • JDBC 规范附录 B 回答了问题的第二部分。它显示了大量的强制强制,并且有一个声明驱动程序可能执行更多。

标签: java sql jdbc


【解决方案1】:

根据 java 文档 PreparedStatement.setNull: "注意:你 必须指定参数的 SQL 类型”。是什么原因 方法需要 SQL 类型 列?

为了最大的兼容性;根据规范,有些数据库不允许将无类型的 NULL 发送到底层数据源。

我注意到路过 java.sql.Types.VARCHAR 也适用于 非 varchar 列。在那里 不会出现 VARCHAR 的场景 合适的(某些列类型或 某些数据库提供商)?

我不认为这种行为真的是规范的一部分,或者如果是,那么我确信那里存在某种隐含的强制。在任何情况下,不建议依赖这种在底层数据存储更改时可能会中断的行为。为什么不直接指定正确的类型?

【讨论】:

  • 1.我仍然不明白为什么我必须声明类型。据我所知,带有 SET MY_COLUMN = NULL 的 UPDATE 命令适用于每种列类型,那为什么还不够呢?
  • 2.我有一个获取 SQL 字符串和 Collection 并为每个对象调用 PreparedStatement.setObject / setNull 的方法。如果我希望将正确的类型传递给 setNull,我需要传递每个对象的类型并创建一个丑陋的 if。如果数据库驱动程序可以处理setObject,我认为它应该处理setNull并在内部进行检查。
  • @user:关于1;正如我已经提到的,JDBC 是一种标准化与数据库交互的尝试,但是每个数据库实现都有自己的做事方式。例如,我听说如果设置 NULL 时没有提供正确的类型,Oracle 会抱怨。因此 JDBC 要求您指定类型,底层 JDBC 实现是否将其传递给数据库是另一回事。如果特定的数据库线路协议决定在设置 NULL 值时传递类型,那将无济于事,因此没有必要对此进行推理。
  • 关于2;这是您做出的设计决定。我不知道有任何 db helper/wrapper code/framework 试图对用户隐藏数据库类型。在 hibernate 中,您指定注解/XML 配置来设置列类型。在你的代码中添加一个处理用户提供的类型的特性怎么样?如果这一切真的很麻烦,只需传入 VARCHAR,交叉手指并希望最好。 :-)
  • JDBC 规范附录 B 回答了问题的第二部分。它显示了大量的强制强制,并且有一个声明驱动程序可能执行更多。
【解决方案2】:

JDBC 驱动程序似乎正在远离setNull。见Add support for setObject(<arg>, null)

我的支持更多逻辑行为的数据库列表是:

  1. 甲骨文
  2. MySQL
  3. Sybase
  4. MS SQL 服务器
  5. HSQL

我的不支持这种逻辑行为的数据库列表是:

  1. 德比Queries with guarded null Parameter fail
  2. PostgreSQL Cannot pass null in Parameter in Query for ISNULL Suggested solution

【讨论】:

    【解决方案3】:

    对于 Oracle,将 varchar2 用于其他数据类型是非常不明智的。这可能会欺骗优化器,您可能会得到一个糟糕的执行计划。例如,在绑定中使用时间戳数据类型对日期列进行过滤,Oracle 最终可能会读取所有行,将所有日期转换为时间戳,然后过滤掉想要的行。 如果您在日期列上有索引,它甚至会变得更糟(如果 oracle 选择使用它) - 对您的 oracle 块进行单次读取。

    --拉瑟

    【讨论】:

      猜你喜欢
      • 2019-06-09
      • 2020-05-03
      • 2020-03-22
      • 2011-08-11
      • 2019-06-09
      • 2012-05-21
      • 2020-02-26
      • 2019-10-12
      • 2012-01-17
      相关资源
      最近更新 更多