CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

C++Qt开发——操作MySQL数据库

Qt SQLQt中的Qt SQL模块提供了对数据库的支持,模块中类可分为三层:驱动层,sql接口层,用户层驱动层:(QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlDriverPlugin)为具体的数据库和SQL接口层之间提供了底层的桥梁;。

sql接口层:(QSqlDatabase,QSqlQuery,QSqlError,QSqlRecord)提供了对数据库的访问,其中QSqlDatabase类用来创建连接,QSqlQuery类可以使用SQL语句来实现与数据库交互;

用户接口层:(QSqlTableModel,QSqlQueryModel,QSqlRelationalTableModel)实现了将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,它们是更高层次的抽象;

1.数据库驱动Qt SQL模块使用数据库驱动插件来和不同的数据库接口进行通信由于Qt SQL模块的接口是独立于数据库的,所以所有数据库特定的代码都包含在了这些驱动中Qt默认支持一些驱动:驱动名称数据库QSQLITE2

SQLite2版本QSQLITESQLite3版本QMYSQLMySQLQODBCSQL ServiceQPSQLPostgreSQL(>=7.3版本)【领QT开发教程学习资料,点击下方链接免费领取↓↓

,先码住不迷路~】点击→领取「链接」2.查询驱动qDebug()<<“数据库驱动:”<

QSqlDatabase的一个实例表示连接 该连接通过一个受支持的数据库驱动程序提供对数据库的访问,该驱动程序派生自QSqlDriver通过调用一个静态addDatabase()函数创建一个连接,在该函数中指定要使用的驱动程序或驱动程序类型(取决于数据库的类型)和一个连接名称。

连接可以通过它自己的名称而不是它所连接的数据库的名称得知 可以有一个或多个数据库的连接 QSqlDatabase还支持默认连接的概念,即未命名连接 要创建默认连接,在调用addDatabase()时不要传递连接名称参数。

随后,如果您调用任何静态成员函数而没有指定连接名,则将假定默认连接下面的代码片段展示了如何创建和打开到MySQL数据库的默认连接:QSqlDatabase db = QSqlDatabase::addDatabase(

“QMYSQL”);//添加一个数据库 db.setHostName(“127.0.0.1”); //设置数据库的主机ip db.setPort(3306); //设置端口号 db.setDatabaseName(

“mydb”); //设置数据库的名字 db.setUserName(“root”); //设置数据库的用户名 db.setPassword(“123456”); //设置数据库的密码

bool ok = db.open(); //打开数据库注意:如果提示驱动未加载,则需要编译驱动,并配置一下QSqlDatabase: QMYSQL driver not loaded

QSqlDatabase: available drivers: QSQLITE QODBC QODBC3 QPSQL QPSQL7创建QSqlDatabase对象之后,使用setDatabaseName()、setUserName()、setPassword()、setHostName()、setPort()和setConnectOptions()设置连接参数。

然后调用open()来激活到数据库的物理连接 在您打开连接之前,该连接不可用上面定义的连接将是默认连接,因为我们没有给addDatabase()提供连接名 随后,你可以通过调用database()不带连接名称参数来获得默认连接:。

QSqlDatabase db = QSqlDatabase::database();QSqlDatabase是一个值类 通过一个QSqlDatabase实例对数据库连接所做的更改将影响表示同一连接的其他QSqlDatabase实例。

使用cloneDatabase()在现有数据库连接的基础上创建一个独立的数据库连接警告:强烈建议不要将QSqlDatabase的副本作为类的成员保存,因为这将阻止在关闭时正确清理实例 如果需要访问现有的QSqlDatabase,应该使用database()来访问它。

如果你选择有一个QSqlDatabase成员变量,它需要在QCoreApplication实例被删除之前被删除,否则它可能会导致未定义的行为如果创建多个数据库连接,在调用addDatabase()时为每个连接指定唯一的连接名。

使用带有连接名的database()来获取该连接 使用removeDatabase()和连接名一起删除连接 如果您试图删除由其他QSqlDatabase对象引用的连接,QSqlDatabase将输出一个警告。

