Qt提供了平台以及数据库种类无关的访问数据库接口,支持 QMYSQL,QODBC ,QPSQL和QSQLITE. 由于Qt对不同平台和数据库都使用同一个接口,本文选择了对嵌入式领域常用的SQLite数据库进行操作。
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至今已经有13个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中(eg. test.db)。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。
1.下载并解压数据库
从sqlite 官网下载最新的源码包 http://www.sqlite.org/download.html 现在最新版本为3080100版本
下载完成后解压: tar -zxvf sqlite-autoconf-3080100.tar.gz
2.交叉编译
a.解压完成之后,进入解压后的目录:
cd sqlite-autoconf-3080100
b.在这个目录之中新建一个文件夹,用于放置最后交叉编译生成的程序包:
mkdir build
c.文件夹中运行 sqlite-autoconf-3080100中的configure脚本生成Makefile文件:
./configure --prefix=/文件夹的绝对路径/ssqlite-autoconf-3080100/build
--Prefix:可以指定编译之后目标存放的路径,可自行设定
还可以通过 --host=arm-linux 指定使用 arm交叉编译器进行交叉编译 以供嵌入式系统使用
d.然后运行指令:
make
make install
3.编译和安装完成之后,在我们指定的路径/文件夹的绝对路径/ssqlite-autoconf-3080100/build 下会生成四个文件夹:
bin、lib、include、share,将bin中的文件拷贝至开发板的/usr/bin中,将lib文件夹中的所有内容拷贝至项目lib文件夹中
4.测试数据库
先将/usr/bin/sqlite3的权限修改一下:
chmod 755 sqlite3
然后在开发板的终端中输入指令:
sqlite3 test.db
执行的结果为:
SQLite version 3.8.1 2013-10-17 12:57:35
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
此时表明Sqlite3已经移植成功
----------------------------
Qt 操作SQlite数据库
----------------------------
1.创建测试数据库
create table qttest([id] integer PRIMARY KEY autoincrement, [userName] varchar(32), [userPwd] varchar(32));
添加测试数据记录
insert into qttest(id,userName,userPwd) values(NULL,"apple","123456");
insert into qttest(id,userName,userPwd) values(NULL,"orange","123456");
2.创建qt项目,将 test.db 放在qt的项目文件夹,并在qt工程文件(xxx.pro)里 添加:
QT += sql
3. qt操作数据库代码:
01 | #include <QApplication> |
02 | #include <QMessageBox> |
06 | bool dbConnect( char *dbname) |
08 | QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE" ); |
11 | db.setDatabaseName(dbname); |
17 | qDebug()<< "Database Error!" <<db.lastError().text(); |
20 | qDebug()<< "Database Success!" ; |
26 | int main( int argc, char *argv[]) |
28 | QApplication app(argc,argv); |
32 | iRet=dbConnect(( char *) "test.db" ); |
37 | query.exec( "select id,userName,userPwd from qttest" ); |
42 | qDebug()<< "Query Error!" <<query.lastError().text(); |
60 | int id = query.value(0).toInt(); |
61 | QString name = query.value(1).toString(); |
62 | QString pwd = query.value(2).toString(); |
63 | qDebug()<< "user info: id= " <<id<< ",name= " <<name<< ",pwd= " <<pwd; |
67 | query.exec( "insert into qttest(id,userName,userPwd) values(null,\"ox\",\"123456\")" ); |
69 | query.exec( "update qttest set userPwd= \"1111\" where id=\"1\"" ); |
经验证,Qt对SQlite数据库的支持可能存在问题. 同样的数据内容,操作MYSQL就不存在问题,但是操作SQlite,就不支持 numRowsAffected()接口 和 ODBC风格的插入操作.
原因不祥,如果是代码或是数据库配置等其他原因,望能得到指点。(平台环境:Ubuntu + Qt Creator 4.8)
运行结果:
--------------------------------
SQLite 数据库 C/C++ 接口
--------------------------------
SQLite 提供了 C/C++ 接口的API函数,这些接口使用起来并不复杂. 最简单的程序仍然使用三个函数就可以完成: sqlite3_open(), sqlite3_exec(), 和 sqlite3_close().
1. 核心对象:
在SQLite中最主要的两个对象是,database_connection和prepared_statement。 database_connection对象是由sqlite3_open()接口函数创建并返回的,在应用程序使用任何其他SQLite接口函数之前,必须先调用该函数以便获得database_connnection对象,在随后的其他APIs调用中,都需要该对象作为输入参数以完成相应的工作。至于 prepare_statement,我们可以简单的将它视为编译后的SQL语句,因此,所有和SQL语句执行相关的函数也都需要该对象作为输入参数以完成指定的SQL操作。
2. 核心接口:
1). sqlite3_open
上面已经提到过这个函数了,它是操作SQLite数据库的入口函数。该函数返回的database_connection对象是很多其他SQLite APIs的句柄参数。注意,我们通过该函数既可以打开已经存在的数据库文件,也可以创建新的数据库文件。对于该函数返回的 database_connection对象,我们可以在多个线程之间共享该对象的指针,以便完成和数据库相关的任意操作。然而在多线程情况下,我们更为推荐的使用方式是,为每个线程创建独立的database_connection对象。对于该函数还有一点也需要额外说明,我们没有必要为了访问多个数据库而创建多个数据库连接对象,因为通过SQLite自带的ATTACH命令可以在一个连接中方便的访问多个数据库。
2). sqlite3_prepare
该函数将SQL文本转换为prepared_statement对象,并在函数执行后返回该对象的指针。事实上,该函数并不会评估参数指定SQL语句,它仅仅是将SQL文本初始化为待执行的状态。最后需要指出的,对于新的应用程序我们可以使用sqlite3_prepare_v2接口函数来替代该函数以完成相同的工作。
3). sqlite3_step
该函数用于评估sqlite3_prepare函数返回的prepared_statement对象,在执行完该函数之后,prepared_statement对象的内部指针将指向其返回的结果集的第一行。如果打算进一步迭代其后的数据行,就需要不断的调用该函数,直到所有的数据行都遍历完毕。然而对于INSERT、UPDATE和DELETE等DML语句,该函数执行一次即可完成。
4). sqlite3_column
该函数用于获取当前行指定列的数据,然而严格意义上讲,此函数在SQLite的接口函数中并不存在,而是由一组相关的接口函数来完成该功能,其中每个函数都返回不同类型的数据,如:
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_bytes16
sqlite3_column_double
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_text
sqlite3_column_text16
sqlite3_column_type
sqlite3_column_value
sqlite3_column_count
其中sqlite3_column_count函数用于获取当前结果集中的字段数据。
5). sqlite3_finalize
该函数用于销毁prepared statement对象,否则将会造成内存泄露。
6). sqlite3_close
该函数用于关闭之前打开的database_connection对象,其中所有和该对象相关的prepared_statements对象都必须在此之前先被销毁。
使用 SQLite API操作数据库:
10 | sqlite3_stmt *ppStmt=NULL; |
12 | iRet = sqlite3_open( "test.db" , &db); |
15 | printf ( "Can't open database: %s\n" , sqlite3_errmsg(db)); |
19 | printf ( "open database!\n" ); |
32 | iRet = sqlite3_exec(db, "insert into qttest(id,userName,userPwd) values(null,\"cat\",\"123456\")" , NULL, NULL, &ErrMsg); |
33 | if ( iRet !=SQLITE_OK ) |
35 | printf ( "SQL error: %s\n" , ErrMsg); |
38 | printf ( "insert ok! \n" ); |
51 | iRet = sqlite3_prepare(db, "select id,userName,userPwd from qttest" , -1, &ppStmt, NULL); |
52 | if ( iRet != SQLITE_OK ) |
54 | printf ( "Select error\n" ); |
56 | sqlite3_finalize(ppStmt); |
59 | printf ( "user info:\n" ); |
60 | while (sqlite3_step(ppStmt) == SQLITE_ROW) |
62 | printf ( "Id: %s\t" , sqlite3_column_text(ppStmt, 0)); |
63 | printf ( "Name: %s\t" , sqlite3_column_text(ppStmt, 1)); |
64 | printf ( "Pwd: %s\n" , sqlite3_column_text(ppStmt, 2)); |
66 | sqlite3_finalize(ppStmt); |
转载:http://www.ichanging.org/qt-sqlite.html