如何在 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 查询的主要内容,如果未能解决你的问题,请参考以下文章