返回

PDO 预处理语句 LIKE 子句字符转义问题解决之道

php

PDO 预处理语句 LIKE 子句中的字符转义问题

前言

在使用 PHP 的 PDO 扩展来执行数据库查询时,使用 LIKE 子句有时会遇到一个令人讨厌的问题:某些特殊字符意外地被转义。这会导致查询结果不准确,令人沮丧。本文将探讨导致此问题的根源,并提供一个经过验证的解决方案。

问题根源

当 LIKE 子句中的值包含某些特殊字符时,PDO 会错误地将它们转义。例如,当值包含百分号 (%) 时,PDO 会将其转义为 Unicode 字符 Ê(U+00C3)。这会导致 LIKE 子句中的值与数据库中的值不匹配,从而产生错误的结果。

解决方案

要解决此问题,我们需要使用 PDO 的参数化查询。参数化查询允许我们绑定 LIKE 子句中的值作为参数,PDO 将确保它们不会被转义。

为此,我们可以使用 bindValue() 方法:

$stmt->bindValue('parameter_name', $value, PDO::PARAM_STR);

在我们的例子中,我们需要将 LIKE 子句中的值绑定为字符串参数:

$stmt->bindValue('shipper_parameter', '%' . strtoupper(trim($shipper)) . '%', PDO::PARAM_STR);

通过使用参数化查询,我们可以防止特殊字符被转义,确保 LIKE 子句正确地执行。

示例

以下是一个使用参数化查询修改后的 PHP 代码示例:

public function checkEkspedisi2($resi_no, $shipper)
{
    $return = array();
    $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);

    $sql = "SELECT resi_no FROM t_vbak WHERE resi_no = ?";

    if ($shipper == "J&T") {
        $sql .= " AND (UPPER(REPLACE(shipper,' ','')) LIKE ?) AND (UPPER(REPLACE(shipper,' ','')) NOT LIKE ?)";
    } else {
        $sql .= " AND UPPER(REPLACE(shipper,' ','')) LIKE ?";
    }

    $stmt = $conn->prepare($sql);

    $stmt->bindValue(1, $resi_no, PDO::PARAM_STR);

    if ($shipper == "J&T") {
        $stmt->bindValue(2, '%' . strtoupper(trim($shipper)) . '%', PDO::PARAM_STR);
        $stmt->bindValue(3, '%Cargo%', PDO::PARAM_STR);
    } else {
        $stmt->bindValue(2, '%' . strtoupper(trim($shipper)) . '%', PDO::PARAM_STR);
    }

    if ($stmt->execute()) {
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $return[] = $row;
        }
    }

    $stmt = null;
    $conn = null;

    return $return;
}

结论

使用参数化查询和 bindValue() 方法,我们可以有效地解决 PDO 预处理语句中的 LIKE 子句字符转义问题。这种方法确保了 LIKE 子句中的值不会被转义,从而产生了准确的查询结果。

常见问题解答

  • 为什么使用参数化查询很重要?
    • 参数化查询防止特殊字符被转义,确保 LIKE 子句正确执行。
  • 我应该在 WHERE 子句中始终使用参数化查询吗?
    • 不,仅当 LIKE 子句中的值包含特殊字符时,才需要使用参数化查询。
  • 是否可以将参数绑定为整数或布尔值?
    • 可以,bindValue() 方法允许您绑定各种数据类型。
  • 如果我忘记将参数绑定到语句,会怎样?
    • PDO 会抛出一个异常,通知您缺少参数。
  • 如何处理复杂的 LIKE 子句,例如带有多个通配符?
    • 您可以通过将通配符绑定为单独的参数来处理复杂的 LIKE 子句。