目前想学习下sqlite数据库编程。之前在开发板上运行Qt程序时,出现了只能读数据库,不能进行写入的情况。在网上查得可以不使用Qt自带的数据库,重新编译一个sqlite3库,然后在Qt中使用这个库就可以了。为了使学习的更为全面,报着认真敲代码的态度,我将这个学习过程以博客的形式写出来。对程序中可能出现的问题,尽量不留死角。同时,在后面尽量解决以前遇到的问题。
现在开发工具如下:
smart210开发板,linux3.0.8内核,qt4.8.6程序库,虚拟机ubuntu12.04系统,交叉编译器arm-linux-gcc 4.5.1。
首先是配置下环境,qte库在友善之臂中的光盘中已经给出,这里我简单说一下sqlite3的编译。首先进入源码目录,执行 “./configure --help > help.txt” 命令,将帮助信息打印到help.txt文件中,打开这个文件,可看到如下说明:
Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [/usr/local] System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> LIBS libraries to pass to the linker, e.g. -l<library> CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor
下面开始第一个qt+sqlite3工程。
首先建立一个Qt Widgets Application 工程,这里命名为1_sqlite3。在工程文件1_sqlite3.pro中添加下面两行代码,来指定sqlite3的库与头文件位置。
LIBS += -L/usr/local/arm_sqlite/lib -lsqlite3 INCLUDEPATH += /usr/local/arm_sqlite/include接下来创建ui界面如下。
这里工程要实现sqlite3的基本功能,如:创建一个表格、删除一个表格、插入一行数据、删除一行数据、查询一条数据并显示。
首先看数据库的打开,代码如下。
//连接数据库 int ret = sqlite3_open("./test.db", &db); if (ret != SQLITE_OK) { fprintf(stderr, "Cannot open datebase %s\n", sqlite3_errmsg(db)); sqlite3_close(db); this->close(); } printf("Connect success\n");
void MainWindow::on_pushButton_ct_clicked() { const char *sSQL = "create table users (" "id integer PRIMARY KEY AUTOINCREMENT, " "name varchar(40) NOT NULL, " "age integer NOT NULL, " "birthday datetime NOT NULL, " "email varchar(40) NOT NULL);"; //执行建表SQL int ret = sqlite3_exec(db, sSQL, NULL, 0, &pErrMsg); if (ret != SQLITE_OK) { fprintf(stderr, "SQL create error: %s\n", pErrMsg); sqlite3_free(pErrMsg); //be supposed return; } rows = 0; index = 0; printf("Datebase table creator success!!\n"); }
使用sqlite3_exec()函数可以执行一条数据库指令,函数有5个参数,第一个是打开的数据库索引,第二个是要执行的语句,第三个是回调函数,当成功执行数据库语句后就会调用这个函数,第四个是传递给回调函数的参数,第五个是用来存储错误信息。这里创建了一个users表格,其有5列数据,第一列为id,设为主键。创建表格成功后,将表格的行数rows,当前查询的行号置零。接下来是插入一行数据的指令,代码如下。
void MainWindow::on_pushButton_ic_clicked() { rows++; QByteArray qb = QString("insert into users values" "(%1, 'ws_%2', %3, '1989-5-4', '[email protected]');") .arg(rows).arg(rows).arg(20+rows).toLatin1(); const char *sSQL = qb.data(); //执行插入数据 int ret = sqlite3_exec(db, sSQL, NULL, 0, &pErrMsg); if (ret != SQLITE_OK) { fprintf(stderr, "SQL insert error: %s\n", pErrMsg); sqlite3_free(pErrMsg); //be supposed return; } ui->horizontalSlider->setMaximum(rows); printf("Datebase insert success!\n"); }
void MainWindow::on_pushButton_sp_clicked() { if(index == 0) index = 1; if(index > 1) index--; QByteArray qb = QString("select * from users where id=%1").arg(index).toLatin1(); const char *sSQL = qb.data(); //执行查询操作 int ret = sqlite3_exec(db, sSQL, _sql_callback, ui, &pErrMsg); if (ret != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", pErrMsg); sqlite3_free(pErrMsg); return; } ui->horizontalSlider->setValue(index); printf("Datebase inquire success!!\n"); }
int MainWindow::_sql_callback(void *p, int argc, char **argv, char **szColName) { Ui::MainWindow *ui = (Ui::MainWindow*)p; printf("Select argc:%d\n", argc); ui->textEdit->clear(); for (int i = 0; i < argc; i++) { ui->textEdit->append(QString("Property :%1, Value :%2").arg(szColName[i]).arg(argv[i])); } return 0; }
void MainWindow::on_pushButton_dc_clicked() { if(rows > 0) rows--; else{ printf("No more row..\n"); return; } QByteArray qb = QString("delete from users where id=%1").arg(rows).toLatin1(); const char *sSQL = qb.data(); //delete row int ret = sqlite3_exec(db, sSQL, NULL, 0, &pErrMsg); if (ret != SQLITE_OK) { fprintf(stderr, "SQL insert error: %s\n", pErrMsg); sqlite3_free(pErrMsg); //be supposed return; } ui->horizontalSlider->setMaximum(rows); printf("Datebase insert success!\n"); }
void MainWindow::on_pushButton_dt_clicked() { const char *sSQL = "drop table users"; //delete table int ret = sqlite3_exec(db, sSQL, NULL, 0, &pErrMsg); if (ret != SQLITE_OK) { fprintf(stderr, "SQL delete error: %s\n", pErrMsg); sqlite3_free(pErrMsg); //be supposed return; } rows = 0; index = 0; printf("Datebase table delete success!!\n"); }
运行时,会通过串口打印命令执行的状态。如果启动应用时,表格已经存在,这个时候,为了是“查询下一条”这个按钮可以执行往下查询数据的命令,应该将表格的最大行数读出来,作为查询的参考条件。查询表格行数的命令是“select count(*) from 表名”,下面是查询表格最大行数的代码。
int MainWindow::sql_getrows(QString table) { sqlite3_stmt *stat; QByteArray qb = QString("select count(*) from %1").arg(table).toLatin1(); const char *sSQL = qb.data(); int ret = sqlite3_prepare_v2(db, sSQL, -1, &stat, 0); if (ret != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", "prepare_v2"); return 0; } int count=0; if(sqlite3_step(stat)==SQLITE_ROW) { count=sqlite3_column_int(stat, 0); } sqlite3_finalize(stat); //perpare will lock the db, this unlock the db return count; }
整个工程文件可以在http://download.csdn.net/detail/westlor/9395502下载。