没有 if 条件(动态查询)或乱码的Where子句中的PreparedStatement“为null”

2024-04-29

假设我有这样的查询:

SELECT * FROM CUSTOMERS WHERE CUSTOMER_ID = ?

使用PreparedStatement,我可以绑定变量:

pstmt.setString(1, custID);

但是,我无法通过以下绑定获得正确的结果:

pstmt.setString(1, null);

结果是:

SELECT * FROM CUSTOMERS WHERE CUSTOMER_ID = NULL

这不会给出任何结果。正确的查询应该是:

SELECT * FROM CUSTOMERS WHERE CUSTOMER_ID IS NULL

通常的解决方案是:

解决方案1

动态生成查询:

String sql = "SELECT * FROM CUSTOMERS WHERE CUSTOMER_ID "
                + (custID==null ? "IS NULL" : "= ?");
if (custID!=null)
    pstmt.setString(1, custID);

解决方案2

Use NVL将 null 值转换为乱码值:

SELECT * FROM CUSTOMERS WHERE NVL(CUSTOMER_ID, 'GIBBERISH') = NVL(?, 'GIBBERISH');

但您需要 100% 确定值“GIBBERISH”永远不会被存储。

Question

有没有办法使用静态查询and避免依赖乱码值转换?我正在寻找类似的东西:

SELECT * FROM CUSTOMERS
    WHERE /** IF ? IS NULL THEN CUSTOMER_ID IS NULL ELSE CUSTOMER_ID = ? **/

我想我可能有一个可行的解决方案:

SELECT * FROM CUSTOMERS
    WHERE ((? IS NULL AND CUSTOMER_ID IS NULL) OR CUSTOMER_ID = ?)

pstmt.setString(1, custID);
pstmt.setString(2, custID);

上述工作可靠吗?有没有更好的方法(可能只需要设置一次参数)?或者根本没有办法可靠地做到这一点?


您的工作解决方案很好(并且类似于我以前用过 https://stackoverflow.com/a/24811331/266304)。如果您只想绑定一次,可以使用 CTE 或内联视图为实际查询提供值:

WITH CTE AS (
    SELECT ? AS REAL_VALUE FROM DUAL
)
SELECT C.*   -- but not * really, list all the columns
FROM CTE
JOIN CUSTOMERS C
ON (CTE.REAL_VALUE IS NULL AND C.CUSTOMER_ID IS NULL)
    OR C.CUSTOMER_ID = CTE.REAL_VALUE

所以只有一个占位符需要绑定。

不过,我并没有真正看到 Java 端的分支存在问题,除非您的实际查询要复杂得多并且会导致大量重复。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

没有 if 条件(动态查询)或乱码的Where子句中的PreparedStatement“为null” 的相关文章

  • 未装饰窗户的 Windows Snap 功能?

    有谁知道如何允许未装饰的窗户使用此功能 唯一的选择就是重新实施它 有任何想法吗 谢谢 可停靠可能是唯一的JToolBar http docs oracle com javase tutorial uiswing components too
  • 将错误保存到 MySQL 数据库

    我有一个 php 查询来更新 MySQL 数据库 请参见下文 sql update hr payroll set payroll number payroll number tax code tax bacs ref bacs ref pa
  • 如何使用 Java 引用释放 Java Unsafe 内存?

    Java Unsafe 类允许您按如下方式为对象分配内存 但是使用此方法在完成后如何释放分配的内存 因为它不提供内存地址 Field f Unsafe class getDeclaredField theUnsafe Internal re
  • SQL如何将两个日期之间一小时内的事件相加并显示在一行中

    我正在使用 C 和 SQL Server 2005 开发一份报告 我只需显示我们每小时获得的点击次数 桌子很大 输出应如下所示 Row Date Time Hit Count 1 07 05 2012 8 00 3 2 07 05 2012
  • 在光标所在行强制关闭!

    嘿 我正在尝试创建一个应用程序来查找存储在 SQlite 数据库中的 GPS 数据 但我面临一个问题 我构建了一个 DbAdapter 类来创建数据库 现在我尝试使用以下函数从另一个类获取所有数据上的光标 public Cursor fet
  • 如何使用内联 SQL 参数化 IN 语句的集合? [复制]

    这个问题在这里已经有答案了 可能的重复 参数化 SQL IN 子句 https stackoverflow com questions 337704 parameterizing a sql in clause 你好 我有一个查询 如下所示
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • 在java程序中使用c++ Dll

    我正在尝试使用System LoadLibrary 使用我用 C 编写的一个简单的 dll UseDllInJava java import com sun jna Library import com sun jna Native imp
  • 按每月时间为用户标记标签

    数据源 User ID Visit Date 1 2020 01 01 12 29 15 1 2020 01 02 12 30 11 1 2020 04 01 12 31 01 2 2020 05 01 12 31 14 Problem 我
  • 如何向页面添加 HTML 页眉和页脚?

    如何使用 itext 从 html 源添加标题到 pdf 目前 我们已经扩展了 PdfPageEventHelper 并重写了这些方法 工作正常 但当我到达 2 个以上页面时 它会抛出 RuntimeWorkerException Over
  • 文本视图不显示全文

    我正在使用 TableLayout 和 TableRow 创建一个简单的布局 其中包含两个 TextView 这是代码的一部分
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • MySQL #1093 - 您无法在 FROM 子句中指定用于更新的目标表“赠品”

    I tried UPDATE giveaways SET winner 1 WHERE ID SELECT MAX ID FROM giveaways 但它给出了 1093 您无法指定目标表 赠品 进行更新FROM clause 本文 ht
  • Android ScrollView,检查当前是否滚动

    有没有办法检查标准 ScrollView 当前是否正在滚动 方向是向上还是向下并不重要 我只需要检查它当前是否正在滚动 ScrollView当前形式不提供用于检测滚动事件的回调 有两种解决方法可用 1 Use a ListView并实施On
  • 对带有空白 NVARCHAR 或 NULL 检查的 VARCHAR 索引进行 Count(*) 会导致返回的行数加倍

    我有一张桌子 上面有VARCHAR列及其上的索引 每当一个SELECT COUNT 是在这张表上完成的 该表检查了COLUMN N OR COLUMN IS NULL它返回双倍的行数 SELECT 与相同的where子句将返回正确的记录数
  • 什么是 Java2D 处理程序线程?

    我创建了一个使用 Hibernate 的示例 java 应用程序 当我进行线程转储时 我观察到一个名为 Java2D Disposer 的奇怪线程 有人能告诉我该线程的功能吗 AWT 系统中的某些实体需要最终确定以释放资源 最突出的例子是j
  • 使用 DBCP 配置 Tomcat

    在闲置一段时间 几个小时 后 我们收到了 CommunicationsException 来自 DBCP 错误消息 在异常中 位于这个问题的末尾 但我没有看到任何配置文件中定义的 wait timeout 我们应该看哪里 在 tomcat
  • 在会话即将到期之前调用方法

    我的网络应用程序有登录的用户 有一个超时 在会话过期之前 我想执行一个方法来清理一些锁 我已经实现了sessionListener但一旦我到达public void sessionDestroyed HttpSessionEvent eve
  • 设置 TreeSet 的大小

    有没有办法像数组一样对 Java 集合中的 TreeSet 进行大小限制 例如我们在数组中 anArray new int 10 数组具有固定长度 在创建数组时必须指定该长度 A TreeSet当您向其中添加元素时会自动增长 您无法设置其大

随机推荐