作为一个答案 - 同时也是对@AndreaColleoni 已经提到的内容的进一步澄清:
管理动态查询中的许多 OR 条件(例如 WHERE 1=0 OR <condition>)
用作开/关开关
我将其用作部分查询的开关(开/关)语句。
如果我要使用
WHERE 1=1
AND (0=? OR first_name = ?)
AND (0=? OR last_name = ?)
然后我可以使用第一个绑定变量 (?) 来打开或关闭 first_name 搜索条件。 ,以及第三个绑定变量 (?) 来打开或关闭 last_name 标准。
我还添加了一个文字 1=1 只是为了美观,因此查询的文本可以很好地对齐。
对于这两个标准,它似乎没有多大帮助,因为通过仅放置 first_name 或 last_name 或两者,或两者来动态构建您的 WHERE 条件,可能会更容易做到这一点没有。因此,您的代码必须动态构建同一查询的 4 个版本。想象一下,如果您要考虑 10 个不同的条件会发生什么,那么您需要管理多少个相同查询的组合?
编译时间优化
我还可以添加 0=?如果您的所有条件都被索引,则绑定变量开关将无法很好地工作。将选择适当索引和执行计划的运行时优化器可能只是看不到在那些稍微复杂的谓词中使用索引的成本效益。因此,我通常建议将 0 / 1 显式注入到您的查询中(将其连接到您的 sql 中的字符串,或进行一些搜索/替换)。这样做将使编译器有机会优化冗余语句,并为运行时执行器提供更简单的查询。
(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)
在上面的第二条语句中,编译器知道它甚至不需要考虑条件的第二部分 (cond = ?),它会简单地删除整个谓词。如果它是一个绑定变量,编译器永远不可能做到这一点。
因为您是简单且强制地注入 0/1,所以 SQL 注入的可能性为零。
在我的 SQL 中,作为一种方法,我通常将我的 sql 注入点放置为 ${literal_name},然后在我什至之前使用正则表达式使用适当的文字搜索/替换任何出现的 ${...}让编译器尝试一下。这基本上导致查询存储如下:
WHERE 1=1
AND (0=${cond1_enabled} OR cond1 = ?)
AND (0=${cond2_enabled} OR cond2 = ?)
看起来不错,易于理解,编译器可以很好地处理它,并且基于运行时成本的优化器可以更好地理解它,并且更有可能选择正确的索引。
我对注射的东西特别小心。出于所有显而易见的原因,传递变量的主要方式是并且仍然是绑定变量。