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

PHP拼接PostgreSQL查询时字符串编码异常问题求助

问题排查与解决方案

问题现象

PHP函数查询PostgreSQL时,当shipper参数为"J&T",SQL语句中原本的UPPER('%Cargo%')输出变为UPPER('Êrgo%');使用urlencode处理后,查询结果与pgAdmin手动执行的正确结果不符。

根本原因

  1. 字符编码不匹配:PHP运行环境、PDO数据库连接、PostgreSQL数据库/表的编码未统一,导致字符串拼接时出现乱码。
  2. SQL直接拼接变量:手动拼接SQL语句不仅存在严重的SQL注入风险,还容易引发编码转义错误。

解决方案

1. 统一字符编码为UTF-8

  • PDO连接时指定编码:修改DB_DSN,添加字符集参数,确保连接编码与数据库一致:
    // 示例DB_DSN格式
    define('DB_DSN', 'pgsql:host=your_host;dbname=your_db;charset=utf8');
    
  • 确认数据库编码:在pgAdmin中检查数据库、t_vbak表及shipper字段的编码为UTF8。
  • PHP文件编码:确保你的PHP文件以UTF-8无BOM格式保存。

2. 使用PDO参数绑定重构代码

彻底抛弃SQL字符串拼接,改用参数绑定,由PDO自动处理编码和转义,同时杜绝SQL注入:

public function checkEkspedisi2($resi_no, $shipper)
{
    $return = array();
    // 连接时指定编码
    $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 可选:开启错误捕获

    $sql = "SELECT resi_no FROM t_vbak WHERE resi_no = :resi_no ";
    $params = [':resi_no' => $resi_no];

    $shipperClean = strtoupper(str_replace(' ', '', trim($shipper)));
    if ($shipper == "J&T") {
        $sql .= " AND UPPER(REPLACE(shipper, ' ', '')) LIKE :shipper_pattern 
                  AND UPPER(REPLACE(shipper, ' ', '')) NOT LIKE :exclude_pattern";
        $params[':shipper_pattern'] = "%{$shipperClean}%";
        $params[':exclude_pattern'] = "%CARGO%"; // 直接写大写,避免重复UPPER处理
    } else {
        $sql .= " AND UPPER(REPLACE(shipper, ' ', '')) LIKE :shipper_pattern";
        $params[':shipper_pattern'] = "%{$shipperClean}%";
    }

    $stmt = $conn->prepare($sql);
    $stmt->execute($params);
    
    // 直接获取所有结果,简化循环
    $return = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $stmt = null;
    $conn = null;
    return $return;
}

3. 为什么urlencode没用?

urlencode是用于处理URL参数的编码函数,会将普通字符转换为%XX格式的URL编码,这会导致SQL查询的匹配内容完全偏离预期,因此不能用于数据库查询的编码处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:25:57