如何在 laravel 中执行复杂的 mysql 查询

Posted

技术标签:

【中文标题】如何在 laravel 中执行复杂的 mysql 查询【英文标题】:how to execute complex mysql queries in laravel 【发布时间】:2021-09-11 14:32:55 【问题描述】:

我有一个下面的 mysql 查询,它工作正常,但我想使用准备语句运行它。

SET @sql = NULL;

SELECT GROUP_CONCAT(CONCAT("SELECT '",colname,":' AS 'Label',GROUP_CONCAT(JSON_UNQUOTE(JSON_EXTRACT(attr_details,'$.", colname,"'))) AS 'val' FROM mytable GROUP BY Label") SEPARATOR " UNION ")
       INTO @sql
FROM
(WITH RECURSIVE data AS (
  SELECT attr_details,JSON_VALUE(JSON_KEYS(attr_details), '$[0]') AS colname, 0 AS idx FROM mytable
  UNION
  SELECT attr_details,JSON_VALUE(JSON_KEYS(attr_details), CONCAT('$[', d.idx + 1, ']')) 
  AS colname, d.idx + 1 AS idx FROM data AS d
  WHERE d.idx < JSON_LENGTH(JSON_KEYS(attr_details)) - 1
) SELECT colname
FROM data
GROUP BY colname) V;

PREPARE stmt FROM @sql;
EXECUTE stmt;;

现在我尝试像下面这样在 larvel 中进行转换

$PDO=DB::connection('mysql')->getPdo();
            $stmt = $PDO->prepare(<<<_OUT
SET @sql = NULL;

SELECT GROUP_CONCAT(CONCAT("SELECT '",colname,"' AS 'Label',GROUP_CONCAT(JSON_UNQUOTE(JSON_EXTRACT(attr_details,'$.", colname,"'))) AS 'val' FROM product_attributes GROUP BY Label") SEPARATOR " UNION ")
       INTO @sql
FROM
(WITH RECURSIVE data AS (
  SELECT attr_details,JSON_VALUE(JSON_KEYS(attr_details), '$[0]') AS colname, 0 AS idx FROM product_attributes
  UNION
  SELECT attr_details,JSON_VALUE(JSON_KEYS(attr_details), CONCAT('$[', d.idx + 1, ']')) 
  AS colname, d.idx + 1 AS idx FROM data AS d
  WHERE d.idx < JSON_LENGTH(JSON_KEYS(attr_details)) - 1
) SELECT colname
FROM data
GROUP BY colname) V;
_OUT
);
    $stmt->execute();

    $result = $stmt->fetchAll();
    echo "<pre>"; print_r($result); die;

我收到此错误 “语法错误,意外的 'SELECT' (T_STRING),期待 ')'”, 谁能帮助我做错了什么

【问题讨论】:

【参考方案1】:
SELECT GROUP_CONCAT(CONCAT("SELECT
                           ^-- this quote must be escaped like this: \"

php 认为你的 SQL 字符串到此结束。

同时检查其他引号。

编辑: 其他选项可能是将整个 SQL 包装到单引号 ('),然后转义查询中的那些 (\')

【讨论】:

SQLSTATE[42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以在第 3 行的 'SELECT GROUP_CONCAT(CONCAT(\"SELECT '\",colname,\"' AS 'Label',GROUP_CONCAT(JSON...' ) 附近使用正确的语法82号线 您的转义似乎不正确。在双引号 (") 中使用 $ 符号时可能还会出现其他错误。最好的解决方案可能是将 SQL 字符串包裹在单引号 (') 中,并像这样在查询中转义其他单引号 \' Filip Halaxa 如果您可以作为答案发布,将会很受欢迎 你能更新我尝试过的代码吗.. 真的很有帮助【参考方案2】:
    请首先检查您的报价。在代码"SELECT GROUP_CONCAT(CONCAT("SELECT 中,PHP 将其识别为完整的字符串 "SELECT GROUP_CONCAT(CONCAT(" 和未定义的 SELECT ' 与下一个字符串,没有连接。

至少对我来说,我的 IDE 将您的代码突出显示为不正确。要处理各种报价,请尝试使用该方法

$stmt = $PDO->prepare(<<<_OUT
SELECT * FROM `table` WHERE "1";
_OUT
);

    尝试编写不带@sql 变量、不带PREPARE stm 和不带EXECUTE stm 的请求。我认为,PDO 将自己处理准备和执行。

    $stmt = $PDO->prepare(

    $stmt->执行(); $stmt->fetchAll();

    尝试使用 Laravel 方法:DB::select(DB::raw($sql));

【讨论】:

SQLSTATE[42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;查看与您的 MariaDB 服务器版本相对应的手册,了解在 'SELECT GROUP_CONCAT(CONCAT(\"SELECT '\",colname,\"' AS 'Label',GROUP_CONCAT(JSON... 我已经更新了我的问题,我尝试了你建议的方式..但它仍然有错误 如果我删除 @sql 我的输出不会出现所有查询都在显示 您是否尝试在不使用 PHP 的情况下手动执行该请求?如果我理解正确,您正试图通过 SQL 端的连接来获取子查询。可能值得重写并以普通方式准备子查询(用于选择)? 并尝试仅使用like 运算符或使用JSON_CONTAINS,即where attr_details like '%something%',通过json 字段进行搜索。可能有助于简化 sql 请求。

以上是关于如何在 laravel 中执行复杂的 mysql 查询的主要内容,如果未能解决你的问题,请参考以下文章

我将如何在 Laravel Eloquent 中编写这个 MySQL 查询?

如何使用 Laravel 框架执行 MySQL 查询?

如何使用 Laravel 的查询构建器执行嵌套连接?

使用 Laravel db builder 在查询中执行 WITH MySQL 表达式

在执行查询之前,如何从 Laravel 的查询构建器中获取原始查询字符串?

如何使用 Laravel 和 MySQL 获取大量记录?