SQLite是一款开源轻量级的数据库软件,不需要server,可以集成在其他软件中,非常适合嵌入式系统。Qt5以上版本可以直接使用SQLite(Qt自带驱动)。
引入SQL模块
在Qt项目文件(.pro文件)中,加入SQL模块:
QT += sql
在需要使用SQL的类定义中,引用相关头文件。例如:
#include <QSqlDatabase> #include <QSqlError> #include <QSqlQuery>
QSqlDatabase类表示到数据库的连接。QSqlDatabase类提供了一个接口,用于通过连接访问数据库。QSqlDatabase的一个实例表示连接。该连接通过受支持的数据库驱动程序之一提供对数据库的访问,该驱动程序派生自QSqlDriver。或者,您可以从QSqlDriver子类化自己的数据库驱动程序。
创建一个连接(例如。调用静态addDatabase()函数之一,在其中指定要使用的驱动程序或驱动程序类型(即)和连接名称。一个连接可以通过它自己的名称而不是它所连接的数据库的名称来识别。您可以有多个到一个数据库的连接。QSqlDatabase还支持默认连接的概念
,即未命名连接。要创建默认连接,在调用addDatabase()时不要传递连接名参数
。随后,当您调用任何接受连接名称参数的静态成员函数时,如果没有传递连接名称参数,则假定默认连接。下面的代码片段展示了如何创建和打开到PostgreSQL数据库的默认连接。
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("acidalia"); db.setDatabaseName("customdb"); db.setUserName("mojito"); db.setPassword("J0a1m8"); bool ok = db.open();
创建QSqlDatabase对象之后,使用
setDatabaseName()
、setUserName()
、setPassword()
、setHostName()
、setPort()
和setConnectOptions()
设置连接参数。然后调用open()来激活到数据库的物理连接。在打开连接之前,连接不可用。上面定义的连接将是默认连接,因为我们没有给addDatabase()指定连接名。
QSqlQuery类提供了执>行和操作SQL语句的方法。QSqlQuery封装了在QSqlDatabase上执行的SQL查询中创建、导航和检索数据所涉及的功能。它可以用来执行
DML
(数据操作语言)语句,如SELECT
、INSERT
、UPDATE
和DELETE
,以及DDL
(数据定义语言)语句,如CREATE TABLE
。它还可以用来执行非标准SQL的特定于数据库的命令(例如,SET DATESTYLE=ISO for PostgreSQL)。成功执行的SQL语句将查询的状态设置为active,以便isActive()返回true。否则,查询的状态被设置为非活动状态。在这两种情况下,当执行一个新的SQL语句时,查询被定位在一个无效的记录上。在检索值之前,必须将活动查询导航到有效记录(以便isValid()返回true)。对于某些数据库,如果在调用commit()或rollback()时存在一个活动查询(即SELECT语句),则提交或回滚将失败。
QSqlError类提供SQL数据库错误信息。QSqlError对象可以提供特定于数据库的错误数据,包括
driverText()
和databaseText()
消息(或者两者都连接为text()
、错误号()和类型()。这些函数都有setter
,因此您可以从自己的类(例如从自己的SQL驱动程序)创建和返回QSqlError
对象。还请参见QSqlDatabase::lastError()
和QSqlQuery::lastError()
。
检查连接、添加数据库驱动、设置数据库名称、数据库登录用户名、密码。检查连接、添加数据库驱动、设置数据库名称、数据库登录用户名、密码。
QSqlDatabase database; if (QSqlDatabase::contains("qt_sql_default_connection")) { database = QSqlDatabase::database("qt_sql_default_connection"); } else { database = QSqlDatabase::addDatabase("QSQLITE"); database.setDatabaseName("MyDataBase.db"); database.setUserName("XingYeZhiXia"); database.setPassword("123456"); }
上述代码解释:
(1)第一行中,建立了一个QSqlDatabase对
象,后续的操作要使用这个对象。
(2)if
语句用来检查指定的连接(connection)是否存在。这里指定的连接名称(connection name)是qt_sql_default_connection
,这是Qt默认连接名称。实际使用时,这个名称可以任意取。如果判断此连接已经存在,那么QSqlDatabase::contains()
函数返回true。此时,进入第一个分支,QSqlDatabase::database()
返回这个连接。
(3)如果这个连接不存在,则进入else分支,需要创建连接,并添加数据库。在else分支第一行,addDatabase()
的参数QSQLITE
是SQLite对应的驱动名,不能改。而且需要注意的是,addDatabase()的第二个参数被省略了,第二个参数的默认参数就是上面提到的Qt默认连接名称qt_sql_default_connection
。如果需要使用自定义的连接名称(如果程序需要处理多个数据库文件的话就会这样),则应该加入第二个参数,例如
database = QSqlDatabase::addDatabase("QSQLITE", "my_sql_connection);
这个时候,如果在另一个地方需要判断my_sql_connection连接是否存在,就应该使用if (QSqlDatabase::contains("my_sql_connection"))
。
(4)else分支第二行中,setDatabaseName()的参数是数据库文件名。如果这个数据库不存在,则会在后续操作时自动创建;如果已经存在,则后续的操作会在已有的数据库上进行。
(5)else分支后面两行,设置用户名和密码。用户名,密码都可以随便取,也可以省略。
使用open()打开数据库,并判断是否成功。注意,在第一步检查连接是否存在时,如果连接存在,则在返回这个连接的时候,会默认将数据库打开。if (!database.open())使用open()打开数据库,并判断是否成功。注意,在第一步检查连接是否存在时,如果连接存在,则在返回这个连接的时候,会默认将数据库打开。
if (!database.open()) { qDebug() << "Error: Failed to connect database." << database.lastError(); } else { // do something }
如果打开成功,则进入else分支。对数据库的操作都需要在else分支中进行。
3. 关闭数据库
数据库操作完成后,最好关闭。
database.close();
QSqlQuery sqlQuery; QString str_sql = ""; str_sql = "create table student (id int primary key,name text ,age int)"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"创建student表失败!!"; } else { qDebug()<<"创建student表成功"; }
例2.插入数据
str_sql = "insert into student values(1,'wengmq',21)"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"插入数据1失败!!"; } else { qDebug()<<"插入数据1成功"; }
当要插入的参数还不固定时,可以用字符串拼接的方式拼接字符串。
//拼装字符串 方法1:sprintf函数 //拼装字符串 方法1 char text[250] ={0}; sprintf(text,"insert into student values(%d,'%s',%d)",2,"Ming",21); qDebug()<<text;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(text)) { qDebug()<<"插入数据2失败!!"; } else { qDebug()<<"插入数据2成功"; }
//拼装字符串 方法2:QString(推荐使用) str_sql = QString("insert into student values(%1,'%2',%3)").arg(3).arg("Qiang").arg(21); qDebug()<<str_sql;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(str_sql)) { qDebug()<<"插入数据3失败!!"; } else { qDebug()<<"插入数据3成功"; }
例3.修改数据
str_sql = QString("update student set name = '%1' where id = %2").arg("weng").arg(1); qDebug()<<str_sql; if(!sqlQuery.exec(str_sql)) { qDebug()<<"修改数据失败!!"; } else { qDebug()<<"修改数据成功"; }
例4.删除数据
str_sql = QString("delete from student where id = %1").arg(2); qDebug()<<str_sql;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(str_sql)) { qDebug()<<"删除id=2的数据失败!!"; } else { qDebug()<<"删除id=2的数据成功"; }
例5.查询数据
str_sql = "select * from student"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"查询失败!!"; } else { qDebug()<<"查询结果如下:"; while(sqlQuery.next()) { int id = sqlQuery.value(0).toInt(); QString str_name = sqlQuery.value(1).toString(); int age = sqlQuery.value(2).toInt(); qDebug()<<QString("id: %1 name: %2 age: %3").arg(id).arg(str_name).arg(age); } }
心得体会: 这一节的内容其实很重要了,数据库连接QT,到后面数据的存储对做项目至关重要,这节课老师讲的都是QT连接数据都是基础,后面我们还要把这些操作包装成类,一些数据库增删改查的操作封装成函数。课上的时候按着老师的代码敲着打发现总是数据插入失败,后面用qDebug打印出来看发现,拼接完的字符串少了单引号,所以数据库无法识别我们要插入的字符串类型的数据,导致了插入失败!!至于老师的代码为什么可以成功我也不太懂,可能跟编译器有关吧。下次有类似问题可以把要执行的SQL语句打印出来看看。
完整代码如下:
main.cpp
#include <QtGui/QApplication> #include "SQLlite.h" #include <QDebug> #include <QTextCodec> #include <QString> #include <QVariant> //添加数据库头文件 #include <QSqlQuery> #include <QSqlDatabase> #include <QSqlError> //在Qt项目文件(.pro文件)中,加入SQL模块:QT += sql int main(int argc, char *argv[]) { QApplication a(argc, argv); //设置本地编码 头文件 #include <QTextCodec> //编码 QTextCodec *codec = QTextCodec::codecForLocale(); QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); //打印数据库的驱动的模块 qDebug()<<":::::::::驱动::::::::::"<<QSqlDatabase::drivers(); QSqlDatabase database; if (QSqlDatabase::contains("qt_sql_default_connection")) { database = QSqlDatabase::database("qt_sql_default_connection"); } else { database = QSqlDatabase::addDatabase("QSQLITE"); database.setDatabaseName("MyDataBase.db"); database.setUserName("admin"); database.setPassword("123456"); } //打开数据库 if(!database.open()) { qDebug()<<"打开数据库失败!!"<<database.lastError(); } else { qDebug()<<"打开数据库成功!!"; } //创建数据表 QSqlQuery sqlQuery; QString str_sql = ""; str_sql = "create table student (id int primary key,name text ,age int)"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"创建student表失败!!"; } else { qDebug()<<"创建student表成功"; } //插入数据 str_sql = "insert into student values(1,'wengmq',21)"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"插入数据1失败!!"; } else { qDebug()<<"插入数据1成功"; } //拼装字符串 方法1 char text[250] ={0}; sprintf(text,"insert into student values(%d,'%s',%d)",2,"Ming",21); qDebug()<<text;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(text)) { qDebug()<<"插入数据2失败!!"; } else { qDebug()<<"插入数据2成功"; } //拼装字符串 方法2 str_sql = QString("insert into student values(%1,'%2',%3)").arg(3).arg("Qiang").arg(21); qDebug()<<str_sql;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(str_sql)) { qDebug()<<"插入数据3失败!!"; } else { qDebug()<<"插入数据3成功"; } //修改数据 str_sql = QString("update student set name = '%1' where id = %2").arg("weng").arg(1); qDebug()<<str_sql; if(!sqlQuery.exec(str_sql)) { qDebug()<<"修改数据失败!!"; } else { qDebug()<<"修改数据成功"; } //删除数据 str_sql = QString("delete from student where id = %1").arg(2); qDebug()<<str_sql;//控制台上打印拼接好的字符串 if(!sqlQuery.exec(str_sql)) { qDebug()<<"删除id=2的数据失败!!"; } else { qDebug()<<"删除id=2的数据成功"; } //查询数据 str_sql = "select * from student"; if(!sqlQuery.exec(str_sql)) { qDebug()<<"查询失败!!"; } else { qDebug()<<"查询结果如下:"; while(sqlQuery.next()) { int id = sqlQuery.value(0).toInt(); QString str_name = sqlQuery.value(1).toString(); int age = sqlQuery.value(2).toInt(); qDebug()<<QString("id: %1 name: %2 age: %3").arg(id).arg(str_name).arg(age); } } database.close(); SQLlite w; w.show(); return a.exec(); }
.pro文件:
QT += core gui sql TARGET = SQL_test TEMPLATE = app SOURCES += main.cpp\ SQLlite.cpp HEADERS += SQLlite.h FORMS += SQLlite.ui
SQLlite.cpp文件:
#include "SQLlite.h" #include "ui_SQLlite.h" SQLlite::SQLlite(QWidget *parent) : QWidget(parent), ui(new Ui::SQLlite) { ui->setupUi(this); } SQLlite::~SQLlite() { delete ui; }
SQLlite.h文件
#ifndef SQLLITE_H
#define SQLLITE_H
#include
namespace Ui {
class SQLlite;
}
class SQLlite : public QWidget
{
Q_OBJECT
public:
explicit SQLlite(QWidget *parent = 0);
~SQLlite();
private:
Ui::SQLlite *ui;
};
#endif // SQLLITE_H
运行控制台截图:数据库显示: