如何将 pdo 的准备语句用于 order by 和 limit 子句?

发布于 2024-08-30 02:28:10 字数 525 浏览 5 评论 0原文

我想使用一个准备好的语句,其中传入的参数用于 ORDER BYLIMIT 子句,如下所示:

$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
     'sort'  => $_GET['sort'], 
     'dir'  => $_GET['dir'], 
     'start'  => $_GET['start'],
     'results' => $_GET['results'],
     )
    );

But $stmt->fetchAll (PDO::FETCH_ASSOC); 不返回任何内容。

有人可以指出我做错了什么吗?能做到吗?如果没有,我应该参考什么来获取可以使用参数的完整子句列表?

I want to use a prepared statement in which the passed-in parameters are for the ORDER BY and LIMIT clauses, like so:

$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
     'sort'  => $_GET['sort'], 
     'dir'  => $_GET['dir'], 
     'start'  => $_GET['start'],
     'results' => $_GET['results'],
     )
    );

But $stmt->fetchAll(PDO::FETCH_ASSOC); returns nothing.

Can someone point out what's the wrong thing I am doing? Can it be done? If not,what should I reference for a complete list of clauses where parameters can be used?

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

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

发布评论

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

评论(4

誰認得朕 2024-09-06 02:28:11

使用后:

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

我收到消息:

未捕获的异常“PDOException”
消息'SQLSTATE[42000]:语法错误
或访问冲突:1064 您有一个
SQL 语法错误;检查
与您的 MySQL 对应的手册
服务器版本的正确语法
在第 1 行的“0”、“10”附近使用

因此,当您使用数组执行时,它会将您的输入视为字符串,这对于 LIMIT 来说不是一个好主意

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT);
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT);
$stmt->bindParam(':sort', $_GET['sort']);
$stmt->bindParam(':dir', $_GET['dir']);
$stmt->execute();

$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);

After using :

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

I got the message :

Uncaught exception 'PDOException' with
message 'SQLSTATE[42000]: Syntax error
or access violation: 1064 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 ''0', '10'' at line 1

So, when you use an array for execute, it consider your inputs as string which is not a good idea for LIMIT

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT);
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT);
$stmt->bindParam(':sort', $_GET['sort']);
$stmt->bindParam(':dir', $_GET['dir']);
$stmt->execute();

$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
陪你到最终 2024-09-06 02:28:11

准备好的语句允许 DBMS 在实际执行针对您提供的参数的查询之前为您的查询生成查询计划。更改 ORDER BY 的字段需要不同的查询计划,因为以不同的方式对数据进行排序可能会极大地影响 DBMS 选择获取数据的方式:例如,某些索引在一种情况下可能会有所帮助,但不在另一个。因此,ORDER BY 字段应构成传递给 prepare() 方法的 SQL 字符串的一部分,而不是在 execute( )

至于 LIMIT 子句,尚不清楚其参数是否会影响查询计划,因此这些参数可能会在稍后绑定,这可能取决于您的 DBMS。根据这个SO答案应该允许它。

Prepared statements allow the DBMS to generate a query plan for your query before actually executing the query for your supplied parameters. Changing the fields for ORDER BY requires a different query plan, because ordering you data in different ways can drastically affect how the DBMS might choose to get the data: for instance, certain indexes may help in one case but not in another. For this reason the ORDER BY fields should form part of the SQL string passed into the prepare() method, rather than being bound to the query prior to execute().

As for the LIMIT clause, it's not clear whether its parameters would affect the query plan, so these may be bound later, possibly depending upon your DBMS. According to this SO answer it should be allowed.

安穩 2024-09-06 02:28:11

您不能绑定参数来指定语言关键字或字段名称 - 它必须替换文字。因此,我认为你的极限值很好,但你的排序依据却不行。最好手动替换字符串中的 sort 和 dir。转义它们,但不要使用数据库工具来执行此操作,因为它们不是字符串文字。基本上确保不存在特殊字符。

You can't bind a parameter to specify a language keyword or a field name - it has to be replacing a literal. Therefore, your limit values I think are fine, but your order by is not. It will be best for you to manually replace sort and dir in the string. Escape them but don't use the DB tools to do so, since they aren't string literals. Basically ensure no special characters are present.

向地狱狂奔 2024-09-06 02:28:11

虽然这个问题相当老了,但我认为它可能仍然很有趣。对我来说,在我

  1. 将bindParam与PDO::PARAM_INT结合使用之后,就像
  2. 在通过调用intval()将变量内容转换为整数值

之前所建议的那样,它的相关部分代码如下所示:

    $stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT);
    $stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT);

不使用 intval() 我还收到了错误语法错误或访问冲突:1064 您的 SQL 语法中有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在第 1 行“0”、10”附近使用的正确语法

Although this question is rather old, I think it might still be of interest. For me it worked after I

  1. used bindParam in combination with PDO::PARAM_INT like suggested before
  2. converted the variable content into an integer value by invoking intval()

The relevant part of the code then looks like this:

    $stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT);
    $stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT);

Without using intval() I also received the error Syntax error or access violation: 1064 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 ''0', 10' at line 1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文