简体   繁体   English

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

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

I build SQL query with a method and then return it and use it.我用一个方法构建 SQL 查询,然后返回它并使用它。

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

Unfortunately this throw me an error:不幸的是,这给我带来了一个错误:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; SQLSTATE[42000]:语法错误或访问冲突:1064 你的 SQL 语法有错误; check the manual that corresponds to your MySQL server version for the right syntax to use near ''SELECT * FROM candidates WHERE firstname = ?检查与您的 MySQL 服务器版本相对应的手册,了解在“SELECT * FROMCandidate WHERE firstname = ?”附近使用的正确语法。 AND surname = ?','Dante', 'Hickman' at line 1 AND surname = ?','Dante', 'Hickman' 在第 1 行

I was searching for it because this looks like SQL syntax fail of previous script which build query so I did simple thing I dump this $query before I used it.我正在搜索它,因为这看起来像之前构建查询的脚本的 SQL 语法失败,所以我做了简单的事情,我在使用它之前转储了这个 $query。

Dump return this:转储返回:

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

Which is correctly, string with 81 chars.这是正确的,字符串包含 81 个字符。 After this, I try to put this to original query instead of variabile and it looks like this:在此之后,我尝试将其置于原始查询而不是变量中,它看起来像这样:

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

This secod script run correcty so it looks query is build correctly, but still error.此 secod 脚本运行正确,因此看起来查询构建正确,但仍然出错。 I am missing something?我错过了什么?

I hope for any advise which can help me solve this problem.我希望任何可以帮助我解决这个问题的建议。

ps Syntax of that query is from nette framework but system should be the same. ps 该查询的语法来自 nette 框架,但系统应该是相同的。

EDIT: adding buildSearchQuery()编辑:添加 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;
        }
    }

The comments above are correct, you are passing a string as the only argument, instead of multiple arguments query expects.上面的评论是正确的,您将字符串作为唯一参数传递,而不是query期望的多个参数。

One possible solution is creating an array and calling the method with array items as arguments (eg using call_user_func_array ).一种可能的解决方案是创建一个数组并使用数组项作为参数调用该方法(例如使用call_user_func_array )。 You can however do better.然而,你可以做得更好。

Nette\\Database is quite powerful and it can build the query for you. Nette\\Database非常强大,它可以为您构建查询。 When you pass an associative array like ["column1" => "value1", "column2" => "value2"] as the only argument of where method, it will create corresponding WHERE column1 = 'value1' AND column2 = 'value2' clause.当你传递一个像["column1" => "value1", "column2" => "value2"]这样的关联数组作为where方法的唯一参数时,它会创建相应的WHERE column1 = 'value1' AND column2 = 'value2'条款。 And of course it will securely escape the values to prevent SQL injection.当然,它会安全地转义这些值以防止 SQL 注入。

You can, therefore, simplify your code into something like following:因此,您可以将代码简化为如下所示:

$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);

No if–else statement is needed as when the array is empty, NDB correctly doesn't append the WHERE clause.不需要 if-else 语句,因为当数组为空时,NDB 不会正确附加 WHERE 子句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM