前言:通常我们操作数据库时,需要使用sql语句;在qt开发环境中提供了QSqlTableModel类,它可以通过简单的接口去操作数据库,即使不熟悉sql语句也可以对数据库进行大部分的操作,而且该模型还具有数据缓存功能,在修改数据后并不是立刻同步到数据库中,允许用户进行数据撤回,如果已经提交到数据库的数据就不能进行撤回了;QSqlTableModel还有一个非常方便的操作就是它可以将数据库的所有记录显示到QTableView控件上,并可以直接通过QTableView控件对数据库任意位置的数据进行修改。下面就QSqlTableModel类的使用进行举例说明。
Qt 5.14完整源码下载,下载链接;源码附带详细注释,十分具有参考意义。
效果图预览:
/*设置使用的数据库驱动*/
QSqlDatabase sqldb = QSqlDatabase::addDatabase("QSQLITE");
/*打开指定文件下的数据库文件,如果不存在则创建*/
sqldb.setDatabaseName("./test.db");
if(sqldb.open()){
qDebug() <<"[test.db]数据库打开成功。";
}else{
qDebug() <<"[test.db]数据库打开失败。";
}
本地数据库可体现为一个文件,解读这个文件需要特定的数据库驱动,不同的数据库类型需要对应的数据库驱动。我上面采用的数据库驱动是QSQLITE,可通过下面的命令查看当前环境支持的数据库类型:
/*获取当前环境支持哪些数据库类型*/
qDebug() <<"支持的数据库类型:" <
执行后的结果是:
支持的数据库类型: ("QSQLITE", "QMYSQL", "QMYSQL3", "QODBC", "QODBC3", "QPSQL", "QPSQL7")
使用QSqlQuery类执行sql语句,对数据库插入一条记录:
/*用来执行sql语句的对象*/
QSqlQuery query(sqldb);
/*创建一个数据表*/
query.exec(QObject::tr("create table student (id int primary key, name vchar ,age int)"));
/*插入一条记录*/
query.exec(QObject::tr("insert into student values (0,'李小明',18)"));
上面的语句在数据库sqldb创建了一个名为student的数据表,数据表里面包含了三个字段id、name、age,类型分别为int、vchar、int。数据库可以有多个数据表,数据表之间可有一对多的关系;数据表中的字段表示数据表中记录的内容项,如一个学生的id、name、age。数据库 > 数据表 > 记录 > 字段。
使用QSqlTableModel类绑定数据库,并将数据库里的内容显示在tableview控件上:
sqlmodel = new QSqlTableModel(this,sqldb);
/*选择一个数据库里的其中一个数据表*/
sqlmodel->setTable("student");
/*设置修改tableview时是否立刻同步到数据库文件里*/
sqlmodel->setEditStrategy(QSqlTableModel::OnManualSubmit);//使用submitAll() or revertAll() 手动同步
/*选取整个表的所有行*/
sqlmodel->select();
ui->tableView->setModel(sqlmodel);
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
实例化一个QSqlTableModel绑定了上面我们新建的数据库sqldb,然后需要选择数据库里面其中一个数据表,如果数据表不存在则会返回失败;使用sqlmodel->setEditStrategy可以设置编辑策略,修改是否立刻同步到数据库文;ui->tableView->setModel(sqlmodel)之后数据库sql里的数据表student所有的内容将在tableview上显示出来。
1.新增记录
/*在表的最后添加一行*/
sqlmodel->insertRow(rowCnt);
/*设置新行的第0列的值*/
sqlmodel->setData(sqlmodel->index(rowCnt,0),id);
rowCnt是所插入的行位置,id是新记录字段"id"的值;setData还可以对已存在的数据项进行修改。
2.删除记录
/*获取当前选中的行*/
int curRow = ui->tableView->currentIndex().row();
if( QMessageBox::critical(0 , tr("警告") ,tr("确认删除?"),QMessageBox::Yes,QMessageBox::No, 0) == QMessageBox::Yes){
sqlmodel->removeRow(curRow);
}
curRow是通过鼠标在tableview选中的行号,删除操作时弹框再次确认是否删除,确认后不会马上消失在tableview里,在它的前面的序号会出现一个叹号,如果点击撤就会恢复这条记录,如果点击提交才会真正在数据库里删除这条记录。
3.查询记录
if(!name.isEmpty() && id != -1){
sqlmodel->setFilter(QObject::tr("name = '%1' id = '%2").arg(name).arg(id));
}else if(!name.isEmpty()){
sqlmodel->setFilter(QObject::tr("name = '%1'").arg(name));
}else if(id != -1){
sqlmodel->setFilter(QObject::tr("id = '%1'").arg(id));
}
sqlmodel->select(); //显示结果
可以同时进行名字name和id筛选,也可以单独一个字段的筛选;相当于SQL语句的:SELECT * FROM student WHERE name = "名字"。
4.排序
void MainWindow::AscendingButton(void)
{
/*获取当前选中列*/
int curCol = ui->tableView->currentIndex().column();
sqlmodel->setSort(curCol,Qt::AscendingOrder);
/*显示整个表的内容*/
sqlmodel->select();
}
void MainWindow::DescendingButton(void)
{
/*获取当前选中列*/
int curCol = ui->tableView->currentIndex().column();
sqlmodel->setSort(curCol,Qt::DescendingOrder);
/*显示整个表的内容*/
sqlmodel->select();
}
curCol是鼠标当前选中的列,setSort需要两个参数(列号,升序/降序)。
5.其他操作
model->submitAll();//提交修改
model->revertAll(); //撤销修改
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->lastError();//获取最后一次的错误信息
OnManualSubmit表明需要submitAll()提交修改才能生效,没有提交之前可以revertAll()撤销修改,提交之后就不能进行撤销了;在操作数据库时,可能会出现条件不满足导致操作失败,我们可以通过lastError获取错误信息,进行错误定位。