PDO SQLite查询零结果问题

发布于 2024-10-12 12:20:57 字数 1896 浏览 3 评论 0原文

我环顾四周,但似乎找不到任何有关此的信息。我不确定这是我的代码的问题还是内存 SQLite 数据库和 PDO 的已知问题。

基本上,在将一行插入内存 SQLite 数据库表后,我希望与插入的项目不匹配的查询返回零行。但是,以下代码给出了一行 (false),但没有实际的 PDO 错误代码。

<?php

    // Create the DB
    $dbh = new PDO('sqlite::memory:');
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Data we'll be using
    $name = 'Entry';

    // Create DB table
    $dbh->query('
        CREATE TABLE
            Test
            (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name VARCHAR(50) NOT NULL
            )
    ');

    // Insert data
    $stmt = $dbh->prepare('
        INSERT INTO
            Test
            (
                name
            )
        VALUES
            (
                :name
            )
    ');

    $stmt->bindParam(':name', $name, PDO::PARAM_STR, 50);
    $stmt->execute();

    // Check data has actually been inserted
    $entries = $dbh->query('
        SELECT
            *
        FROM
            Test
    ')->fetchAll(PDO::FETCH_ASSOC);

    var_dump($entries);

    // Query DB for non-existent items
    $stmt = $dbh->prepare('
        SELECT
            *
        FROM
            Test
        WHERE
            name != :name
    ');

    $stmt->bindParam(':name', $name, PDO::PARAM_STR);
    $stmt->execute();

    // How many rows returned
    echo $stmt->rowCount();

    // Actual data returned
    var_dump($stmt->fetch(PDO::FETCH_ASSOC));
?>

我已经设法通过一些黑客技术解决了这个问题,但最好不必这样做:

<?php

    echo (
        (0 == $stmt->rowCount()) || 
        (
            (1 == $stmt->rowCount()) && 
            (false === (($row = $stmt->fetch(PDO::FETCH_ASSOC)))) && 
            ('0000' == array_pop($dbh->errorInfo()))
        )
    ) ? 'true' : 'false';

?>

任何人都可以帮助或指出我可能犯的任何明显错误吗?

I've had a look around but can't seem to find any information on this. I'm not sure if it's an issue with my code or a known issue with in-memory SQLite databases and PDO.

Basically, after inserting a single row into an in-memory SQLite database table, I'd expect that a query that doesn't match the inserted item to return zero rows. However, the following code gives a single row (false) but no actual PDO error code.

<?php

    // Create the DB
    $dbh = new PDO('sqlite::memory:');
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Data we'll be using
    $name = 'Entry';

    // Create DB table
    $dbh->query('
        CREATE TABLE
            Test
            (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name VARCHAR(50) NOT NULL
            )
    ');

    // Insert data
    $stmt = $dbh->prepare('
        INSERT INTO
            Test
            (
                name
            )
        VALUES
            (
                :name
            )
    ');

    $stmt->bindParam(':name', $name, PDO::PARAM_STR, 50);
    $stmt->execute();

    // Check data has actually been inserted
    $entries = $dbh->query('
        SELECT
            *
        FROM
            Test
    ')->fetchAll(PDO::FETCH_ASSOC);

    var_dump($entries);

    // Query DB for non-existent items
    $stmt = $dbh->prepare('
        SELECT
            *
        FROM
            Test
        WHERE
            name != :name
    ');

    $stmt->bindParam(':name', $name, PDO::PARAM_STR);
    $stmt->execute();

    // How many rows returned
    echo $stmt->rowCount();

    // Actual data returned
    var_dump($stmt->fetch(PDO::FETCH_ASSOC));
?>

I've managed to work-around the problem with some hackery but it'd be nice to not have to do this:

<?php

    echo (
        (0 == $stmt->rowCount()) || 
        (
            (1 == $stmt->rowCount()) && 
            (false === (($row = $stmt->fetch(PDO::FETCH_ASSOC)))) && 
            ('0000' == array_pop($dbh->errorInfo()))
        )
    ) ? 'true' : 'false';

?>

Can anyone help or point out any glaring mistakes that I may have made?

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

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

发布评论

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

评论(1

熊抱啵儿 2024-10-19 12:20:57

PDOStatement::rowCount() 返回

...受相应 PDOStatement 对象执行的最后一个 DELETE、INSERT 或 UPDATE 语句影响的行数。

如果关联的 PDOStatement 执行的最后一个 SQL 语句是 SELECT 语句,某些数据库可能会返回该语句返回的行数。但是,不能保证所有数据库都具有此行为,并且不应依赖于可移植应用程序。

欢迎来到 PDO,在这里,简单的事情有效,不那么简单的事情会毁掉你的一天。 SQLite 是没有可靠的“我的结果集中有多少行?”的驱动程序之一。功能。来自评论:

从 SQLite 3.x 开始,SQLite API 本身发生了变化,现在所有查询都是使用“语句”实现的。因此,PDO 无法知道 SELECT 结果的 rowCount,因为 SQLite API 本身不提供此功能。

PDOStatement::fetch()< 返回 false /a> 是“没有返回”的保证,并且您的检查代码完全正常,尽管有点难以阅读。为了您自己的理智,您可能希望考虑包装或派生 PDO 和 PDOStatement。

(免责声明:我是 PDO 粉丝。)

PDOStatement::rowCount() returns

... the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.

If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.

Welcome to PDO, where the easy stuff works and the not-so-easy stuff ruins your day. SQLite is one of the drivers that doesn't have a reliable "how many rows are in my result set?" function. From the comments:

As of SQLite 3.x, the SQLite API itself changed and now all queries are implemented using "statements". Because of this, there is no way for PDO to know the rowCount of a SELECT result because the SQLite API itself doesn't offer this ability.

A return of false from PDOStatement::fetch() is a guarantee of "nothing came back," and your checking code is entirely sane, if a bit hard to read. You may wish to consider wrapping or deriving from PDO and PDOStatement for your own sanity.

(Disclaimer: I am a PDO fanboy.)

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