【问题标题】:PHP PDO::prepare() - SQL Error with placeholdersPHP PDO::prepare() - 占位符的 SQL 错误
【发布时间】:2011-11-23 14:13:56
【问题描述】:

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

SQL 错误是:

PDO::errorInfo(): Array ([0] => 42000 [1] => 1064 [2] => 你有一个 SQL 语法错误;检查与您对应的手册 MySQL 服务器版本,用于在 *''sdfghjk' ( id INT NOT NULL,stop_start SMALLINT NOT NULL,stop_end SMA'* 在第 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();

}

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

【问题讨论】:

    标签: sql pdo placeholder


    【解决方案1】:

    我看到这个问题已经有一年多了,但我只是偶然发现它并想强调一下:这与引号无关。

    当发生错误并给出与所讨论语法相关的 SQL 的 sn-p 时,它会自动用一对单引号括起来。这通常会使它看起来好像存在不同的问题,即双引号和单引号的混合问题。

    在这个例子中 -

    PDO::errorInfo(): Array ( [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 上的预处理语句很常见。这适用于 any 查询 - 选择/插入/更新等 - 他们都不能接受表名作为参数。有关更多信息 - 请参阅此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 有所帮助,但我希望它现在对其他人有所帮助! :)

    【讨论】:

      【解决方案2】:

      好的,现在我知道 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,
      

      【讨论】:

        猜你喜欢
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 1970-01-01
        • 2021-08-24
        相关资源
        最近更新 更多