You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用PDO执行MariaDB动态透视SQL报1064语法错误求解决

问题原因

  • PDO默认禁止单次执行多条SQL语句,你把SET、SELECT、PREPARE、EXECUTE等多个SQL语句拼接后一次性传入prepare()执行,直接触发语法报错。
  • PHP代码中SQL字符串拼接存在语法错误:你给第一句$sql1 = "SET @sql = NULL;";末尾加了赋值结束的分号,下一行直接以.开头拼接字符串属于PHP语法错误,最终拼接出来的SQL内容本身就是残缺的。
  • MySQL默认GROUP_CONCAT函数长度限制为1024字节,如果你的meta_key数量较多,拼接出来的动态SQL会被截断,也会导致语法错误。

修复方案

方案1(更稳妥,完全避免MySQL动态SQL风险)

直接在PHP侧拼接透视SQL,不需要依赖MySQL用户变量:

global $con;
$hasil = array();
try {
    // 第一步:先查询所有需要透视的meta_key
    $stmt = $con->query("SELECT DISTINCT meta_key FROM wp_frmt_form_entry_meta RIGHT JOIN wp_frmt_form_id ON wp_frmt_form_entry_meta.meta_key = wp_frmt_form_id.meta_keyy ORDER BY wp_frmt_form_entry_meta.meta_id");
    $metaKeys = $stmt->fetchAll(PDO::FETCH_COLUMN);

    // 第二步:在PHP侧拼接透视字段部分
    $selectFields = ["`entry_id`"];
    foreach ($metaKeys as $key) {
        // 转义key避免SQL注入
        $escapedKey = $con->quote($key);
        $selectFields[] = "MAX(IF(`meta_key` = $escapedKey, `meta_value`, '')) AS `" . str_replace("`", "``", $key) . "`";
    }

    // 第三步:拼接完整的查询SQL执行
    $sql = "SELECT " . implode(',', $selectFields) . " FROM wp_frmt_form_entry_meta s GROUP BY s.`entry_id` ORDER BY s.`entry_id`";
    $stmt = $con->query($sql);
    $rs = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if($rs){
        foreach ($rs as $i => $val) {
            $hasil[$i]['name-1'] = $val['name-1'] ?? '';
            // 其余字段按需求处理
        }
    }
} catch (Exception $e) {
    echo 'Error getAllData = '.$e->getMessage();
}
return $hasil;

方案2(保留原SQL逻辑,修复执行方式)

如果要保留原MySQL动态SQL逻辑,需要调整配置和代码:

  1. 初始化PDO的时候开启模拟预处理,支持多语句执行:
$con = new PDO("mysql:host=你的数据库地址;dbname=库名;charset=utf8mb4", '账号', '密码', [
    PDO::ATTR_EMULATE_PREPARES => true,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
  1. 修复SQL字符串拼接错误,去掉第一行赋值后的多余分号:
$sql1 = "SET @sql = NULL;"
."SELECT GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(`meta_key` = \"', `meta_key`,'\", `meta_value`,\"\")) AS \"',`meta_key`,'\"')) INTO @sql 
FROM wp_frmt_form_entry_meta 
RIGHT JOIN wp_frmt_form_id
ON wp_frmt_form_entry_meta.meta_key = wp_frmt_form_id.meta_keyy
ORDER BY wp_frmt_form_entry_meta.meta_id;

SET @sql = CONCAT('SELECT `entry_id`,  ', @sql, ' 
FROM wp_frmt_form_entry_meta s
GROUP BY s.entry_id
ORDER BY s.entry_id');

PREPARE a FROM @sql;
EXECUTE a;";
  1. 提前修改MySQLGROUP_CONCAT长度限制,避免SQL截断:在执行动态SQL前先执行$con->query("SET SESSION group_concat_max_len = 102400;");

注意事项

  • 多语句执行存在SQL注入风险,优先选择方案1在PHP侧拼接SQL,可控性更高。
  • 所有动态拼接到SQL中的字段值都要做好转义处理,避免注入风险。

内容的提问来源于stack exchange,提问作者Paulus Andry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 13:45:03