在Qt中连接SQLite和MySQL数据库

来源:互联网 发布:冰与火之歌 知乎 编辑:程序博客网 时间:2024/05/17 08:52

 

Qt+sqlite3  

一、QT编译数据库问题:

 1、根文件系统:友善提供的源代码,去掉qtopia之后的qt4部分

 2、问题现象   

QSqlDatabasedb=QSqlDatabase::addDatabase("QSQLITE");

db.setDatabaseName("database.db");

*第一步:链接嵌入式数据库QSQLITE的,已经绑定成功

if (!db.open()) {

QMessageBox::warning(0, QObject::tr("Database Error"),

db.lastError().text());

qDebug() <<QString("dasfsdafdaga");

 return false;

}

*第二步:打开数据库也没有问题

QSqlQuery query;

query.exec(QObject::tr("create table student (id int primary key, name vchar)"));

query.exec(QObject::tr("insert into student values (0,'刘明')"));

query.exec(QObject::tr("insert into student values (2,'王红')"));

*第三步,数据库操作开始出现问题,在PC机上实现的实现的时候这步一旦执行isActive变为true,数据库写入成功。但是移植到arm上之后却显示为false。我就郁闷了,数据库没法操作啊。网上查了老半天,遇到同样问题的人挺多,就是没有人说解决方案,有人在帖子上说跟友善的根文件系统配置有关,我打电话问友善技术支持,他们说友善对数据库的支持比较差,他们也不确定是什么问题。继续查了几天错误,还是不知道到底是少了什么库还是少了什么设置,就是不能用,有个前辈建议我改为xml或者装个sqlite3的插件先代替数据库,最后决定,还是装sqlite3插件了。

 

二、QT+sqlite3

先说一下QT自带数据库和sqlite3的区别,他们的功能是一样的,但是代码就不一样了。QT对数据库具有完善的支持,不需要加任何其他插件就可以直接使用,但是如果你要是加了sqlite3插件,调用数据库就跟直接调用一个驱动一样,直接调用接口函数:openclose……,换言之QT自带的数据库语言就用不上了。

1、安装sqlite3插件

从官方网站http://www.sqlite.org下载完整版本。

2、安装sqlite3

网上可以看到很多修改下载之后的源代码的论坛,我估计那些帖子比较老一点,最新版的代码已经不存在那些bug了,可以直接编译

 

 *注意复制粘贴库函数的时候有的动态链接库如果单独复制会丢失之间的链接关系,所以需要一块复制

cp -arf libsqlite3.so libsqlite3.so.0 libsqlite3.so.0.8.6 。。。

3、移植sqlite3

QTEinclude文件中建立新文件夹sqlite3,将头文件放到里面;把库文件放到QTElib文件中

4、编程

1 QT生成的.pro文件中添加库指令: LIBS += -lsqlite3

2在调用数据库的文件的头文件里添加头文件和变量

 #include "sqlite3/sqlite3.h"            

 sqlite3 *db;        //数据库

 char *zErrMsg;      //出错信息

 char  **resultp;    //调用时的保存位置

 int  nrow;          //列数

int  ncolumn;       //行数

 char  *errmsg;      //出错信息

 

3)新建或打开数据库      

if( (sqlite3_open("people.db", &db)) != 0 ){

qDebug()<<"sqlite3 open is false";

 }

else {

qDebug()<<"sqlite3 open is OK";

 

 }

4建立表格

sqlite3_exec(db, "create table person(name varchar(30) PRIMARY KEY, age int);", NULL, NULL, &zErrMsg);

*添加 PRIMARY KEY是指定主键,每个数据库只能有一个,主键的值不能重复,比方说你设定name为主键,则相同名字的人只能保存第一个,其他的忽略不计。若想避免这种情况,则去掉主键或者设定id号为主键(id号一直加一,不会重复)。

5)往表格里写入信息

 a.直接添加数据  

 sqlite3_exec(db, "insert into person values('张翼', 30)", NULL, NULL, &zErrMsg);

 sqlite3_exec(db, "insert into person values('hongdy', 28)", NULL, NULL, &zErrMsg);                     

 b.添加数字变量

 int  data=10;

 char sql2[100];  //必须写明大小,划分内存,如果只写一个 char *sql2,会出现段错误

 sprintf(sql2,"insert into person values('张翼',%d);",data);

sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);

*sprintf的作用是字串格式化命令,主要功能是把格式化的数据写入某个字符串中

 c.添加字符串变量

 char data[]="张翼";

 char sql2[100];

 sprintf(sql2,"insert into person values('%s',10);",data);

 

sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);

 * %s需要用单引号注释             

d.添加text中的变量到数据库中

 这里需要汉字编码的问题,Windows下默认GBKGB2312编码,Linux下默认UTF-8编码,所以如果没有设置好会出现乱码

d1. main.cpp中添加以下指令,支持中文显示 

 #include <QTextCodec>

QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

d2. 读取保存

 char *abc=ui->lineEdit->text().toUtf8().data();   //QStringchar*

 sprintf(sql2,"insert into person values('%s',%d);",abc,data);

sqlite3_exec(db,sql2,NULL,NULL,&zErrMsg);

*在调试的时候如果用串口超级终端调试的话,在ARM上显示正常,但是在串口是乱码,不要被迷惑

6)查询、调用数据库

a. 查询全部

sqlite3_get_table(db, "select * from person", &resultp, &nrow, &ncolumn, &errmsg);

*resultp保存数据库信息,nrow返回列数,ncolumn返回列数

b. 查询部分信息

sqlite3_get_table(db, "select * from person where name='zhang'", &resultp, &nrow, &ncolumn, &errmsg);

c. 变量查询查询

 char data[]="张翼";

 char sql3[100];

 sprintf(sql3,"select * from person where name='zhang';",data);

 sqlite3_get_table(db, sql3, &resultp, &nrow, &ncolumn, &errmsg);

 *查询时使用变量的方法和添加时一样

(7)关闭数据库

 sqlite3_close(db);

下载SQLite数据库

首先到SQLite官方网站下载:

http://www.sqlite.org/download.html

得到sqlite3.exe。即可.就可以操作数据库了。

运行cmd到该指定的目录下,使用如下命令:如

F:\软件\学习软件\数据库\SQlite\sqlite-3_6_17>sqlite3.exe test  

并有以下提示:Enter SQL statements terminated with a ";"   

 

就可以创建一个名为test的数据库了.你可以使用.help命令查看各命令.

.databases   可以得到所有的数据库。

  可以使用如下命令得到一张表,并插入数据。最后.quit退出.
F:\
软件\学习软件\数据库
\SQlite\sqlite-3_6_17> create table student(id varchar(10),name varchar(20),age smallint);   
F:\
软件\学习软件\数据库
\SQlite\sqlite-3_6_17> select * from student;   
F:\
软件\学习软件\数据库
\SQlite\sqlite-3_6_17> insert into student values('1001' , 'lovesizhao' ,26);   
F:\
软件\学习软件\数据库
\SQlite\sqlite-3_6_17> select * from student;   
1001|lovesizhao|26   
F:\
软件\学习软件\数据库
\SQlite\sqlite-3_6_17> drop table student;   
F:\
软件\学习软件\数据库\SQlite\sqlite-3_6_17> .quit  

drop table student;   可以删除该表格.其实大部操作都属于SQL的相同没什么改变.

也可以将该数据库备份至output.sql,也称为重定向

sqlite3.exe test.db3 >output.sql

最后可以将数据库保存为test.db3即可。

下面讲解如何通过Qt来访问刚才建立的数据库:

 QSqlDatabase dbconn = QSqlDatabase::addDatabase("QSQLITE", "testSQLite");   
    dbconn.setDatabaseName("test.db3");  //
当前目录下的test.db3数据库文件
   
    //SQLite
数据库文件可用SQLite的命令行工具(c:\sqlite3.exe 数据库名)或用SQLite GUI工具创建,
SQLiteSpy   
 
    if(!dbconn.open())   
    {   
           
        return;   
    }   
  
    QTableView *view;   
    QSqlTableModel *model;   
    view = new QTableView();   
    model = new QSqlTableModel(this,dbconn);   
    model->setTable("test");   
    model->select();   
    view->setModel(model);  