使用contains()查看给定的连接名是否在连接列表中一些实用方法:函数描述QStringList tables()返回数据库中所有的表列表QSqlRecord QSqlDatabase::record(const QString &

tablename)返回一条记录(改记录只包含字段,没有数据)bool QSqlDatabase::transaction()开启事务bool QSqlDatabase::commit()提交事务bool QSqlDatabase::rollback()

回滚事务bool QSqlDriver::hasFrature()检查驱动程序是否支持事务QSqlError QSqlDatabase::lastError()返回数据库上发生的最后一个错误的信息[static] QStringList QSqlDatabase::drivers()。

返回可用SQL驱动程序的名称[static] bool QSqlDatabase::isDriverAvailable(const QString &name)检查某个特定的驱动程序是否可用4.QSqlRecord

QSqlRecord类封装了数据库记录(通常是数据库中的表或视图中的一行)的功能和特征 QSqlRecord支持添加和删除字段,以及设置和检索字段值使用setValue()可以通过名称或位置设置记录字段的值; 如果你想设置一个字段值为空,使用setNull()。

要按名称查找字段的位置,请使用indexOf(),要在特定位置查找字段的名称,请使用fieldName() 使用field()检索给定字段的QSqlField对象 使用contains()查看记录是否包含特定的字段名。

当生成要在数据库上执行的查询时,生成的SQL中只包含isGenerated()为true的字段一条记录可以有通过append()或insert()添加的字段,通过replace()替换的字段,以及通过remove()删除的字段。

可以使用clear()删除所有字段 字段的数量由count()给出; 所有它们的值都可以使用clearValues()清除(为空)对SqlRecord记录字段操作不会影响到原来的表下面的代码片段展示了如何获取指定表的所有字段,只不过值是无效的。

QSqlRecord rec = db.record(“emp”); for (int i=0;i

value(i); }5.QSqlFieldQSqlField表示数据库表或视图中单个列的特征,例如数据类型和列名 字段还包含数据库列的值,可以查看或更改该值字段数据值存储为qvariant 不允许使用不兼容的类型。

例如:QSqlFieldfield(“age”, QVariant::Int); field.setValue(QPixmap()); // WRONG但是,在可能的情况下,字段会尝试将某些数据类型转换为字段数据类型:

QSqlFieldfield(“age”, QVariant::Int); field.setValue(QString(“123”)); // casts QString to int很少在应用程序代码中显式创建QSqlField对象。

它们通常通过已经包含字段列表的QSqlRecords间接访问 例如:QSqlQueryquery;…QSqlRecordrecord = query.record();QSqlFieldfield = record.field(“country”);

QSqlField对象可以提供一些关于字段的元数据,例如,它的name()、variant type()、length()、precision()、defaultValue()、typeID()以及它的requiredStatus()、isGenerated()和isReadOnly()。

可以检查字段的数据,看看它是否为null(),并检索它的值() 当编辑数据时,可以使用setValue()设置或使用clear()设置为NULL【领QT开发教程学习资料,点击下方链接免费领取↓↓,先码住不迷路~】

点击→领取「链接」6.QSqlQueryQSqlQuery封装了从在QSqlDatabase上执行的SQL查询中创建、导航和检索数据所涉及的功能 它可以用于执行DML(数据操作语言)语句,如SELECT、INSERT、UPDATE和DELETE,也可以用于执行DDL(数据定义语言)语句,如CREATE TABLE。

它也可以用于执行非标准SQL的特定数据库命令成功执行的SQL语句将查询的状态设置为活动,以便isActive()返回true 否则,查询的状态将设置为不活动 在这两种情况下,当执行新的SQL语句时,查询将定位在无效的记录上。

在检索值之前,活动查询必须导航到有效记录(以便isValid()返回true)导航记录有以下功能:boolnext()//检索结果中的下一条记录(如果可用),并在检索的记录上定位查询boolprevious。

()//检索结果中的前一条记录(如果可用),并将查询定位于检索的记录上 boolfirst()//检索结果中的第一条记录(如果可用),并在检索的记录上定位查询 boollast()//检索结果中的最后一条记录(如果可用),并在检索的记录上定位查询 。

