
Qt使用SQL
主要是下面的几个类
QSqlDatabase 建立于数据库的链接
QSqlQuery 用于执行SQL语句
QSqlTableModel 结合QTableView可以输出数据库的表
贴下我写的简单Demo
[cpp]view plaincopyprint?
1.QSqlDatabase db =QSqlDatabase::addDatabase("QMYSQL"); // becomes the new default connection
2. db.setUserName("root");//用户名
3. db.setPassword("password");//密码
4. db.setHostName("localhost");
5. db.setDatabaseName("test");//数据库名
6. db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1");//使用SSL
7. db.setPort(3306);//端口
8. if(db.open()){
9. qDebug()<<"open/n"< 11. else{ 12. qDebug()<<"open faile/n"; 13. } 14. QSqlQuery query;//用于执行SQL语言 15. query.exec("show databases");//很方便的 16. while (query.next()) { 17. qDebug()< 19. } 20. 21. QSqlTableModel *model = new QSqlTableModel;//间接将数据库表装入QTableView 22. model->setTable("people"); //表名 23. model->setEditStrategy(QSqlTableModel::OnManualSubmit); 24. model->select(); 25. //model->removeColumn(0); // don't show the ID 26. //model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID")); 27. model->setHeaderData(0, Qt::Horizontal, tr("Name")); 28. model->setHeaderData(1, Qt::Horizontal, tr("Age")); 29. model->setHeaderData(2, Qt::Horizontal, tr("Sex")); 30. 31. 32. QTableView *view = new QTableView(this); 33. view->setModel(model); 34. 35. db.close(); 36. 37. QGridLayout * gl=new QGridLayout(); 38. gl->addWidget(view); 39. this->setLayout(gl); 2、 下面是最终的现实效果如下: 现在先做一个显示的界面,界面是由一个表格试图和三个按钮组成。我的大概流程是: <1>在对话框窗口先创建一个栅格布局管理器,添加一个表格视图窗口部件。 <2>创建一个水平布局管理器,在水平布局管理器中添加三个按钮,最后将水平布局管理器添加到栅格布局管理器中。 <3>创建三个按钮的信号与槽 <4>数据库的使用分为三步:(1)QsqlDatabase建立数据库的链接(2)QsqlQuery用于执行SQL语句(3)QsqlTableModel结合QtableView可以输出数据库的表。 <5>效果测试点击connect按钮链接打开数据库 #include #include "table.h" int main(intargc,char *argv[]) { QApplicationapp(argc,argv); Table *table = new Table; table->show(); returnapp.exec(); } #ifndef TABLE_H #define TABLE_H #include #include classQGridLayout; classQPushButton; classQHBoxLayout; classTable:publicQDialog { Q_OBJECT public: //继承公共对话框窗体派生类 Table(QWidget *parent = 0); //创建各个类的指针 QTableView *table; QGridLayout *gridLayout; QPushButton *connectButton; QPushButton *executionButton; QPushButton *displayButton; QHBoxLayout *verticalLayout; private slots: //创建三个按钮槽函数 voidon_connectButton_clicked(); voidon_executionButton_clicked(); voidon_displayButton_clicked(); }; #endif #include #include #include #include #include "table.h" Table::Table(QWidget *parent) :QDialog(parent) { //创建视图及按钮的对象 table = new QTableView; connectButton = new QPushButton("connect"); executionButton = new QPushButton("execution"); displayButton = new QPushButton("display"); //建立三个信号与槽函数链接 connect(connectButton,SIGNAL(clicked()),this,SLOT(on_connectButton_clicked())); connect(executionButton,SIGNAL(clicked()),this,SLOT(on_executionButton_clicked())); connect(displayButton,SIGNAL(clicked()),this,SLOT(on_displayButton_clicked())); //创建一个水平布局管理器,布局三个按钮 verticalLayout = new QHBoxLayout; verticalLayout->addWidget(connectButton); verticalLayout->addWidget(executionButton); verticalLayout->addWidget(displayButton); //创建一个栅格布局管理器对整体窗口部件的排布。 gridLayout = new QGridLayout; gridLayout->addWidget(table,0,0,1,1); gridLayout->addLayout(verticalLayout,1,0,1,1); setLayout(gridLayout); //设置窗口的大小 resize(500,400); } void Table::on_connectButton_clicked() { //链接函数实现数据库的链接功能 QSqlDatabasedb = QSqlDatabase::addDatabase("QMYSQL"); //添加QMYSQL数据库驱动 db.setHostName("localhost"); //设置登陆的主机名为localhost db.setUserName("root"); //登陆的用户是超级用户 root db.setPassword("123456"); //登陆密码是123456 db.setDatabaseName("student"); //打开的数据库表格,这个表格式预先创建好的。用>create database student;创建。 bool ok = db.open(); //布尔类型,打开数据。 if(ok) //if判断 { qDebug()<<"open Database!"< } else { QMessageBox::critical(0,QObject::tr("Database Error"),db.lastError().text()); //否则输出数据库的消息框错误信息 } } void Table::on_executionButton_clicked() { //按executionButton按钮执行SQL语句 QSqlQuery query; //创建一个执行数据库SQL语句对象 query.exec("drop table employee"); //如果存在employee数据库表格,先删除 query.exec("create table employee(id int(11) primary key,namevarchar(50),description varchar(255))"); //在创建数据库表格employee query.exec("insert into employee values(1,'zhangsan','student')"); query.exec("insert into employee values(2,'lisi','teacher')"); query.exec("insert into employee values(3,'wangwu','professor')"); //插入三个记录 } void Table::on_displayButton_clicked() { //用数据库表格模式结合试图显示数据库内容。 QSqlTableModel *model = new QSqlTableModel; //创建数据表模式对象 model->setTable("employee"); //设置数据库表上的运作模式以employee表名,不选择从数据表格以外获取信息 model->setEditStrategy(QSqlTableModel::OnManualSubmit); //所有更改将被缓存在模型中,直到submitAll()或revertAll()函数被调用 model->select(); //select()函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。 model->setHeaderData(0,Qt::Horizontal,QObject::tr("ID")); model->setHeaderData(1,Qt::Horizontal,QObject::tr("name")); model->setHeaderData(2,Qt::Horizontal,QObject::tr("description")); //对应指定的字段并设置对应的水平标题显示 table->setModel(model); //将这个数据库表格模式用视图显示出来。 } 在关闭对话框后出现查询应用默认数据库连接错误: QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work. 我googel以下,参照http://www.cnblogs.com/codingmylife/archive/2010/04/27/1722404.html 的内容测试,还是解决不了。 在第二个按钮末尾添加下面的语句: QString name; { name = QSqlDatabase::database().connectionName(); } QSqlDatabase::removeDatabase(name); On_executionButton_clicked()函数末尾添加,执行SQL语句后关闭窗口时有效的,但在on_displayButton_clicked()函数末尾添加却没有效。问题还在解决当中。。。 Qt中MySQL数据库操作 首先,要查询相关的驱动是否已经装好了,可以用以下的程序进行验证: #include #include #include #include int main(intargc, char *argv[]) { QCoreApplicationa(argc, argv); qDebug()<<"Available drivers:"; QStringList drivers = QSqlDatabase::drivers(); foreach(QString driver, drivers) qDebug() <<"/t" << driver; returna.exec(); } 结果如下: 接着是连接数据库: #include #include #include boolcreateConnection() { QSqlDatabasedb = QSqlDatabase::addDatabase("QMYSQL"); db.setDatabaseName("test"); db.setUserName("root"); db.setPassword("123456"); bool ok = db.open(); if(!ok){ QMessageBox::critical(0, QObject::tr(" 连接数据库失败!!! "), db.lastError().text()); return false; }else{ QMessageBox::information(0, QObject::tr("Tips"), QObject::tr(" 连接数据库成功!!! ")); return true; } } int main(intargc, char *argv[]) { QApplicationa(argc, argv); QTextCodec *codec= QTextCodec::codecForName("GB2312"); QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); if(!createConnection()) return 1; returna.exec(); } 插入操作: //ODBC数据库表示方式 QSqlQuery query; query.prepare( “insert into student (id, name) ” “values (:id, :name) ”); query.bindValue(0, 5); query.bindValue(1, “sixth ”); query.exec(); //Oracle表示方式 query.prepare( “insert into student (id, name) ” “values (?, ?) ”); query.bindValue(0, 5); query.bindValue(1, “sixth ”); query.exec(); //使用 addBindValue()函数,省去了编号,它是按属性顺序赋值的 query.prepare( “insert into student (id, name) ” “values (?, ?) ”); query.addBindValue(5); query.addBindValue( “sixth ”); query.exec(); //使用 ODBC方法时,可以将编号用实际的占位符代替 query.prepare( “insert into student (id, name) ” “values (:id, :name) ”); query.bindValue( “:id ”, 5); query.bindValue( “:name ”, “sixth ”); query.exec(); 注意:最后一定要执行 exec() ,否则上面的语句是不会被执行的。 //进行多个记录的插入时,可以利用绑定进行批处理 QSqlQuery q; q.prepare( “insert into student values (?, ?) ”); QVariantListints; ints<< 10 << 11 << 12 << 13; q.addBindValue(ints); QVariantList names; names << “xiaoming ” << “xiaoliang ” << “xiaogang ” < q.addBindValue(names); if (!q.execBatch()) // 进行批处理,如果出错就输出错误 qDebug() < 查询操作: //返回全部的属性和结果集 QSqlQuery query; query.exec( “select * from student ”);// 执行查询操作 qDebug() << “exec next() : ”; if(query.next()) // 开始就先执行一次next() 函数,那么query 指向结果集的第一条记录 { introwNum = query.at(); // 获取query 所指向的记录在结果集中的编号 intcolumnNum = query.record().count(); // 获取每条记录中属性(即列)的个数 intfieldNo = query.record().indexOf( “name ”); // 获取 ” name ”属性所在列的编号,列从左向右编号,最左边的编号为 0 int id = query.value(0).toInt(); // 获取id 属性的值,并转换为int 型 QString name = query.value(fieldNo).toString(); // 获取name 属性的值 qDebug() << “rowNum is : ” < <<” name is : ” << name <<”columnNum is : ” < qDebug() << “exec seek(2) : ”; if(query.seek(2)) // 定位到结果集中编号为2 的记录,即第三条记录,因为第一条记录的编号为 0 { qDebug() << “rowNum is : ” << query.at() <<”id is : ”< qDebug() << “exec last() : ”; if(query.last()) // 定位到结果集中最后一条记录 { qDebug() << “rowNum is : ” << query.at() << ” id is : ” < 结果集其实就是查询到的所有记录的集合,而在QSqlQuery 类中提供了多个函数来操作这个集合,需要注意这个集合中的记录是从0开始编号的。最常用的有: seek(int n) :query 指向结果集的第n 条记录。 first() :query 指向结果集的第一条记录。 last() :query 指向结果集的最后一条记录。 next() :query 指向下一条记录,每执行一次该函数,便指向相邻的下一条记录。 previous() :query 指向上一条记录,每执行一次该函数,便指向相邻的上一条记录。 record() :获得现在指向的记录。 value(int n) :获得属性的值。其中n 表示你查询的第n 个属性,比方上面我们使用 “ select * from student ”就相当于 “ select id, name from student ”,那么value(0) 返回id 属性的值,value(1) 返回name 属性的值。该函数返回QVariant 类型的数据,关于该类型与其他类型的对应关系,可以在帮助中查看QVariant 。 at() :获得现在query 指向的记录在结果集中的编号。 需要说明,当刚执行完query.exec( “select * from student ”); 这行代码时,query 是指向结果集以外的,我们可以利用query.next() ,当第一次执行这句代码时,query 便指向了结果集的第一条记录。当然我们也可以利用seek(0) 函数或者first() 函数使query 指向结果集的第一条记录。但是为了节省内存开销,推荐的方法是,在query.exec( “select * from student ”); 这行代码前加上query.setForwardOnly(true); 这条代码,此后只能使用next() 和seek() 函数。 //满足一定条件的结果集,方法一 QSqlQuery query; query.prepare( “select name from student where id = ? ”); int id =2; // 从界面获取id 的值 query.addBindValue(id); // 将id 值进行绑定 query.exec(); query.next(); // 指向第一条记录 qDebug() < //方法二 QSqlQuery query; query. exec( QObject :: tr( "select * from student where id = %1" ). arg( 2 )); if (! query. next()) qDebug()<< "none" ; else qDebug()<< query. value( 0 ). toInt()<< query. value( 1 ). toString(); 事务是数据库的一个重要功能,所谓事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。在Qt 中用transaction() 开始一个事务操作,用commit() 函数或rollback() 函数进行结束。commit() 表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到数据库,事务正常结束。rollback() 表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。 QSqlQuery query; if(QSqlDatabase::database().transaction()) // 启动事务操作 { // 下面执行各种数据库操作 query.exec( “insert into student values (14, ‘hello’) ”); query.exec( “delete from student where id = 1 ″); // if(!QSqlDatabase::database().commit()) { qDebug() < qDebug() < } // 输出整张表 query.exec( “select * from student ”); while(query.next()) qDebug() < // QSqlQueryModel QSqlQueryModel *model = new QSqlQueryModel; model->setQuery( “select * from student ”); model->setHeaderData(0, Qt::Horizontal, tr( “id ”)); model->setHeaderData(1, Qt::Horizontal, tr( “name ”)); QTableView *view = new QTableView; view->setModel(model); view->show(); //QSqlTableModel QSqlTableModel *model; model = new QSqlTableModel(this); model->setTable( “student ”); model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->select(); // 选取整个表的所有行 // model->removeColumn(1); // 不显示name 属性列 , 如果这时添加记录,则该属性的值添加不上 ui->tableView->setModel(model); // ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 使其不可编辑 //过滤 model->setFilter(QObject::tr(“name = ‘%1 ′”).arg(name)); // 根据姓名进行筛选 model->select(); // 显示结果 //删除操作 intcurRow = ui->tableView->currentIndex().row(); // 获取选中的行 model->removeRow(curRow); // 删除该行 int ok = QMessageBox::warning(this,tr( “删除当前行! ”),tr( “你确定 ” “删除当前行吗? ” ), QMessageBox::Yes,QMessageBox::No); if(ok == QMessageBox::No) { model->revertAll(); // 如果不删除,则撤销 } else model->submitAll(); // 否则提交,在数据库中删除该行 //插入操作 introwNum = model->rowCount(); // 获得表的行数 int id = 10; model->insertRow(rowNum); // 添加一行 model->setData(model->index(rowNum,0),id); model->submitAll();// 记得提交 //QSqlRelationalTableModel //create table student (id int primary key, name vchar,courseint) // create table course (id int primary key, name vchar, teacher vchar) model = new QSqlRelationalTableModel(this); model->setEditStrategy(QSqlTableModel::OnFieldChange); // 属性变化时写入数据库 model->setTable( “student ”); model->setRelation(2,QSqlRelation( “course ”, ”id ”, ”name ”)); // 将student 表的第三个属性设为course 表的id 属性的外键,并将其显示为course 表的name 属性的值 model->setHeaderData(0, Qt::Horizontal, QObject::tr( “ID ”)); model->setHeaderData(1, Qt::Horizontal, QObject::tr( “Name ”)); model->setHeaderData(2, Qt::Horizontal, QObject::tr( “Course ”)); model->select(); ui->tableView->setModel(model); ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));// 如果用户更改课程属性,那么他只能在课程表中有的课程中进行选择,而不能随意填写课程。在Qt 中的QSqlRelationalDelegate 委托类就能实现这个功能。我们只需添加一行代码 3、连接mysql数据库 QSqlDatabasedb = QSqlDatabase::addDatabase("QMYSQL"); // 使用mysql数据库驱动 db.setHostName("localhost"); db.setDatabaseName("exampledb"); // 数据库名称 db.setUserName("sa"); // 用户名 db.setPassword("1"); // 密码 bool ok = db.open(); // 尝试连接数据库 if(ok) { QSqlQuerymyquery; if(myquery.exec("select * from employeedb")) { intnum = 0; if(db.driver()->hasFeature(QSqlDriver::QuerySize)) { num = myquery.size(); // 如果支持结果影响的行数,那么直接记录下来 } else { myquery.last(); //否则定位到结果最后 num = myquery.at() + 1; } //这里添加数据库的查询结果处理操作 } else // 如果查询失败 { QSqlError error = myquery.lastError(); } } else // 打开数据库失败 { }