也可以直接访问内存得到:如

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open()) {
        QMessageBox::critical(0, qApp->tr("Cannot open database"),
            qApp->tr("Unable to establish a database connection.\n"
                     "This example needs SQLite support. Please read "
                     "the Qt SQL driver documentation for information how "
                     "to build it.\n\n"
                     "Click Cancel to exit."), QMessageBox::Cancel);
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
               "firstname varchar(20), lastname varchar(20))");
    query.exec("insert into person values(101, 'Danny', 'Young')");
    query.exec("insert into person values(102, 'Christine', 'Holand')");

    query.exec("create table images (locationid int, file varchar(20))");
    query.exec("insert into images values(0, 'images/oslo.png')");
    query.exec("insert into images values(1, 'images/brisbane.png')");
  

以下的操作只是往数据库中添加数据的插入操作.如果想进一步学习,请查找相当资料。


在这里我还提拱和种可以访问mysql的方法.

首先要在Qt安装好mysql的插件.

去网上下载:mingw-utils-0.3

然后将解包后在其bin目录下找到reimp.exe,拷贝到mingwbin目录下。而且要将mingwbin目录加到classpath.

则可以在cmd下使用如下命令:

t> reimp -d libmysql.lib

t>dlltool -k -d libmysql.def -l libmysql.a

注意:t的目录是mysql安装目录下。我的目录为D:\MySQL\lib\opt(而且这些目录中间不能有空格,否则得不到libmysql.a

然后转到Qt的目录下(我的为D:\Qt\4.3.2\src\plugins\sqldrivers\mysql).

运行如下命令:

qmake -o Makefile "INCLUDEPATH+=D:\MySQL\lib\include"  "LIBS+=D:\MySQL\lib\lib\opt\LIBMYSQL.a" mysql.pro

 

 mingw32-make

这样就在D:\Qt\4.3.2\plugins\sqldrivers目录下生成libqsqlmysql4.aqsqlmysql4.dll.

然后就是运行一个连接到mysql数据库,测试是否成功.

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); // 使用mysql数据库驱动 
 db.setHostName("localhost");
 db.setDatabaseName("test"); // 
我们之前建立的数据库

 db.setUserName("root"); // 
我们创建的 yunfan 用户名
 db.setPassword("123"); // yunfan 
用户的密码
 bool ok = db.open(); // 
尝试连接数据库
 if(ok) { // 
这里用yunfan已经成功连上数据库
  QSqlQuery query; // 
新建一个查询的实例
  if(query.exec("select * from t_customer")){ // 
尝试列出 employee 表的所有记录
  // 
本次查询成功
   int numRows = 0; // 
询问数据库驱动,是否驱动含有某种特性 
   if(db.driver()->hasFeature(QSqlDriver::QuerySize)){
    numRows = query.size(); // 
如果支持结果影响的行数,那么直接记录下来

   } else {
    query.last(); //
否则定位到结果最后,qt 文档说,这个方法非常慢
    numRows = query.at() + 1;
   }
   QString id, lname, fname, phone; 
   QDateTime dob;
   display.append("===========================================");
   display.append(QString::fromLocal8Bit(" account | password | cname | cbalance"));
   display.append("--------------------------------------");
   while(query.next()) { // 
定位结果到下一条记录
    id = query.value(0).toString();
    //lname = QString::fromLocal8Bit(query.value(1).toByteArray());
    //fname = QString::fromLocal8Bit(query.value(2).toByteArray());
    //dob = query.value(3).toDateTime();
    //phone = QString::fromLocal8Bit(query.value(4).toByteArray());
    QString result = id ;//+ " " + fname + lname + " " + (dob.toString()) + " "+phone;
    display.append(result);
   }
   display.append("============================================");
   display.append(QString("totally %1 rows").arg( numRows));
  } else { // 
如果查询失败,用下面的方法得到具体数据库返回的原因
   QSqlError error = query.lastError();
   display.append("From mysql database: " + error.databaseText());
  }
 } else{ // 
打开数据库失败,显示数据库返回的失败描述
  display.append("cannot open database.");
  display.append("Reason: " + db.lastError().databaseText());
 }

这只是其中一部分核心代码.

 

0 0