boolseek()//在位置索引处检索记录(如果可用),并在检索的记录上定位查询 第一条记录位于位置0intat()const//返回查询的当前内部位置 如果位置无效,函数返回特殊的负值QSql::BeforeFirstRow或QSql::AfterLastRow。

这些函数允许程序员在查询返回的记录中向前、向后移动或任意移动 如果您只需要移动结果(例如,使用next()),您可以使用setForwardOnly(),这将节省大量的内存开销,并提高某些数据库的性能 一旦活动查询定位在有效记录上,就可以使用value()检索数据。

所有数据都使用qvariant从SQL后端传输例如:QSqlQuery query(“SELECT ename FROM emp”); while (query.next()) { QString ename = query.

value(0).toString(); QString ename = query.value(“ename”).toString(); qDebug()<< ename; }

要访问查询返回的数据,请使用value(int) 通过从0开始传递字段在语句中的位置来访问SELECT语句返回的数据中的每个字段 这使得使用SELECT *查询是不可取的,因为返回的字段的顺序是不确定的。

下面代码片段可以获取指定表的所有记录:QSqlQuery query(“SELECT * FROM emp”); auto record = query.record(); while (query.next()) {

for (int i = 0;i

std::cout<< ename.toStdString()<<“\t”; } std::cout<

const获取SQL语句影响的行数int QSqlQuery::numRowsAffected() constsize()用来获取SELECT语句查询到的记录条数如果大小无法确定或数据库不支持报告有关查询大小的信息,则返回-1。

注意,对于非select语句(isSelect()返回false), size()将返回-1 如果查询不是活动的(isActive()返回false),则返回-1numRowsAffected()返回受结果的SQL语句影响的行数,如果不能确定,则返回-1。

注意,对于SELECT语句,该值是未定义的; 使用size() 如果查询未激活,则返回-1Oracle数据库使用冒号-名称语法来标识占位符,例如:name ODBC简单使用 ? 字符 Qt支持这两种语法,但有一个限制,就是不能在同一个查询中混合使用它们。

可以使用boundValues()检索单个变量(映射)中所有字段的值QSqlQuery支持预先准备的查询执行和将参数值绑定到占位符 有些数据库不支持这些特性,所以对于这些特性,Qt会模拟所需的功能Oracle数据库使用冒号语法识别占位符,例如:name。

ODBC仅仅使用? 字符 Qt支持这两种语法,只是不能将它们混合在同一个查询中6.1绑定值QSqlQuery 支持将参数值绑定到占位符下面展示了使用几种不同绑定方法将值绑定到存储过程的示例使用命名占位符的

命名绑定:QSqlQueryquery; query.prepare(“INSERT INTO user (id, username, nickname)””VALUES (:id, :username, :nickname)”

); query.bindValue(“:id”,520); query.bindValue(“:username”,”maye”); query.bindValue(“:nickname”,”顽石”);

query.exec();使用命名占位符的位置绑定:QSqlQueryquery; query.prepare(“INSERT INTO user (id, username, nickname)””VALUES (:id, :username, :nickname)”

); query.bindValue(0,520); query.bindValue(1,”maye”); query.bindValue(2,”顽石”); query.exec();使用位置占位符绑定值(版本1):

QSqlQueryquery; query.prepare(“INSERT INTO user (id, username, nickname)”

“VALUES (?,?,?)”); query.bindValue(0,520);

query.bindValue(1,”maye”); query.bindValue(2,”顽石”);

query.exec();使用位置占位符绑定值(版本2):QSqlQueryquery; query.prepare(“INSERT INTO user (id, username, nickname)”

“VALUES (?,?,?)”); query.addBindValue(520);

query.addBindValue(“maye”); query.addBindValue(“顽石”);

query.exec();另外,未绑定的参数将导致操作失败【领QT开发教程学习资料,点击下方链接免费领取↓↓,先码住不迷路~】点击→领取「链接」6.2批处理操作方式一:addBindValue()  在query.prepare()中输入自己想要执行的语句,其中待输入的值用“?”代替,在这里“?”就是通配符。

后面再用idList、nameList、ageList和mathList添加自己想要设置的值注意,addBindValue()绑定值的顺序需要与id、name、age、math的顺序一致在批处理中执行先前准备的SQL查询。

所有绑定参数都必须是变量列表 QSqlQuery query; query.prepare(“insert into student (id,name,age,math) values (?,?,?,?)”

); //书写语句模型//添加绑定数据 QVariantList idList; idList << 15<<16<<17; //创建一个id列表 query.addBindValue(idList);

//完成第一个?的绑定 QVariantList nameList; nameList << “ddd”<<“eee”<<“jjj”;//创建一个name列表 query.addBindValue(nameList);

//完成第二个?的绑定 QVariantList ageList; ageList << 25<<24<<23; //创建一个age列表 query.addBindValue(ageList);

//完成第三个?的绑定 QVariantList mathList; mathList << 90<<89<<90; //创建一个math列表 query.addBindValue(mathList);

//完成第四个?的绑定 query.execBatch();//执行批处理方式二:bindValue()直接用自定义的名称来完成绑定,这时绑定顺序可以自己决定 QSqlQuery query; query.prepare(。

“insert into student (id,name,age,math) values (:id,:name,:age,:math)”); //:id之类的名字时自定义的 自己方便就好//添加绑定数据

