【问题标题】:Laravel 4 DB::raw query with IN in the WHERE clause doesn't work with parameter with MySQL在 WHERE 子句中使用 IN 的 Laravel 4 DB::raw 查询不适用于 MySQL 的参数
【发布时间】:2014-04-18 17:03:12
【问题描述】:

当我在 Laravel 4 中对 MySQL 进行 DB:selectDB:raw 查询时,它不会返回任何结果。 (注意,我已经截断了这个例子的实际查询。)

SELECT user_id, email, first_name, last_name, photo_small
FROM users AS u
JOIN profiles AS p ON p.user_id = u.id
 WHERE email IN (?) ....

其中 $p= "email.address1@com","xyz.xxx@.edu" 而 $p 是参数

当我执行以下操作时

SELECT user_id, email, first_name, last_name, photo_small
FROM users AS u
JOIN profiles AS p ON p.user_id = u.id
 WHERE email IN ("email.address1@com","xyz.xxx@.edu") ....

我确实得到了结果。

我已经确认了参数的值,使用DB::getQueryLog() 检查了 SQL 和绑定,并使用单独的数据库工具验证了结果。

出于显而易见的原因,我真的很想避免使用未参数化的查询,但似乎无法让它返回任何内容,即使它是有效的 SQL

欢迎提出任何建议。

【问题讨论】:

  • 你是如何传递参数的?实际调用是什么。

标签: mysql laravel laravel-4


【解决方案1】:

像这样动态参数化值怎么样?这是一个 Id 列表,但我相信您可以看到如何将其调整为电子邮件。

public function getDataByIds($idArray)
{
    $parametersString="";
    $parameters=[];
    for($i=0; $i<count($idArray);$i++)
    {
        $parameterName = ":id" . $i;
        $parametersString .= $parameterName . ",";
        $parameters[$parameterName]=$idArray[$i];
    }
    $parametersString=substr($parametersString, 0, -1);
    $query = $this->getQuery("SELECT blah WHERE id IN (".$parametersString.")");
    return DB::select(DB::raw($query), $parameters);
}

【讨论】:

    【解决方案2】:

    这种方法不起作用,因为底层机制是 PDO,它需要每个参数都有一个值。您试图欺骗它接受以逗号分隔的参数列表,但这不起作用。

    请参阅PDO with "WHERE... IN" queries 了解解决方法。您可以使用 majimboo 提供的内容并添加一些代码,这些代码将通过您的值数组并生成您的 in 语句,如下所示:

    WHERE id IN (:val1, :val2, etc)
    

    或者您可以将其呈现为:

    WHERE id IN (?, ?, ?)
    

    然后传递实际替换值的数组应该被接受。

    不过,我同意 majimboo 的观点,您应该能够使用查询构建器进行此查询。它有 whereIn() 方法可以帮助您处理这部分查询,并且您不必编写自己的查询语法生成代码。

    【讨论】:

    • 啊哈。我会尝试确认。
    【解决方案3】:

    我与 DB::select() 有一条相同的船...我还没有找到任何好的解决方案,除了这个:

    PDO with "WHERE... IN" queries

    $array = [...];
    $stringList = implode(",", $array);
    $result = DB::select('....... WHERE id IN ('.$stringList.')');
    

    所以参数实际上不是参数而是准备好的字符串,你可以将它注入到 SQL 查询中。它绝对不优雅也不安全,但我发现这是唯一一个可行的解决方案。确保在注入之前创建子字符串时检查了所有可能的情况!

    【讨论】:

    • 不使用绑定/准备好的语句。
    【解决方案4】:

    尝试类似:

    $array = [...];                    // your array
    $strArray = implode(",", $array);  // covert it to a comma delimited string
    DB::raw("
    ...
    WHERE email IN ($strArray)         // call the comma delimited string of the array
    ...
    ");
    

    应该与DB::select() 相同
    但是你为什么不使用 Eloquent?


    也可以使用单引号,例如:$p = "'email.address1@com', 'xyz.xxx@.edu'";


    只是说清楚

    警告双重检查

    $results = DB::select('SELECT * FROM users WHERE id IN (?)', array($strArray));
    

    另一个想法

    DB::select( 
      DB::raw("SELECT * FROM my_table WHERE id IN (:strArray)"), array(
        'strArray' => $strArray
      )
    );
    

    【讨论】:

    • 问题是如何传递绑定参数并让它在IN中工作。
    • @gview 就像我说的,Should work the same with DB::select()。虽然更新了我的答案。干杯。哦等等。
    • 为什么没有 Eloquent,我是新手,我需要一个 not in 子选择和联合。
    猜你喜欢
    • 2020-06-10
    • 1970-01-01
    • 2010-10-03
    • 2020-10-13
    • 2013-05-03
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    相关资源
    最近更新 更多