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

发布于 2024-12-05 21:13:35 字数 1202 浏览 1 评论 0原文

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

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

}

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

My problem is that I can't get placeholders to work in my SQL statements. Specifically, in the below code, when I replace the placeholder ':tripsid' with a value like 'abcdefg' the TABLE isn't being created as intended.

SQL Error is:

PDO::errorInfo(): Array ( [0] => 42000 [1] => 1064 [2] => 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 *''sdfghjk' ( id
INT NOT NULL, stop_start SMALLINT NOT NULL, stop_end SMA'* at line 1 )

And the code:

// 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();

}

I have tried everything I could think of. Does anyone see the mistake?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你的往事 2024-12-12 21:13:35

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

当发生错误并且给你时与相关语法相关的 SQL 片段,它会自动用一对单引号引起来。这通常会使事情看起来好像存在不同的问题,即双引号和单引号混合的问题。

在这个例子中 -

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

它指的是:

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

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

至于您真正的问题:您不能将表名称(或列名称)指定为参数;这对于大多数平台和 API 上的预准备语句来说很常见。对于任何查询 - 选择/插入/更新等 - 它们都不能接受表名作为参数。有关更多信息 - 请参阅此处的问题

因此,考虑到这一点,我将使用 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 有所帮助,但我希望它会现在就帮助别人吧! :)

I see this question is over a year old, but I've just stumbled across it and would like to highlight something: this has nothing to do with the quotation marks.

When an error occurs and you are given the snippet of SQL relating to the syntax in question, it is automatically enclosed around a pair of single quotation marks. This can often make it look as though there's a different issue, namely that of a mixture of double and single quotes.

In this example -

PDO::errorInfo(): Array ( [0] => 42000 1 => 1064 [2] => 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 ''sdfghjk' ( id INT NOT NULL, stop_start SMALLINT NOT NULL, stop_end SMA' at line 1 )

It's referring to:

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

The outermost quotation marks are just specific to the error output; like me - I fear you noticed this and thought your error was about incorrect quotation marks. This is a red herring! Remove the outermost single quotes to actually see the SQL which was incorrect.

As for your real problem: You CANNOT specify the table name (or a column name) as a parameter; this is common to prepared statements on most platforms and APIs. This goes for any query - select/insert/update etc etc - none of them can accept the tablename as a parameter. For more information - see this question here.

So with this in mind, I would use sprintf() to achieve something like this...

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

Yes, it rather takes the beauty out of PDO when you still have to manipulate strings - unfortunately, this is the case for using table names as parameters! Also, remember this means 'old stylee' SQL Injection risks could still apply as you are manipulating the query directly.

I don't expect this will help the OP a year later, but I hope it'll help someone else now! :)

私藏温柔 2024-12-12 21:13:35

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

ok now I know that the quotation marks bound to the parameter automatically by PDO::bindParam() is causing the problem. Does anybody have an idea how to remove the quotation marks from the table name so my code will be...

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

instead of

$STH = $this->DBH->prepare('CREATE TABLE IF NOT EXISTS 'tablename' (
            id INT NOT NULL,
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文