在 PDO 中的执行函数中将 NULL 值绑定到具有关联数组的命名占位符的问题

Posted

技术标签:

【中文标题】在 PDO 中的执行函数中将 NULL 值绑定到具有关联数组的命名占位符的问题【英文标题】:Problem with binding NULL value to named placeholders with associative array in execute function in PDO 【发布时间】:2020-05-26 05:16:38 【问题描述】:

table_nameconditional_clauses 以 OOP 方式作为参数传递时,我正在尝试构造和执行删除查询。我通过将 PDO 包装在自定义包装器中来使用它。我正在使用带有命名占位符的准备好的语句。在每种情况下,我都会在 PDO->execute() 函数中传递一个关联数组,其中 array_keys 是使用的占位符的名称,而 array_value 是要替换的相应值。当我想用 WHERE 子句指定 IS NULL 条件时,我只在一种情况下遇到问题。

基本上,如果我想搜索以下内容:

SELECT * FROM EMPLOYEES WHERE salary > 10000 AND skill IS NULL

我能够动态构建一个准备好的语句,如下所示:

$sql = SELECT * FROM employees WHERE salary > :salary AND skill IS :skill

然后将准备好的SQL执行为:

$stmt->execute(["salary" => 10000,
                "skill" => null])

这就是我面临的问题。仅当值为 null 时,我才会在这里遇到致命错误。而且,我想在我的包装器中包含检查 IS NULL 功能。

请注意-

我想在不使用 bindValue() 的情况下达到目的或 bindParam() 函数。

我已关闭仿真(因为 mysql 可以将所有占位符排序出来 正确)。

使用 ? 作为占位符不是我的选择。我将不得不 否则重新设计我的整个代码库。

这里的代码sn-p供参考:

<?php
class DeleteQuery 
        protected function where(array $whereCondition, array &$values): string
        $whereClause = ' WHERE ';
        $i = 0;
        $j = 0;

        $hasComparators = array_key_exists("comparators", $whereCondition);
        $hasConjunctions = array_key_exists("conjunctions", $whereCondition);

        $comparatorCount = $hasComparators ? count($whereCondition["comparators"]) : 0;
        $conjunctionCount = $hasConjunctions ? count($whereCondition["conjunctions"]) : 0;

        foreach ($whereCondition["predicates"] as $predicate_key => &$predicate_value) 
            $whereClause .= $predicate_key;

            $whereClause .= ($hasComparators and ($i < $comparatorCount)) ?
            ' ' . $whereCondition["comparators"][$i++] . ' ' : ' = ';

            if (is_array($predicate_value)) 
                $whereClause .= "('" . implode("', '", $predicate_value) . "')";
                unset($whereCondition['predicates'][$predicate_key]);
             else 
                $whereClause .= ':' . $predicate_key;
            

            $whereClause .= !($hasConjunctions and ($j < $conjunctionCount)) ?
            '' : ' ' . $whereCondition["conjunctions"][$j++] . ' ';
        

        $values = array_merge($values, $whereCondition['predicates']);

        return $whereClause;
    

    public function delete($tblName, $conditions) 
        $sql = "DELETE FROM " . $tblName;
        $values = [];

        if (!empty($conditions) && is_array($conditions)) 
            /* If the stmt has WHERE clause */
            if (array_key_exists("where", $conditions)) 
                $sql .= $this->where($conditions['where'], $values);
            

            /* If the stmt has ORDER BY clause */
            if (array_key_exists("order_by", $conditions)) 
                $sql .= $this->order_by($conditions['order_by']);
            

            /* If the stmt has LIMIT clause */
            if (array_key_exists("limit", $conditions)) 
                $sql .= $this->limit($conditions['limit'], $values);
            
        

        echo $sql . PHP_EOL;
        print_r($values);
    


$deleteConditions = [
    "where" => array(
        "predicates" => ["skill" => null],
        "comparators" => ["IS"],
    ),

    /* other conditional clauses */

];
$obj = new DeleteQuery();
$obj->delete("employees", $deleteConditions);

【问题讨论】:

显然你不能绑定NULL 【参考方案1】:

IS 运算符不能与表达式一起使用。 IS NULLIS NOT NULL 是关键字。

您需要一个适用于空值和非空值:skill 的测试。您可以使用空安全相等运算符&lt;=&gt;

$sql = 'SELECT * 
        FROM employees 
        WHERE salary > :salary 
        AND skill <=> :skill';

【讨论】:

你能帮我看看我可以用什么来检查IS NOT NULL吗? AND NOT skill &lt;=&gt; :skill 如果你想查找不等于参数的东西。 我会做IS NULLIS NOT NULL。但问题是我正在考虑 $conditions[] 数组如下:$conditions = ["predicates" =&gt; ["sal" =&gt; 10000, "skill" =&gt; null], "comparators" =&gt; ["&gt;" , "&lt;=&gt;"], "conjunctions" =&gt; ["AND"]]; 然后,我使用上面的代码将这些片段连接在一起形成一个循环。所以我想要一个通用的解决方案,如果可能的话。如果我把 comparator 当作 `IS NOT NULL`,那么它会导致错误,因为在 predicates 中没有匹配的操作数(值) 如果你想要一个 ORM,也许你应该安装 Laravel 之类的东西,而不是试图重新发明***。 我已经浏览了它们。我想做这个活动,因为它很有趣,并且有助于我的代码编写和分解能力。对于实际的生产工作,我会使用 Eloquent 或 Doctrine 之类的东西。

以上是关于在 PDO 中的执行函数中将 NULL 值绑定到具有关联数组的命名占位符的问题的主要内容,如果未能解决你的问题,请参考以下文章

将值和数组添加到 PDO 执行方法

为啥在特殊成员函数中将 r 值绑定到 const 左值引用是非法的?

PHP PDO - 绑定表名? [复制]

PDO 使用 foreach 绑定 n 次相同的值

PDO从先前选择插入的绑定参数

循环内 PDO 语句的绑定参数