0

尝试将参数绑定到 PDO 准备语句时,我得到了非常令人沮丧的结果。

结果是这个错误: 你的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“项目”附近使用正确的语法

该错误清楚地表明,表 'items' 不应该被单引号引用。我在下面做了一个小测试。如您所见,我并没有将参数放在语句中的引号中,这可能是大多数人最初的猜测。我知道它与 BindParam/BindValue 函数有关(我都尝试过,结果相同),因为如果通过将 $params 设置为 null 并在语句中将 ':table' 替换为 'items' 来绕过 bindParams 函数,它工作得很好。

<?php

echo 'started test...';

//connect to database

try {
    $dbHandle = new PDO('mysql:dbname=mydatabase;host=mysql.mywebsite.com', 'myuser', 'mypass');   
} catch (PDOException $e) {
    echo 'Database connection failed: ' . $e->getMessage();    
}

//print out the contents of table 'items'

print_r(query("SELECT * FROM :table", array("table" => "items"), $dbHandle));

//the query() function used above

function query($query_str, $params = null, $dbHandle) {

    $stmt_obj = $dbHandle->prepare($query_str);

    if($params != null) {           
        bindParams($stmt_obj, $params);
    }

    $stmt_obj->execute();

    //debug stuff
    echo '<pre>';   
    echo 'ERROR: ';
    $error = $stmt_obj->errorInfo();        
    echo $error[2].'<br /><br />';
    echo 'DEBUG DUMP:<br />';
    $stmt_obj->debugDumpParams();
    echo '</pre>';

    if (preg_match("/SELECT/i", $query_str)) {
        $result = array();      
        while ($row = $stmt_obj->fetch(PDO::FETCH_ASSOC)) {         
            array_push($result, $row);
        }
        unset($stmt_obj);
        return $result;
    }   

}

function bindParams($stmt, $params) {   
    if(is_object($stmt) && ($stmt instanceof PDOStatement))
    {           
        foreach($params as $key => $value)
        {            
            if(is_int($value)) {
                $param = PDO::PARAM_INT; 
            } elseif(is_bool($value)) {
                $param = PDO::PARAM_BOOL;
            } elseif(is_null($value)) {
                $param = PDO::PARAM_NULL;
            } elseif(is_string($value)) {
                $param = PDO::PARAM_STR;
            } else {
                $param = FALSE;
            }
            if($param) {                                                        
                $stmt->bindValue(":$key", $value, $param);                  
            }
        }
    }

有谁愿意让我摆脱痛苦并指出我错过的一些非常明显的事情?

4

1 回答 1

1

准备好的语句中的符号只是值的占位符,而不是标识符,因此您不能创建具有动态列或表名的准备好的语句。所有数据库引用都需要在准备时解决。即使这不是真的,PDO/MySQL 怎么知道:table占位符是字面量还是标识符?他们有不同的报价规则。

此限制对所有数据库系统和所有 API 中的预准备语句都很常见。这当然不是 PDO 错误。

于 2012-01-07T05:33:23.923 回答