【问题标题】:open existing sqlite3 database under QT在QT下打开已有的sqlite3数据库
【发布时间】:2011-12-10 16:45:14
【问题描述】:

我对 QT 和 SQLite DBMS 非常陌生。我正在尝试在 ubuntu Linux 下打开使用“sqlite3”命令行程序创建的现有数据库。我尝试使用以下代码在 QT 下访问的同一数据库:

void MainWindow::func()
{
    QSqlQuery query;
    accounts_db = new QSqlDatabase();
    *accounts_db = QSqlDatabase::addDatabase("QSQLITE");
    perror("? ");
accounts_db->setDatabaseName("/home/user/xyz.db");
QSqlError *a = new QSqlError();
*a = accounts_db->lastError();
perror(a->text().toLatin1());
if (!accounts_db->open()) {
    perror("database open error :");
}
if ( !accounts_db->isOpen() ) {
    perror("database is not open");
}
query.exec("select accno,branchcode,fname,lname,curbalance,accdate from accounts");
while(query.next()) {
    QString str = query.value(0).toString();
    std::cerr << qPrintable(str) << std::endl;
}
end:
;
}

这会失败并出现以下错误...

No such file or directory
: Invalid argument
QSqlQuery::exec: database not open

请注意,在 adddatabase() 之后我得到“没有这样的文件或目录”,不知道它在谈论哪个文件。还要注意 isOpen() 和 open() 返回“true” (???)。 “数据库未打开”错误来自 db.exec() 调用(......我想......)。

急需指导...

【问题讨论】:

  • 如果数据库打开正确,检查exec的结果。然后使用 lastError() 进行检查。
  • 我确实这样做了,exec() 调用打印出 database not open 错误,这是我在问题中发布的第三个错误(如上)。而 lastError() 返回 Invalid argument 错误。

标签: linux qt sqlite


【解决方案1】:

不带参数的 QSqlQuery 的构造函数使用您应用程序的默认数据库。也许它还没有设置。使用构造函数指定查询需要使用的数据库:

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "connection_name");
// Open db...
QSqlQuery query(db);
if (!query.exec(...)) {
   // ...
}
// ...

注意之后如何关闭连接。

编辑:这是我刚刚编写的测试,正在我的系统上运行。你可能想试试。

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>

int main(int argc, char *argv[])
{
    // Create database.
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "Connection");
    db.setDatabaseName("/tmp/test.db");
    if (!db.open()) {
        qDebug("Error occurred opening the database.");
        qDebug("%s.", qPrintable(db.lastError().text()));
        return -1;
    }

    // Insert table.
    QSqlQuery query(db);
    query.prepare("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, text TEXT)");
    if (!query.exec()) {
        qDebug("Error occurred creating table.");
        qDebug("%s.", qPrintable(db.lastError().text()));
        return -1;
    }

    // Insert row.
    query.prepare("INSERT INTO test VALUES (null, ?)");
    query.addBindValue("Some text");
    if (!query.exec()) {
        qDebug("Error occurred inserting.");
        qDebug("%s.", qPrintable(db.lastError().text()));
        return -1;
    }

    // Query.
    query.prepare("SELECT * FROM test");
    if (!query.exec()) {
        qDebug("Error occurred querying.");
        qDebug("%s.", qPrintable(db.lastError().text()));
        return -1;
    }
    while (query.next()) {
        qDebug("id = %d, text = %s.", query.value(0).toInt(),
               qPrintable(query.value(1).toString()));
    }

    return 0;
}

【讨论】:

  • 我很困惑。您可能想尝试我添加到答案中的代码。这将创建数据库、创建表、插入示例行和查询。请报告输出。
  • 试了一下,结果是打印id = 1, text = Some text,对吗?我还是一个初学者,所以我还不明白 addBindValue() 是如何工作的,因此我不明白打印的结果。
  • 是的,没错。如果再次运行它,每次执行都会多看到一行。文本是常量,整数总是递增。所以一切正常。尝试使用此代码打开您的数据库,删除创建新表的部分和插入新行的部分。将查询中的 test 替换为您的表名并再次测试。
  • 完美无瑕的男人!!!。只是好奇...为什么使用指针访问数据库不好?
  • 你的意思是QSqlDatabase吗?我不认为这是一个问题,据我所知,从未以这种方式使用过,但我认为没关系。只需正确处理断开连接即可。这是一个非常微妙的观点。有关说明,请参阅 Qt 文档中的 removeDatabase。
【解决方案2】:

这主要是猜测,因为您的代码在很多方面都是错误的,包括错误报告。