QVariantList idList; idList << 18<<19<<20; query.bindValue(“:id”,idList); //完成:id的绑定

QVariantList nameList; nameList << “ddd”<<“eee”<<“jjj”; query.bindValue(“:name”,nameList);

//完成:name的绑定 QVariantList ageList; ageList << 25<<24<<23; query.bindValue(“:age”,ageList);

//完成:age的绑定 QVariantList mathList; mathList << 90<<89<<90; query.bindValue(“:math”,mathList);

//完成:math的绑定 query.execBatch();//执行批处理注意:每个绑定的QVariantList必须包含相同数量的变量注意:列表中qvariables的类型不能更改。

例如,您不能在QVariantList中混合整数和字符串变量SQL模型类Qt还提供了3个更高层的类来访问数据库,分别是QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。

这3个类都是从QAbstractTableModel派生来的,可以很容易地实现将数据库中的数据在QListView和QTableView等项视图类中进行显示使用这些类的另一个好处是,这样可以使编写的代码很容易的适应其他的数据源。

例如,如果开始使用了QSqlTableModel,而后来要改为使用XML文件来存储数据,这样需要做的仅是更换一个数据模型1.QSqlQueryModel模型QSqlQueryModel类为SQL结果集提供了

只读数据模型QSqlQueryModel是执行SQL语句和遍历结果集的高级接口 它构建在较低级别的QSqlQuery之上,可用于向视图类(如QTableView)提供数据QSqlQueryModel *sqlQueryModel = 。

new QSqlQueryModel(this); //sqlQueryModel->setQuery(query); sqlQueryModel->setQuery(“select * from user”

,database); QTableView * view = new QTableView; view->setModel(sqlQueryModel); view->show();我们设置了模型的查询,然后设置了显示在视图头中的标签。

QSqlQueryModel也可以用于通过编程方式访问数据库,而无需将其绑定到视图:QSqlQueryModel model; model.setQuery(“SELECT username,nickname

FROMuser”); QString nickname = model.record(4).value(“nickname”).toInt();上面的代码片段从SELECT查询结果集中的记录4中提取nickname字段。

由于nickname是第3列(索引为2),我们可以重写最后一行如下:QString nickname = model.data(model.index(4,2)).toInt();默认情况下,模型是只读的。

要使它可读可写,必须子类化它并重新实现setData()和flags() 另一种选择是使用QSqlTableModel,它提供了基于单个数据库表的读写模型如果数据库不返回查询中选择的行数,模型将以递增的方式获取行。

//清除模型并释放所有获得的资源 virtualvoidclear()//返回关于数据库上发生的最后一个错误的信息 QSqlError lastError()const//返回与此模型关联的QSqlQuery。

QSqlQuery query()const//返回包含有关当前查询字段信息的记录 如果row是有效行的索引,则记录将使用来自该行的值填充 QSqlRecord record(

