Qt:QSqlDatabase
0、说明
QSqlDatabase类处理与数据库连接相关的操作。一个QSqlDatabase实例就代表了一个连接,连接时要提供访问数据库的driver,driver继承自QSqlDriver。
通过静态方法addDatabase()构造一个QSqlDatabase来构造一个连接,调用这个方法时可以指定driver或driver type和连接名。
不同连接通过连接的name进行区分,而不是它要连接的数据库的name。我们可以通过多种连接连接到一个数据库。QSqlDatabase也支持默认连接——无名连接。为了构造这个默认连接,当我们调用addDatabase()时,不传入连接name。之后,当我们调用任何static成员函数时,如果不指定连接名,都会采用该默认连接。
下面的代码段展示了如何构造一个默认连接来连接一个PostgreSQL database:
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("Administrator"); db.setDatabaseName("Mydb"); db.setUserName("User"); db.setPassword("123456"); bool ok = db.open();
构造完成QSqlDatabase对象之后,要分别调用setHostName()、setDatabaseName()、setUserName()、setPassword()、setPort()、setConnectOptions()来设置连接配置项。之后,调用open()方法激活和数据库的连接。在open()之前,连接是不可用的。
上文我们构造了一个默认连接,因为我们在调用addDatabase()时并没有给这个连接命名。接下来,我们可以通过调用database()来得到这个默认连接对应的QSqlDatabase对象:
QSqlDatabase db = QSqlDatabase::database();
QSqlDatabase是一个值相关类,也就是说,在这个连接上进行的操作会影响到其它代表同一个连接的QSqlDatabase对象的内容。调用cloneDatabase()可以用已存在的连接构造一个独立的数据库连接。
注意
强烈推荐不要为QSqlDatabase构造副本,不然可能会在关闭时导致清理异常。如果我们需要访问一个存在的QSqlDatabase,应该通过database()来进行。如果我们获取并记录了一个QSqlDatabase类型的成员字段,那么它在QCoreApplication实例关闭前需要将其delete。
如果我们构造了多个连接,那么需要在调用addDatabase()时为每个连接指定一个独特的名字。通过调用database()时传入连接名来获取对应的连接。
调用removeDatabase()并传入相应的连接名来实现取消连接。如果我们想关闭一个正在被其他QSqlDatabase使用的连接,那么会输出一个警告信息。可以调用contains()可以检查某个连接名是否包含在连接List中。
QSqlDatabase::exec()已经过时了,现在应该用QSqlQuery::exec()。
使用事务时,必须在创建查询前启动事务。
1、模块和加载项
Header: | #include <QSqlDatabase> |
qmake: | QT += sql |
2、构造
QSqlDatabase(QSqlDatabase other) | 复制一个QSqlDatabase |
QSqlDatabase() |
构造一个空的、非法的QSqlDatabase。 需要使用addDatabase()、removeDatabase()、database()来获取合法的QSqlDatabase |
通常不用构造方法构造一个QSqlDatabase,而用静态方法addDatabase()。
5、静态方法
返回值类型 |
方法 |
说明 |
QSqlDatabase |
addDatabase(QString type, QString connectionName = QLatin1String(defaultConnection)) addDatabase(QSqlDriver *driver, QString connectionName = QLatin1String(defaultConnection)) |
用driver type和连接名构造一个连接,如果和之前的连接重名,那么会删除之前的连接,而返回新构造的连接。 如果type不可用,isValid()会返回false。 如果连接名未指定,那么新构建的连接将成为默认连接,可以通过调用无参database()来访问这个默认连接。如果提连接名,将会返回连接名对应的连接。 如果多次调用该方法且不指定连接名,那么后建立的默认连接会覆盖之前的默认连接。 在使用连接前,需要先初始化,也就是调用 setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), and setConnectOptions()这些方法或其中的一些方法。最后,open() |
该方法用一个driver来实例化数据库连接,这个driver可以是我们自写的。 这个方法我们用到的比较少,有需要的可以去官网查看addDatabase。 |
||
QSqlDatabase |
cloneDatabase(QSqlDatabase other, QString connectionName) cloneDatabase(QString other, QString connectionName) |
复制一个连接,返回它的副本,并为该副本命名。 所有原连接的内容如databaseName()、hostName()都会原封不动的保存下来。 这个新的连接并不是open的,在使用它之前,要先用open()打开。 |
QStringList | connectionNames() | 返回包含所有连接名的QStringList |
bool | contains(QString connectionName = QLatin1String(defaultConnection)) | 如果连接名List中包含指定连接名,返回true |
QSqlDatabase | database(QString connectionName = QLatin1String(defaultConnection), bool open = true) |
返回指定连接名的连接。 如果参数open = true(默认),那么如果返回的连接原本没有open,那么现在它会open。 如果不指定连接名,会返回默认连接;如果连接名不存在,会返回一个非法连接。 该方法是线程安全的。 |
QStringList | drivers() | 返回所有可用的drivers组成的QStringList |
bool | isDriverAvailable(QString name) | 如果名字为name的driver可用,就返回true |
void | registerSqlDriver(QString name, QSqlDriverCreatorBase *creator) |
注册一个新的名为name的driver。 如果我们有一个定制SQL driver并且并不想将它编译成一个接口时,可以调用该方法。 |
void | removeDatabase(QString connectionName) |
在连接List中删除某个连接。 需要注意的是,在该连接上不能有某个启动的Query,否则可能导致资源泄漏。 也就是说,Query语句必须与removeDatabase不在一个代码块中 错误示范: // WRONG QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); QSqlDatabase::removeDatabase("sales"); // will output a warning // "db" is now a dangling invalid database connection, // "query" contains an invalid result set 正确示范: { QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); } // 当db和query离开代码块之后,它们就会被销毁,此时再销毁是安全的 QSqlDatabase::removeDatabase("sales"); // correct 为了移除默认连接,可以通过database().connectionName()来获取默认连接name。 该方法是线程安全的。 |
QString的Drive type
Driver Type | Description |
---|---|
QDB2 | IBM DB2 |
QIBASE | Borland InterBase Driver |
QMYSQL | MySQL Driver |
QOCI | Oracle Call Interface Driver |
QODBC | ODBC Driver (includes Microsoft SQL Server) |
QPSQL | PostgreSQL Driver |
QSQLITE | SQLite version 3 or above |
QSQLITE2 | SQLite version 2 |
QTDS | Sybase Adaptive Server |
6、实例方法
返回值类型 |
方法 |
说明 |
QSqlDatabase & | operator=(QSqlDatabase other) | 赋值 |
void | close() | 关闭连接,释放所有资源,取消建立在该连接上的所有查询相关的QSqlQuery对象 |
bool | commit() |
如果driver支持事务,那么就向数据库提交事务,此时transaction()会启动。如果操作成功,返回true。 对于某些数据库,当在数据库上有活动查询正在执行,那么事务提交会失败并返回false。在事务提交之前应使查询失效。 调用lastError()可以得知错误信息。 |
QString | connectOptions() | 返回该连接所用到的一些连接配置 |
QString | connectionName() | 返回连接名 |
QString | databaseName() | 返回数据库名 |
QSqlDriver * | driver() | 返回该连接用的QSqlDriver |
QString | driverName() | 返回driver名 |
QSqlQuery | exec(QString query = QString()) | 执行一段SQL语句,返回QSqlQuery对象。 |
QString | hostName() | 返回连接的Host名 |
bool | isOpen() | 连接是否open |
isOpenError() |
是否存在打开错误。 错误信息通过lastError()查询 |
|
isValid() |
如果该QSqlDatabase有一个合法driver返回true。 QSqlDatabase db; qDebug() << db.isValid(); // Returns false db = QSqlDatabase::database("sales"); qDebug() << db.isValid(); // 如果连接"sales"存在,返回true QSqlDatabase::removeDatabase("sales"); qDebug() << db.isValid(); // Returns false |
|
QSqlError | lastError() |
返回最近的错误信息。 查询相关的错误会被QSqlQuery::lastError()抛出 |
QSql::NumericalPrecisionPolicy | numericalPrecisionPolicy() | 返回当前数据库连接的默认精度策略。 |
bool |
open() open(QString user, QString password) |
启动一个数据库连接 |
QString | password() | 返回连接密码 |
int | port() | 返回连接端口 |
QSqlIndex | primaryIndex(QString tablename) | 返回表tablename上的索引。 |
QSqlRecord | record(QString tablename) | 返回表tablename(或视图)上所有字段组成的QSqlRecord |
bool | rollback() | 如果事务transaction()已经启动,回滚数据库上的事务。 |
void 这些方法必须在连接open()前调用,否则是无效的。 不然就只能先close(),再调用该方法,再open()。 |
setConnectOptions(QString options = QString()) |
设置连接配置项。
参数options字符串是以分号';'分隔的option=value对。不同的数据库的配置是不同的,具体可查看官方文档setConnectOptions |
setDatabaseName(QString name) |
设置数据库名。 如果数据库服务器上有多个数据库,就要用该项指明用哪个数据库。 |
|
setHostName(QString host) | 设置Host名(服务器IP/域名)。 | |
setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy) | 设置数字精度策略。 | |
setPassword(QString password) | 设置密码。 | |
setPort(int port) | 设置端口。 | |
setUserName(QString name) | 设置用户名。 | |
QStringList | tables(QSql::TableType type = QSql::Tables) | 返回数据库中所有的table、system table、view构成的QStringList,具体返回哪种,由参数type指定。 |
bool | transaction() | 启动一项事务,成功则返回true |
QString | userName() | 返回用户名 |
事务
在以上方法中,我们提到了事务(transaction)一词,它的意思是我们对数据库进行的各项操作,需要注意的是,对数据库修改的事务,必须commit()提交事务,才能真正实现对数据库修改,否则只是对它的映像进行修改。
7、用法
1)构造数据库连接
int main(int argc, char *argv[]) { QSqlDatabase db =QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("Mysql"); db.setPort(1234); db.setUserName("User"); db.setPassword("pwd1"); db.setDatabaseName("Table1"); if( !db.open() ){ //数据库打开失败 qDebug()<<db.lastError().text(); } }