PHP拼接PostgreSQL查询时字符串编码异常问题求助
问题排查与解决方案
问题现象
PHP函数查询PostgreSQL时,当shipper参数为"J&T",SQL语句中原本的UPPER('%Cargo%')输出变为UPPER('Êrgo%');使用urlencode处理后,查询结果与pgAdmin手动执行的正确结果不符。
根本原因
- 字符编码不匹配:PHP运行环境、PDO数据库连接、PostgreSQL数据库/表的编码未统一,导致字符串拼接时出现乱码。
- 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
相关产品推荐
相关产品推荐