int row)const QSqlRecord record()const//执行给定数据库连接db的查询查询 如果没有指定数据库(或无效的数据库),则使用默认连接 voidsetQuery(const。

QSqlQuery &query)voidsetQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())2.QSqlTableModel模型

QSqlTableModel类为单个数据库表提供了一个可编辑的数据模型QSqlTableModel是一个高级接口,用于从单个表中读写数据库记录可用于向视图类(如QTableView)提供数据 例如://构造时指定数据库,如果使用默认连接则不需要指定

QSqlTableModel* sqltableModel = new QSqlTableModel(this,database); //设置需要查询的表名 sqltableModel->setTable(

“freecustomers”); //设置在视图中编辑值时选择的策略 OnManualSubmit手动提交 sqltableModel->setEditStrategy(QSqlTableModel::EditStrategy::OnManualSubmit); 。

//使用指定的过滤器和排序条件,用setTable()设置的表中的数据填充模型,如果成功则返回true; 否则返回false sqltableModel->select(); //设置表头数据 sqltableModel->setHeaderData(。

0,Qt::Horizontal,”ID”); sqltableModel->setHeaderData(1,Qt::Horizontal,”QQ”); sqltableModel->setHeaderData(

2,Qt::Horizontal,”电话”); ​ QTableView * tableView = new QTableView; tableView->setModel(sqltableModel); tableView->hideColumn(

0); //隐藏ID tableView->show();QSqlTableModel不提供对外键的直接支持 如果要解析外键,请使用QSqlRelationalTableModel和QSqlRelationalDelegate。

其他函数//还原指定行的更改virtualvoidrevertRow(int row)////设置在视图中编辑值时选择的策略 virtualvoidsetEditStrategy(QSqlTableModel::EditStrategy strategy)。

//将当前筛选器设置为筛选器这个过滤器是一个没有关键字WHERE的SQL WHERE子句(例如,name=Josephine) virtualvoidsetFilter(const QString &filter)。

//设置一条记录到指定行,记录顺序可以随意,会自动映射 boolsetRecord(int row, const QSqlRecord &values)boolinsertRecord(int row,

const QSqlRecord &record)//将列的排序顺序设置为order 这不会影响当前数据,要使用新的排序顺序刷新数据,调用select()(在查询之前设置即可) virtualvoid

setSort(int column, Qt::SortOrder order)//将模型操作的数据库表设置为tableName 如果设置之后不调用select,那么将获取表的字段信息,要获取数据,必须调用select 。

virtualvoidsetTable(const QString &tableName)//获取表名 QString tableName()const//获取一条空记录,只有字段名 此函数可用于检索记录的字段名。

QSqlRecord record()const//获取指定行的记录,如果row是有效行的索引 如果模型没有初始化,将返回一个空记录 QSqlRecord record(int row)const

//返回当前表的主键,如果表没有设置或没有主键,则返回空QSqlIndex QSqlIndex primaryKey()const//如果模型包含未提交到数据库的修改值,则返回true,否则返回false。

boolisDirty(const QModelIndex &index)constboolisDirty()constslots//当用户取消编辑当前行时,项目委托将调用这个重新实现的槽 如果模型的策略设置为OnRowChange或OnFieldChange,则恢复更改。

对OnManualSubmit策略不做任何操作 使用revertAll()来恢复OnManualSubmit策略的所有挂起的更改,或使用revertRow()来恢复特定的行 virtualvoid

revert()override//恢复所有待提交的更改voidrevertAll()//使用指定的过滤器和排序条件,用setTable()设置的表中的数据填充模型,如果成功则返回true; 否则返回false。

virtualboolselect()//刷新某一行,按主键匹配,如果没有主键,那么每一个字段都必须对应(重新从数据库中查询一行) virtualboolselectRow(int row)

//使用submitAll()提交OnManualSubmit策略中所有挂起的更改 成功返回true; 否则返回false 使用lastError()查询详细的错误信息 不会自动重新填充模型 成功时将从数据库刷新提交的行。

