15

我在我的应用程序中使用 PDO。但是当我在包含LIMIT. 有什么问题?
代码:

$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));

错误:

检查与您的 MySQL 服务器版本相对应的手册,以获取在 ''0'、'20'' 附近使用的正确语法

4

5 回答 5

14

关于使用准备好的语句在 MySQL 上发布LIMIT 关键字,下面的代码可以解决我的问题。

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);

感谢Álvaro G. VicarioMaerlyn

于 2012-07-31T11:04:10.653 回答
13

你可以这样做:

$sql = SELECT * FROM tbl_news ORDER BY date DESC LIMIT :start, :rows";
$q = $db->prepare($sql);
$q->bindParam(':start', $start, PDO::PARAM_INT);
$q->bindParam(':rows',$rows, PDO::PARAM_INT);
于 2012-07-31T11:00:57.450 回答
3

这是一个已知的错误,已在 5.5.6 中从内存中修复。

来自文章: LIMIT 不允许在任何上下文中使用变量。它的参数必须是整数常量。

进一步编辑:(关于此事存在争议)用户变量是准备好的语句中 LIMIT 子句的可接受参数,准备好的语句的 SQL 语法可以在存储过程中使用。

第三次编辑:此链接说明这些应与准备好的语句一起使用。

于 2012-07-31T10:55:20.840 回答
1

我只是偶然发现了同样的问题。对我来说,使用我自己的语句类(扩展PDOStatement)和我自己的execute()方法来修复它。

这是课程:

class MyPDOStatement extends PDOStatement {

  public function execute($input_parameters = null) {
    if (is_array($input_parameters)) {
      $i = 1;
      foreach ($input_parameters as $p) {
        // default to string datatype
        $parameterType = PDO::PARAM_STR;
        // now let's see if there is something more appropriate
        if (is_bool($p)) {
          $parameterType = PDO::PARAM_BOOL;
        } elseif (is_null($p)) {
          $parameterType = PDO::PARAM_NULL;
        } elseif (is_int($p)) {
          $parameterType = PDO::PARAM_INT;
        }
        // parameters passed to execute() are input-only parameters, so use
        // bindValue()
        $this->bindValue($i, $p, $parameterType);
        $i++;
      }
    }
    return parent::execute();
  }

}

要告诉 PDO 使用此语句类而不是默认的,请执行以下操作:

$db = new PDO(...);
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement'));

现在问题中的代码将起作用:

$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));

您唯一需要做的事情是绑定到语句的变量具有正确的类型,整数。如果你有一个数字字符串,例如来自$_GET数组,你可以这样做:

if (isset($_GET['start']) && is_numeric($_GET['start'])
    && is_int($_GET['start'] + 0) {
  $start = (int) $_GET['start'];
}

如果最后一件事有更简单的方法,我不确定,但至少它对我来说很好。

于 2013-03-03T19:18:12.583 回答
-3

date是一个保留字,你必须用它来包装它 back-ticks

于 2012-07-31T10:54:22.910 回答