变量为 false 时的 where 子句不会将其考虑到 SQL 查询中?
Posted
技术标签:
【中文标题】变量为 false 时的 where 子句不会将其考虑到 SQL 查询中?【英文标题】:Where clause when variable is false doesn't consider that into the SQL query? 【发布时间】:2018-07-14 03:53:11 【问题描述】:我有一些我不太明白的东西,我有解决方案,但我不知道为什么,这让我有点抓狂
控制器
DB::connection()->enableQueryLog();
$transfer = Transfer::where('ticket_id', $last_ticket)->where('event_id', 36)->where('buyer', $user_email)->first();
$queries = DB::getQueryLog();
dd($queries);
结果
array:1 [
0 => array:3 [
"query" => "select * from `transfers` where `ticket_id` = ? and `event_id` = ? and `buyer` = ? limit 1"
"bindings" => array:3 [
0 => false
1 => 36
2 => "[email protected]"
]
"time" => 0.36
]
]
情况:
数据库中的$last_ticket
是唯一的,绝不是null
、空或false
。
在我的示例中$last_ticket
是false
,但在数据库中没有任何false
,为什么我仍然得到结果?
是不是因为每当条件为假时,它就不会将其纳入等式?
所以问题是: 我该怎么做才能收到正确的结果含义:如果 $last_ticket 为 false 则没有结果,如果它有一些数据,则返回受 $last_ticket 限制的行结果
一种选择可能是输入if($last_ticket == false)$last_ticket='randomInexistentString_ag4dh&2g32y4t'
,这样它就不是空值或零,但我认为这不是更漂亮的方法
【问题讨论】:
您能否提供“transfers”表架构,并具体说明“ticket_id”列数据类型和约束? 返回结果集中ticket_id 字段的值是多少? (我猜它是 0)。 @Shadow 为 false 可能与 0 相同 我对返回值感兴趣,而不是您提供的参数。这会告诉我们发生了什么。 啊抱歉,根据帖子中的调试结果,您的意思返回的值也是 false .. 还是您在问另一个值? 【参考方案1】:mysql 中的零总是匹配任何不以数字开头的字符串 - 这是因为它希望比较的两边是相同的类型,因此它将字符串转换为数字,并且任何字符串不以数字开头,自动计算为0
。
现在,你不是给它一个0
- 但你给它一个false
,在MySQL中,这不是一个真正的布尔值,而是一个0
。
在不确切知道您的数据库是什么样子的情况下,我会说这是最可能的解释。
有一些方法可以解决这个问题,例如,您可以在 Eloquent 上使用 ->when()
链接:
Transfer::where('event_id', 36)
->where('buyer', $user_email)
->when($last_ticket, function ($query) use ($last_ticket)
$query->where('ticket_id', $last_ticket);
)
->first();
(凭记忆,语法可能有点偏差。感谢 Rick James 对 cmets 的修正。)
【讨论】:
哦,谢谢,我不知道 0,如果我用 null 喂它? 我认为这是同一件事,但我真的不确定。 加分 ;) 我在同一个主题中添加了一个问题,如果 last_ticket 为零或 null,如何返回 none 你的额外问题有点奇怪 - 这是一个纯粹的 if 条件,所以你为什么不直接做if ($last_ticket) do things else don't do things
?
@JoelHinz - 不。零匹配任何不以数字开头的字符串。在将字符串转换为数字时,它会消耗前导数字(如果存在)。【参考方案2】:
重新设计用户界面。如果某些内容应该被排除在查询之外,那么不要将其包含在查询中。
也就是说,动态构建WHERE
子句,以便在提供“false”时变为
WHERE `event_id` = ? and `buyer` = ?
我不了解 Laravel,但是在 php 中,我会构建一个数组到 AND
一起,然后构造 WHERE
:
$ands = array();
if (...) $ands[] = "ticket_id = ...";
if (...) $ands[] = "event_id = ...";
if (...) $ands[] = "buyer = ...";
if (empty($ands))
$where = '';
else
$where = 'WHERE ' . implode(' AND ', $ands);
$sql = "SELECT ... $where ...";
请注意,它可以轻松处理任何或全部或没有被省略的项目。
【讨论】:
在 laravel 查询构建器中,您可以传递一个条件数组:->where(['ticket_id' => 7, 'event_id' => 5])
。见第一条评论here。你甚至应该能够传递一个空数组,所以你不需要检查if (empty($ands))
。以上是关于变量为 false 时的 where 子句不会将其考虑到 SQL 查询中?的主要内容,如果未能解决你的问题,请参考以下文章
SQL HELP - 基于 BIT 变量的条件 where 子句 - SQL Server