virtualboolsubmit()override//提交所有挂起的更改并在成功时返回true 错误返回false,详细的错误信息可以通过lastError()获得 //注意:在OnManualSubmit模式下,当submitAll()失败时,已经提交的更改不会从缓存中清除。

这允许在不丢失数据的情况下回滚和重新提交事务 boolsubmitAll()signals//在删除某一行之前会发出这个信号voidbeforeDelete(int row)//在插入某一条记录之前会发出这个信号,可以在插入之前修改记录 (这里是使用insertRow() 或 setData() 插入非空数据时发出的)

voidbeforeInsert(QSqlRecord &record)//在更新某一行记录之前发出此信号 voidbeforeUpdate(int row, QSqlRecord &record)。

//准备插入一条记录是时,insertRows()将发出此信号 可以将记录参数写入(因为它是一个引用),例如用默认值填充某些字段,并设置字段的生成标志(这里是使用insertRows()插入多个空行时发出的,一次插入多条,那么每一条记录就会发出一次信号) 。

voidprimeInsert(int row, QSqlRecord &record)3.QSqlRelationalTableModel模型QSqlRelationalTableModel的作用类似于QSqlTableModel,但允许将列设置为其他数据库表的外键。

左边的截图显示了一个普通的QTableView中的QSqlTableModel 外键(城市和国家)不能解析为人类可读的值 右边的屏幕截图显示了一个QSqlRelationalTableModel,外键被解析为人类可读的文本字符串。

QSqlRelationalTableModel* relationalModel = new QSqlRelationalTableModel(this,database); relationalModel->setTable(

“freecustomers”); relationalModel->setRelation(1,QSqlRelation(“lectures”,”qq”,”nickname”)); relationalModel->select();

调用setRelation()函数建立两个表之间的关系 调用指定表freecustomers中的第1列是与表lectures的字段qq映射的外键,并且视图应该向用户显示城市的名称字段 (把freecustomers表中第一列(qq字段),换成lectures表中qq与nickname对应的字段)。

如果使用可读可写的QSqlRelationalTableModel,则可能需要在视图上使用QSqlRelationalDelegate 与默认委托不同,QSqlRelationalDelegate为作为其他表的外键的字段提供了一个组合框。

要使用该类,只需在视图中调用QAbstractItemView::setItemDelegate(),并使用QSqlRelationalDelegate的实例:QTableView * tableView =

new QTableView; tableView->setModel(relationalModel); tableView->setItemDelegate(new QSqlRelationalDelegate(this)); tableView->show();

其他函数//设置SQL joinMode以显示或隐藏具有NULL外键的行 在InnerJoin模式(默认)中,这些行不会显示:如果您想显示它们,请使用LeftJoin模式 voidsetJoinMode。

(QSqlRelationalTableModel::JoinMode joinMode)//让指定的列是relation指定的外部索引 virtualvoidsetRelation(int column,

const QSqlRelation &relation)程序打包注意事项:程序打包之后,需要把mysql数据库bin目录下面的libcrypto-1_1-x64.dll和libssl-1_1-x64.dll两个动态库拷贝到可执行程序的同级目录,以及lib目录下面的libmysql.dll也要拷贝进去

【领QT开发教程学习资料,点击下方链接免费领取↓↓,先码住不迷路~】点击→领取「链接」使用SQLiteSQLite(sql)是一款开源轻量级的数据库软件,不需要server,可以集成在其他软件中,非常适合嵌入式系统。

Qt5以上版本可以直接使用SQLite(Qt自带驱动)1.准备(1).引入SQL模块 在Qt项目文件(.pro文件)中,加入SQL模块:QT += sql(2).引用头文件 在需要使用SQL的类定义中,引用相关头文件。

例如:#include#include#include2.连接数据库连接SQLite不需要指定服务器名和端口号,但是可以设置用户名和密码。

如果指定的数据库名不存在,则会创建一个新的QSqlDatabase db = QSqlDatabase::addDatabase(“QSQLITE”); db.setUserName(“root”); db.setPassword(

“123456”); db.setDatabaseName(“student.db”); ​ if(!db.open()) { cout<<“student 数据库打开失败”;

return; }

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容