SQLSTATE[42000]:语法错误或访问冲突 [PHP]

SQLSTATE[42000]: Syntax error or access violation [ PHP ]

我使用方法构建 SQL 查询,然后 return 并使用它。

$query = $this->buildSearchQuery($searchParams);            
return $this->db->query($query);

不幸的是,这会给我一个错误:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''SELECT * FROM candidates WHERE firstname = ? AND surname = ?','Dante', 'Hickman' at line 1

我正在搜索它,因为这看起来像 SQL 以前构建查询的脚本的语法失败所以我做了简单的事情我在使用它之前转储了这个 $query。

转储return这个:

"'SELECT * FROM candidates WHERE firstname = ? AND surname = ?','Dante', 'Hickman'" (81)

这是正确的,81 个字符的字符串。 在此之后,我尝试将其放入原始查询而不是变量,它看起来像这样:

return $this->db->query('SELECT * FROM candidates WHERE firstname = ? AND surname = ?','Dante', 'Hickman'); 

这个 secod 脚本 运行 正确,所以它看起来查询是正确构建的,但仍然有错误。我错过了什么?

我希望任何能帮助我解决这个问题的建议。

p.s。该查询的语法来自 nette 框架,但系统应该相同。

编辑: 添加 buildSearchQuery()

function buildSearchQuery($searchParams)
    {
        $column = "";
        $values = "";
        $col = "";
        $i=0;
        // Trim to make sure user doesn't enter space there
        if((trim($searchParams->firstname)))
        {
            $column .= "firstname,";
            $i++;
        }
        if((trim($searchParams->surname)))
        {
            $column .= "surname,";  
            $i++;
        }

        if((trim($searchParams->specialization)))
        {
            $column .= "specialization,";   
            $i++;
        }           
        if($searchParams->english !== NULL)
        {
            $column .= "english,";
            $i++;
        }           
        if($searchParams->german !== NULL)
        {
            $column .= "german,";
            $i++;
        }           
        if($searchParams->russian !== NULL)
        {
            $column .= "russian,";
            $i++;
        }           
        if($searchParams->french !== NULL)
        {
            $column .= "french,";
            $i++;
        }           
        if($searchParams->school !== NULL)
        {
            $column .= "school,";
            $i++;
        }

        if((trim($searchParams->registrationDate)))
        {
            $column .= "registrationDate";
            $i++;
        }
        if($i > 0)
        {
            // If number of columns is bigger then 0 (if user fill atleast one input)                   
            $columns = explode(",", $column);       
            // Create list of values for query (name of columns and values)
            foreach($columns as $c)
            {                                                   
                if (isset($searchParams->$c)) {     
                    $values .= "'".$searchParams->{$c}."', ";               
                    $col .= $c." = ? AND ";                 
                }                       
            }
            // Remove last "," and space
            $values = substr_replace($values, "", -2);          
            $col = substr_replace($col, "", -5);    
            $query = $col."',".$values;
            $query = "'SELECT * FROM candidates WHERE ".$query;         
            //$query = substr($query, 0, -1); //remove last char ( ' in this case)
            return $query;
        }
        else
        {
            $query = "SELECT * FROM candidates";
            return $query;
        }
    }

上面的评论是正确的,您传递的是一个字符串作为唯一参数,而不是 query 预期的多个参数。

一种可能的解决方案是创建一个数组并使用数组项作为参数调用该方法(例如使用 call_user_func_array)。但是你可以做得更好。

Nette\Database是quite powerful and it can build the query for you. When you pass an associative array like ["column1" => "value1", "column2" => "value2"] as the only argument of where方法,它会创建相应的WHERE column1 = 'value1' AND column2 = 'value2'子句。当然,它会安全地转义值以防止 SQL 注入。

因此,您可以将代码简化为如下所示:

$columns = ["firstname", "surname", "specialization", "english", "german", "russian", "french", "school", "registrationDate"];
$conditions = [];
foreach ($columns as $c) {
    if (isset($searchParams->$c) && trim($searchParams->$c) !== "") {
        $conditions[$c] = $searchParams->{$c};
    }
}
return $this->db->table('candidates')->where($conditions);

不需要 if–else 语句,因为当数组为空时,NDB 不会正确地附加 WHERE 子句。