最可能的问题是您的文件路径不正确,或者您运行应用程序的用户对文件和/或目录没有适当的权限。 (注意:文件和目录在 Linux 中是区分大小写的。)

perror 只能在调用实际失败的系统函数后使用,并且在失败时设置errno。 Qt 不这样做。

请尝试运行此程序,如果您仍然无法解决问题,请更新您的问题:

void MainWindow::func()
{
    // Note: no pointer!
    QSqlDatabase accounts_db = QSqlDatabase::addDatabase("QSQLITE");
    accounts_db.setDatabaseName("/home/user/xyz.db");
    if (!accounts_db.open())
    {
        qDebug() << "Could not open database file:";
        qDebug() << accounts_db.lastError();
        return;
    }
    // Note: don't construct queries before you have a database!
    QSqlQuery query;
    if (!query.exec("select accno,branchcode,fname,lname,curbalance,accdate from accounts"))   
    {
        qDebug() << "Query failed:";
        qDebug() << query.lastError();
        return;
    }
    while(query.next()) {
      QString str = query.value(0).toString();
      std::cerr << qPrintable(str) << std::endl;
    }
}

(我什至没有尝试编译这个,所以 YMMV。)

也看看SQL examples,看看他们是如何处理这一切的。

【讨论】:

  • 谢谢老兄...我试过了。 qDebug() 不断打印 QSqlError(-1, "", "") 。事实上,所有 lastError() 调用都在打印相同的内容,除了 query.exec()。那个正在打印 QSqlError(1, "Unable to execute statement", "no such column: accdate") 。但当然,这些列确实存在,我已经使用 cmdline sqlite3 程序 chkd。 SQL 示例没有使用数据库文件,它们使用“:memry:”而不是数据库文件路径。
【解决方案3】:

好的,我使用 sqlite3 命令创建了一个全新的数据库文件,现在我的问题中的同一个程序正在运行!!!。

我以前也尝试过,但那次没有用(......当这种情况发生时我讨厌它)。我猜以前的文件可能已损坏。但是之前的数据库文件可以从 cmdline sqlite3 程序访问,所以我假设该文件是好的,但显然不是。

无论如何,非常感谢大家给我时间,如果浪费了我非常抱歉:(。

我将其标记为答案只是为了清楚地回答这个问题。但它并不完全是一个答案(......因为我仍然不明白发生了什么!?)

再次感谢...

编辑:

这里是代码

QSqlError *a = new QSqlError();

accounts_db = new QSqlDatabase();
*accounts_db = QSqlDatabase::addDatabase("QSQLITE");

accounts_db->setDatabaseName("/home/user/test.db");

if ( !accounts_db->open() ) {
    qDebug() << accounts_db->lastError();
    qDebug() << "Could not open database file:";
}
QSqlQuery query;

if ( !(accounts_db->isOpen()) ) {
    qDebug() << accounts_db->lastError();
    qDebug() << ": Could not open database file:";
    goto end;   // quit if not successful
}

query.exec("select * from accounts");

while(query.next()) {
    // loop for i columns
    QString str = query.value(i).toString();
    std::cerr << qPrintable(str) << std::endl ;
    // loop
}
end:
;

【讨论】:

  • 如果您打算接受修改后的代码,请在答案中不包含所有内容(尤其是perror 内容),否则其他人可能会认为您问题中的代码是有效,但不是的情况。
  • 实际上 IS 是这样,我之前的代码 IS 工作。我所做的只是在不同的数据库文件上尝试相同的代码:)。但我发布代码以防万一......以避免混淆。
  • 对不起,你的代码不好。您正在分配一个 QSqlDatabase,然后立即将其丢弃(泄漏)。与 QSqlError 相同。您正在通过指针使用 QSqlDatabase,这不是您应该使用的方式。您没有检查 query.execute() 的返回值,这是不好的做法。你有一个无用的 goto,这是非常糟糕的做法,尤其是在 C++ 中。如果数据库无法打开,您不会中断您的程序流程,这是不好的做法。对不起,-1 来自我。
  • 好吧,我只发布了对答案有用的代码部分。我同意,GOTO 很危险,我应该 避开它们。但是我是用它来突破上面的功能,代码底部的end:标签是我跳转的地方,取消分配资源然后退出。正如我所说,我对 C++ 和 OOP 还是很陌生。顺便说一句,为什么使用指针访问数据库是错误的?
  • 没有错,不正常。这不是在样本中完成的方式。它会导致泄漏(如您的代码中所示)。 goto 在 C++ 中比在 C 中更难正确,如果你不在那里进行清理,那么在函数末尾执行 goto 是没有意义的。
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2019-07-12
相关资源
最近更新 更多