变量为 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_ticketfalse,但在数据库中没有任何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 对 cme​​ts 的修正。)

【讨论】:

哦,谢谢,我不知道 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

删除 where 子句然后添加回来时的执行计划优化

在聚集字段上使用 WHERE 子句运行查询时,Google BigQuery 聚集表不会减少查询大小

查询索引视图时的 WHERE 子句性能

使用 JOIN 时的 WHERE 子句与 ON

sql 基础语句