PHP PDO :: prepare() - 带占位符的SQL错误

时间:2011-09-23 11:11:48

标签: sql pdo placeholder

我的问题是我无法让占位符在我的SQL语句中工作。具体来说,在下面的代码中,当我用类似':tripsid'的值替换占位符'abcdefg'时,未按预期创建TABLE。

SQL错误是:

  

PDO :: errorInfo():数组([0] => 42000 [1] => 1064 [2] =>你有一个   SQL语法错误;查看与您的手册相对应的手册   MySQL服务器版本,用于在*''sdfghjk'附近使用正确的语法(id   INT NOT NULL,stop_start SMALLINT NOT NULL,stop_end SMA'* at line 1)

代码:

// My method to create a table with PDO and placeholders
public function routes_table()  {

    $this->connect();

    $STH = $this->DBH->prepare('CREATE TABLE IF NOT EXISTS :tripsid (
        id INT NOT NULL,
        stop_start SMALLINT NOT NULL,
        stop_end SMALLINT NOT NULL,
        distance SMALLINT NOT NULL,
        duration TINYINT NOT NULL,
        medium TINYTEXT NOT NULL,
        CONSTRAINT pk_routes PRIMARY KEY ( id )
        )');


    $tripsid = "sdfghjk";
    $STH->bindParam(':tripsid', $tripsid, PDO::PARAM_STR, 7);

    $STH->execute(); 

    // SQL Errors
    if (!$STH->execute($input)) {
        echo "\nPDO::errorInfo():\n";
        print_r($STH->errorInfo());
    }

    $this->disconnect();

}

我已经尝试了我能想到的一切。有没有人看到这个错误?

2 个答案:

答案 0 :(得分:0)

现在我知道PDO :: bindParam()自动绑定到参数的引号导致问题。有没有人知道如何从表名中删除引号所以我的代码将是......

$STH = $this->DBH->prepare('CREATE TABLE IF NOT EXISTS tablename (
            id INT NOT NULL,...

而不是

$STH = $this->DBH->prepare('CREATE TABLE IF NOT EXISTS 'tablename' (
            id INT NOT NULL,

答案 1 :(得分:0)

我看到这个问题已经过了一年多了,但我偶然发现了它并想突出显示一些内容:这与引号无关。

当出现错误并且您获得与相关语法相关的SQL片段时,它会自动包含在一对单引号周围。这通常会使它看起来好像有一个不同的问题,即双引号和单引号混合的问题。

在这个例子中 -

  

PDO :: errorInfo():数组([0] => 42000 1 => 1064 [2] =>您的SQL语法出错; 检查与MySQL服务器版本对应的手册,以便在'sdfghjk'附近使用正确的语法(id INT NOT NULL,stop_start SMALLINT NOT NULL,stop_end SMA'在第1行)

指的是:

'sdfghjk' ( id INT NOT NULL, stop_start SMALLINT NOT NULL, stop_end SMA

最外面的引号只是特定于错误输出;像我一样 - 我担心你注意到这一点,并认为你的错误是关于错误的引号。 这是一个红色的鲱鱼!删除最外面的单引号,以实际看到不正确的SQL。

至于您的真实问题:您不能将表名(或列名)指定为参数;这在大多数平台和API的准备语句中很常见。这适用于任何查询 - 选择/插入/更新等等 - 它们都不能接受表名作为参数。有关详细信息,请参阅此question here

因此,考虑到这一点,我会使用sprintf()来实现这样的目标......

$STH = $this->DBH->prepare(
    sprintf('CREATE TABLE IF NOT EXISTS %s (
        id INT NOT NULL,
        stop_start SMALLINT NOT NULL,
        stop_end SMALLINT NOT NULL,
        distance SMALLINT NOT NULL,
        duration TINYINT NOT NULL,
        medium TINYTEXT NOT NULL,
        CONSTRAINT pk_routes PRIMARY KEY ( id )
        )', $tripsid) 
);

$STH->execute();

是的,当你仍然需要操作字符串时,它更需要PDO的美感 - 不幸的是,这是使用表名作为参数的情况! 此外,请记住,这意味着“旧样式”SQL注入风险仍然可以应用,因为您直接操作查询。

我不认为这会在一年后帮助OP,但我希望它现在能帮助别人! :)