【问题标题】:PDO call failing in PHP but successfully executes in MySQL WorkbenchPDO 调用在 PHP 中失败,但在 MySQL Workbench 中成功执行
【发布时间】:2015-02-17 16:43:04
【问题描述】:

我正在通过 PDO 连接到 MySQL 数据库,但是当我尝试在 PHP 中执行 SQL 调用时,它失败并出现以下错误。当我回显 SQL 并在 MySQL Workbench 中运行它时,它返回的正是我所期望的。这是$prepared->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 "5" at line 17
)

所以看起来准备好的语句和在execute 上传递值有问题,但我不确定是什么。 http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html#error_er_parse_error 除了告诉我同样的问题之外并没有真正的帮助。

function __construct($params = array()) {

    $DB = new PDO('mysql:host='.$config['host'].';port='.$config['port'].';dbname='.$config['name'], $config['user'], $config['pswd']);
    if (!$DB) {
        throw new Exception('Could not connect to database');
    }

    $type = $params['topic'];

    if (isset($params['topic']) && $params['topic'] !== '') {
        $typeSlugSql = "SELECT id from topics WHERE slug = ? LIMIT 1";

        $prepared = $DB->prepare($topicSlugSql);
        $list = $prepared->execute(array($params['topic'])); //NOTE: this is working correctly and returns the ID I expect
        if (!$list) {
            throw new Exception('topic slug execute failed');
        }
        $row = $prepared->fetch(PDO::FETCH_ASSOC);

        $topic = $row['id']; //id is correctly 6 at this point
    }

    //generate SQL query
    $sql = "SELECT
                articles.id AS id,
                articles.slug AS slug,
                articles.title AS title,
                articles.headline AS headline,
                articles.description AS description,
                articles.keywords AS keywords,
                articles.content AS content,
                DATE(articles.published_date) AS date,
                articles.created AS created
            FROM
                articles articles
            WHERE
                articles.published_date <= CURRENT_TIMESTAMP
                AND (articles.published IS NOT NULL OR articles.published = 1)
            ORDER BY
                articles.published_date DESC LIMIT 0 , ?";

    //run the query and get the feed data
    $prepared = $DB->prepare($sql);
    $items = $prepared->execute(array(5)); //this will make the SQL fail...

    echo $sql;

    if (!$items) {
        print_r($DB->errorInfo()); //this prints the 'errorInfo' listed above
        throw new Exception('execution error...');
    }

    $options = array('ellipsis' => '...', 'exact' => false, 'html' => false);
    while ($row = $prepared->fetch(PDO::FETCH_ASSOC)) {
        array_push($this->resources, new Resource($row['title'], $row['slug'], $row['date'], $this->cleanAndTruncate($row['content'])));
    }

}

最奇怪的部分是$prepared-&gt;execute(array($params['type'])) 可以正常工作并返回我期望的 ID。同样,如果我复制/粘贴echo'd SQL 并将? 替换为5,它将在 MySQL Workbench 中按预期工作。如果我这样做:

    $sql = "SELECT
                articles.id AS id,
                articles.slug AS slug,
                articles.title AS title,
                articles.headline AS headline,
                articles.description AS description,
                articles.keywords AS keywords,
                articles.content AS content,
                DATE(articles.published_date) AS date,
                articles.created AS created
            FROM
                articles articles
            WHERE
                articles.published_date <= CURRENT_TIMESTAMP
                AND (articles.published IS NOT NULL OR articles.published = 1)
            ORDER BY
                articles.published_date DESC LIMIT 0 , 5";

    $prepared = $DB->prepare($sql);
    $items = $prepared->execute();

它适用于 PDO 和 MySQL Workbench,但我需要 LIMIT 来根据传入的参数进行更改。有什么建议可以找出问题所在吗?

【问题讨论】:

  • FROM articles articles?
  • 这只是我对多个表使用的语法的一部分,所以更清楚,FROM articles articles, articles_topics at, articles_something_else ase,这根本不影响执行。
  • 要“捕获”错误,请使用try/catch 方法:try{...} catch(PDOException $e){ $e-&gt;getMessage(); for the real error } 并在打开连接后立即添加$DB-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);。请参阅下面的答案。
  • 什么PHP版本和PDO版本?

标签: php mysql pdo


【解决方案1】:

试试这个:

$sql = "SELECT
            articles.id AS id,
            articles.slug AS slug,
            articles.title AS title,
            articles.headline AS headline,
            articles.description AS description,
            articles.keywords AS keywords,
            articles.content AS content,
            DATE(articles.published_date) AS date,
            articles.created AS created
        FROM
            articles articles
        WHERE
            articles.published_date <= CURRENT_TIMESTAMP
            AND (articles.published IS NOT NULL OR articles.published = 1)
        ORDER BY
            articles.published_date DESC LIMIT :limit , 5";

$stmt = $DB->prepare($sql);

$limit = 5;

$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);

$items = $stmt->execute();

【讨论】:

  • $this-&gt;numberOfResources = 5; $prepared = $DB-&gt;prepare($sql); $prepared-&gt;bindParam(':limit', $this-&gt;numberOfResources, PDO::PARAM_INT); $items = $prepared-&gt;execute(); 还是不行
  • 已更新,请尝试...当我将 5 作为第二个参数硬编码为 bindParam 时,给了我一个通过引用错误。
  • 相同,所以我改用$this-&gt;numberOfResources。我现在正在修改:? 格式。我会告诉你这是否能解决问题。
  • 发布的代码应该可以工作,我测试过。显然不是相同的模式,而是语言结构。试着做一个SELECT * FROM articles LIMIT :limit 来消除任何其他干扰。
  • @Anthony 的评论是原因,这就是解决方案。实际上,我最终使用了$DB-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE); 并将我的参数保留为?,但它本质上给了我相同的功能。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2013-08-26
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多