<一> 第一个qt+sqlite3程序

    目前想学习下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

    这里设置prefix(安装目录)、host(目标平台)、CC(编译器)这三个参数即可。命令 “./configure --prefix=/usr/local/arm_sqlite --host=arm-linux CC=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-gcc” 。然后 make,make install。

    下面开始第一个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界面如下。

<一> 第一个qt+sqlite3程序_第1张图片

    这里工程要实现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");

    sqlite3_open()函数会打开一个数据库文件,当这个文件不存在则创建。下面是创建一个表格的代码。

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");
}

    这里,将id号赋值为行号,姓名为"ws_行号",年龄为"20+行号",然后剩下两个参数固定,由于创建表格与插入数据都不需要调用回调函数,所以这里sqlite3_exec() 函数的第三个和第四个参数分别设置为NULL和零。接下来是查询语句,代码如下。

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");
}

    这里将id号作为查询条件,执行了数据库的查询操作,查询的结果可以通过回调函数来读出,如果查询的为多行,则回调函数会被多次顺序调用。这里的回调函数为_sql_callback(),其中传递给回调函数的指针为ui指针。下面看回调函数的定义。

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;
}

    回调函数的参数中,p指针为传入的参数,即上面传入的ui指针,使用时要先将其强制转换。argc参数表示查询的一行数据有多少项,szColName指向该项数据的属性名,argv指向该项数据的值。这里将其显示到ui界面的textEdit控件上。下面来看删除行的操作,代码如下。

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");
}

    删除行时,调用的命令为"delete from users where id=n",删除一行后,应将行数减一,这里行数是通过ui控件的horizontalSlider 来表示的。接下来是删除表格的命令,代码如下。

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");
}

    删除表格的命令比较简单,为“drop table 表名”。最后来张在开发板上运行的图片。



    运行时,会通过串口打印命令执行的状态。如果启动应用时,表格已经存在,这个时候,为了是“查询下一条”这个按钮可以执行往下查询数据的命令,应该将表格的最大行数读出来,作为查询的参考条件。查询表格行数的命令是“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下载。

你可能感兴趣的:(行数,qt,sqlite3,s5pv210,smart210)