假设下表:
╔═══╦══════════════╦═════════════╗
║ ║Property A ║Property B ║
╠═══╬══════════════╬═════════════╣
║ 1 ║ slow ║low ║
║ 2 ║ fast ║high ║
╚═══╩══════════════╩═════════════╝
用户可以选择使用两个属性或一个属性筛选结果。输入存储在变量中 $p1, $p2
如果这两个变量都从用户那里得到一个值,我可以像这样轻松地查询它们:
select * from table where (propertyA=$p1 and propertyB=$p2)
但是,如果其中一个没有从用户那里得到任何值,我该如何查询?因为在上面的查询中 propertyA=$p1
从那以后就变成假的了 $p1
可以为null,但查询结果应基于的值返回 $p2
.
例如,对于输入(null,low),查询应该返回第一条记录,但是对于我的查询,它不会返回。
这个例子只针对两个属性,我的表中有多个属性,所以实现多个if条件会很麻烦。
我想知道有没有什么简洁的方法来处理这个问题。
谢谢您!
3条答案
按热度按时间nuypyhwy1#
好吧,查询是一个字符串毕竟,你需要先格式化字符串,根据条件,然后当最后一个字符串准备好,执行查询。
希望这有帮助,谢谢
kkbh8khc2#
如果两个属性都是字符串,则可以使用通配符
'%'
```select * from table where (propertyA like $p1 and propertyB like $p2)
c90pui9n3#
解决这个问题有两种基本方法:1)动态生成sql语句,2)在静态sql语句中用表达式处理null
动态方法,如果查询是从应用程序执行的。。。
我们从一个静态字符串开始,每次查询都是这样的:
然后决定是否要在where子句中附加另一个条件
动态sql的缺点是,对于更复杂的问题,正确地构造sql语句可能会变得非常棘手。有着公正的社会条件
WHERE
这是一个可行的方法。另一个缺点是,我们最终可以生成各种各样的sql语句,确保每个变体都有合适的执行计划变得复杂。where子句中只有两个可选条件,我们总共有4个变体。。。
哦,包括这个条件的原因
1=1
在WHERE
子句不影响语句;优化器足够聪明,可以找出每一行的值都是真的,所以条件会被抛出。当我们附加到WHERE
子句中,我们不再需要检查“这是where子句中的第一个条件吗?”这样我们就知道是否要附加WHERE
或者AND
对声明的回应。第二种方法是在sql中使用static,使用一些表达式。
例如,假设propertya和propertb是字符类型列:
如果我们提供一个非零长度的字符串
:p1
,然后NULLIF
函数返回:p1
,ifnull函数返回:p1
. 就好像我们刚刚写了:如果我们提供一个零长度的字符串
$p1
(用于占位符):p1
)然后是sqlNULLIF
函数将返回null。反过来IFNULL
函数将返回t.propertyA
,因此语句将进行比较propertyA
因此最终结果将如我们所写或者只是
(区别在于优化器不会放弃我们的条件,因为优化器不知道我们准备执行计划时为p1提供什么值。
注:以下为
<=>
spaceship运算符是空安全比较。它保证返回true或false(不返回null),这与标准的相等比较不同(=
)当被比较的值中的一个(或两个)为null时,返回null。这是:
基本上是等价物的简写:
如果我们保证
propertyA
将永远不会为null(例如,通过表定义中的显式notnull约束),我们可以放弃spaceship操作符,只使用简单的相等比较。这种方法的缺点是sql语句不够直观;不知情的人可能会为此挠头。所以我们要在代码中留下一个注解,解释匹配的条件是condition,if
:p1
是空字符串,与:p1
.我们可以使用不同的语法来实现相同的结果,例如,使用更具可移植性的符合ansi标准的语法
COALESCE
功能代替IFNULL
,和CASE
表达式代替NULLIF
. (那就需要我们提供$p1
一个额外的占位符,写它像我们做的,我们只需要提供$p1
一次。)但这是两种基本模式。摘下你的毒药。