SQL 数据库驱动程序
Qt SQL 模块使用驱动插件与不同的数据库 API 通信。由于 Qt 的 SQL 模块 API 与数据库无关,所有与数据库相关的代码都包含在这些驱动程序中。Qt 提供了多个驱动程序,还可以添加其他驱动程序。我们还提供了驱动程序源代码,可作为编写自己的驱动程序的范本。
支持的数据库
下表列出了 Qt 附带的驱动程序:
驱动程序名称 | 数据库管理系统 |
---|---|
QDB2 | IBM DB2(7.1 及以上版本) |
QIBASE | Borland InterBase / Firebird |
QMYSQL / MARIADB | MySQL 或 MariaDB(5.6 及以上版本) |
QOCI | Oracle 调用接口驱动程序(12.1 及以上版本) |
QODBC | 开放数据库连接(ODBC)--Microsoft SQL Server 和其他兼容 ODBC 的数据库 |
QPSQL | PostgreSQL (7.3 及以上版本) |
QSQLITE | SQLite 第 3 版 |
QMIMER | Mimer SQL(11 及以上版本) |
SQLite 是进程内数据库系统,在所有平台上都有最好的测试覆盖面和支持。通过 OCI 对 Oracle、PostgreSQL 和 MySQL(通过 ODBC 或本地驱动程序)在 Windows 和 Linux 上进行了很好的测试。对其他系统支持的完整性取决于客户端库的可用性和质量。
注: 要构建驱动程序插件,需要为数据库管理系统(DBMS)准备相应的客户端库。该库可访问 DBMS 公开的 API,通常随 DBMS 一起提供。大多数安装程序还允许你安装 "开发库",而这些正是你所需要的。这些库负责与 DBMS 进行底层通信。还要确保为 Qt 架构(32 或 64 位)安装正确的数据库库。
注意: 在开源条件下使用 Qt 但使用专有数据库时,请验证客户端库的许可证是否与 LGPL 兼容。
构建驱动程序
使用特定驱动程序编译 Qt
Qtconfigure
脚本会尝试自动检测机器上可用的客户端库。运行configure -help
查看可以构建哪些驱动程序。您应该会得到类似下面的输出结果:
[...] Database options: -sql-<driver> ........ Enable SQL <driver> plugin. Supported drivers: db2 ibase mysql oci odbc psql sqlite [all auto] -sqlite .............. Select used sqlite [system/qt] [...]
如果必要的库和包含文件不在标准路径中,则configure
脚本无法检测到它们,因此可能需要使用特定于驱动程序的包含和库路径变量或CMAKE_INCLUDE_PATH
和CMAKE_LIBRARY_PATH
来指定这些路径。例如,如果您的 MySQL 文件安装在 Windows 上的C:\mysql-connector-c-6.1.11-winx64
中,则在配置行的双斜线部分传递以下参数:
C:\Qt\6.0.0\Src\configure.bat -sql-mysql -- -DMySQL_ROOT="C:\mysql-8.0.22-winx64" Configure summary: ... Qt Sql Drivers: DB2 (IBM) .............................. no InterBase .............................. no Mimer SQL .............................. yes MySql .................................. yes OCI (Oracle) ........................... no ODBC ................................... yes PostgreSQL ............................. no SQLite ................................. yes Using system provided SQLite ......... no ...
当你以上述方式配置驱动程序时,CMake 会跳过任何依赖关系检查,直接使用所提供的路径。如果软件包提供了自己的系统库,而这些库不应被编译例程识别,那么这一点尤其有用。
下文将解释每个驱动程序的具体细节。
注意: 如果出了问题,而你又希望 CMake 重新检查可用的驱动程序,你可能需要从联编目录中删除CMakeCache.txt。
只编译特定的 SQL 驱动程序
当 Qt SQL 已编译或安装为二进制版本时,可以只编译特定的 SQL 驱动程序。但你必须确保安装了完全相同版本的 Qt 源(例如通过Qt Maintenance Tool ),否则你可能会因更改 apis 而导致编译错误。此外,还要确保在 Windows 开始菜单中执行相应的 Qt 命令提示符,以正确设置编译环境。
典型的qt-cmake
运行(在本例中是为 MySQL 配置)如下:
C:\Qt\6.0.0\mingw81_64\bin\qt-cmake -G Ninja C:\Qt\6.0.0\Src\qtbase\src\plugins\sqldrivers -DMySQL_INCLUDE_DIR="C:\mysql-8.0.22-winx64\include" -DMySQL_LIBRARY="C:\mysql-8.0.22-winx64\lib\libmysql.lib" -DCMAKE_INSTALL_PREFIX="C:\Qt\6.0.0\mingw81_64" Configure summary: Qt Sql Drivers: DB2 (IBM) .............................. no InterBase .............................. no Mimer SQL .............................. yes MySql .................................. yes OCI (Oracle) ........................... no ODBC ................................... yes PostgreSQL ............................. no SQLite ................................. yes Using system provided SQLite ......... no -- Configuring done -- Generating done -- Build files have been written to: C:/build-qt6-sqldrivers
注意: 如《使用特定驱动程序编译 Qt》一文所述,如果找不到驱动程序或驱动程序未启用,请删除CMakeCache.txt 重新开始。
出于处理外部依赖关系的实际考虑,只有 SQLite 插件随 Qt 的二进制版本一起提供。Windows 版 Qt 的二进制版本还包括 ODBC 和 PostgreSQL 插件。为了能在 Qt 安装中添加其他驱动程序,而无需重新构建所有 Qt,可以在完整 Qt 构建目录之外配置并构建qtbase/src/plugins/sqldrivers
目录。请注意,无法单独配置每个驱动程序,只能一次配置所有驱动程序。不过,驱动程序可以单独构建。
注意: 如果想在编译完成后安装插件,则需要指定CMAKE_INSTALL_PREFIX
。
驱动程序说明
适用于 MySQL 或 MariaDB 5.6 及更高版本的 QMYSQL
MariaDB是MySQL的一个分叉,旨在保持GNU通用公共许可证下的自由和开源软件。MariaDB旨在保持与MySQL的高度兼容性,确保可直接替换,并与MySQL API和命令完全匹配。因此,MySQL 和 MariaDB 的插件合并为一个 Qt 插件。
时间戳支持
自 Qt 6.8 起,QDateTime 值在插入前转换为 UTC,并在检索时从 UTC 返回。为了实现这一点,驱动程序会在 open() 时将连接时区设置为 UTC(SET time_zone = '+00:00')。由于 MySQL 不存储任何时区信息,因此该信息会丢失,所有检索到的QDateTime 值都是 UTC。
QMYSQL 存储过程支持
MySQL 在 SQL 层支持存储过程,但没有控制 IN、OUT 和 INOUT 参数的 API。因此,必须使用 SQL 命令而不是QSqlQuery::bindValue() 来设置和读取参数。
存储过程示例:
create procedure qtestproc (OUT param1 INT, OUT param2 INT) BEGIN set param1 = 42; set param2 = 43; END
访问 OUT 值的源代码:
QSqlQueryq; q.exec("call qtestproc (@outval1, @outval2)"); q.exec("select @outval1, @outval2");if(q.next()) qDebug() << q.value(0) << q.value(1); // outputs "42" and "43"
注意: @outval1
和@outval2
是当前连接的本地变量,不会受到从其他主机或连接发送的查询的影响。
嵌入式 MySQL 服务器
MySQL 嵌入式服务器可直接替代普通客户端库。有了嵌入式 MySQL 服务器,使用 MySQL 功能就不需要 MySQL 服务器了。
要使用嵌入式 MySQL 服务器,只需将 Qt XML 插件链接到libmysqld
,而不是libmysqlclient
。这可以通过在 configure 命令行中添加-DMySQL_LIBRARY=<path/to/mysqld/>libmysqld.<so|lib|dylib>
来实现。
有关 MySQL 嵌入式服务器的更多信息,请参阅 MySQL 文档 "libmysqld,嵌入式 MySQL 服务器库 "一章。
连接选项
Qt MySQL/MariaDB 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
客户端压缩 | 如果设置,则在成功验证后切换到压缩协议 |
客户端找到的行 | 如果设置,则发送找到的行,而不是受影响的行 |
忽略空格 | 如果设置,则忽略'('前的空格 |
客户机模式 | 如果设置,则不允许使用数据库表列 |
客户端交互 | 如果设置,则将客户端视为交互式 |
mysql_opt_protocol | 明确指定要使用的协议: MYSQL_PROTOCOL_TCP:使用 tcp 连接(通过 setHostname() 指定 IP/主机名) MYSQL_PROTOCOL_SOCKET:通过在 UNIX_SOCKET 中指定的套接字连接 MYSQL_PROTOCOL_PIPE:通过在 UNIX_SOCKET 中指定的命名管道连接 MYSQL_PROTOCOL_MEMORY:通过在 MYSQL_SHARED_MEMORY_BASE_NAME 中指定的共享内存连接 |
UNIX_SOCKET | 指定要使用的套接字或命名管道,即使称为 UNIX_SOCKET,也可以在 Windows 中使用 |
mysql_shared_memory_base_name | 指定要使用的共享内存段名称 |
mysql_opt_reconnect | TRUE 或 1:连接丢失后自动重新连接 FALSE 或 0:连接丢失后不自动重新连接(默认) 参见自动重新连接控制 |
mysql_opt_connect_timeout | 连接超时(以秒为单位 |
读取超时 | 每次尝试从服务器读取数据的超时,以秒为单位 |
写超时 | 每次尝试向服务器写入的超时(秒 |
mysql_opt_local_infile | 设为 1 可启用对本地LOAD_DATA 的支持,未设为 0 则禁用 |
mysql_opt_ssl_mode | 用于连接服务器的安全状态:ssl_mode_disabled、ssl_mode_preferred、ssl_mode_required、ssl_mode_verify_ca、ssl_mode_verify_identity。 |
mysql_opt_tls_version | 客户端允许加密连接的协议列表。根据所使用的MySQL 服务器版本,该值可以是 "TLSv1"、"TLSv1.1"、"TLSv1.2 "或 "TLSv1.3 "的组合。 |
MYSQL_OPT_SSL_KEY / SSL_KEY(已废弃) | 客户端私钥文件的路径名 |
MYSQL_OPT_SSL_CERT / SSL_CERT(已废弃) | 客户端公钥证书文件的路径名 |
MYSQL_OPT_SSL_CA / SSL_CA(已废弃) | 证书颁发机构(CA)证书文件的路径名 |
MYSQL_OPT_SSL_CAPATH / SSL_CAPATH(已废弃) | 包含可信 SSL CA 证书文件的目录路径名 |
MYSQL_OPT_SSL_CIPHER / SSL_CIPHER(已废弃) | 允许用于 SSL 加密的密码列表 |
mysql_opt_ssl_crl | 包含证书吊销列表的文件路径名 |
mysql_opt_ssl_crlpath | 包含证书吊销列表文件的目录路径名 |
有关连接选项的更多详细信息,请参阅 MySQL 文档mysql_options()。
如何在 Unix 和 macOS 上构建 QMYSQL 插件
您需要 MySQL / MariaDB 头文件,以及共享库libmysqlclient.<so|dylib>
/libmariadb.<so|dylib>
。根据你的 Linux 发行版,你可能需要安装一个包,通常称为 "mysql-devel "或 "mariadb-devel"。
告诉qt-cmake
在哪里找到 MySQL / MariaDB 头文件和共享库(此处假定 MySQL / MariaDB 安装在/usr/local
中),然后构建:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DMySQL_ROOT="/usr/local/mysql" cmake --build . cmake --install .
如何在 Windows 上构建 QMYSQL 插件
你需要获取MySQL安装文件(如MySQL网络安装程序或MariaDB C连接器)。运行安装程序,选择自定义安装并安装与 Qt 安装(x86 或 x64)相匹配的 MySQL C Connector。安装完成后,检查所需文件是否存在:
<MySQL dir>/lib/libmysql.lib
<MySQL dir>/lib/libmysql.dll
<MySQL dir>/include/mysql.h
和 MariaDB
<MariaDB dir>/lib/libmariadb.lib
<MariaDB dir>/lib/libmariadb.dll
<MariaDB dir>/include/mysql.h
注: 自 MySQL 8.0.19 起,C 连接器不再作为独立的可安装组件提供。相反,您可以通过安装完整的 MySQL 服务器(仅限 x64)或MariaDB C 连接器获得mysql.h
和libmysql.*
。
按如下步骤构建插件(此处假定<MySQL dir>
为C:\mysql-8.0.22-winx64
):
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DMySQL_ROOT="C:\mysql-8.0.22-winx64" cmake --build . cmake --install .
发布应用程序时,请记住在安装包中包含libmysql.dll/libmariadb.dll。libmysql.dll还需要 MSVC 运行库,可通过vcredist.exe安装。
用于 Oracle 调用接口 (OCI) 的 QOCI
Qt OCI 插件支持连接 Oracle 数据库,这取决于所使用的即时客户端版本。这取决于甲骨文表示支持的版本。插件将自动检测数据库版本并启用相应功能。
可以在没有 tnsnames.ora 文件的情况下连接 Oracle 数据库。这需要将数据库 SID 作为数据库名称传递给驱动程序,并提供主机名。
OCI 用户身份验证
Qt OCI 插件支持使用外部凭证(OCI_CRED_EXT)进行身份验证。通常,这意味着数据库服务器将使用操作系统提供的用户身份验证,而不是自己的身份验证机制。
在使用QSqlDatabase 打开连接时,请将用户名和密码留空,以便使用外部凭证身份验证。
支持 OCI BLOB/LOB
可以读写二进制大对象(BLOB),但要注意读写过程可能需要大量内存。应使用只向前查询来选择 LOB 字段(请参阅QSqlQuery::setForwardOnly() )。
插入 BLOB 应使用准备好的查询(BLOB 绑定到占位符)或QSqlTableModel ,后者在内部使用准备好的查询来完成。
连接选项
Qt OCI 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
OCI_ATTR_PREFETCH_ROWS | 将 OCI 属性OCI_ATTR_PREFETCH_ROWS设置为指定值 |
oci_attr_prefetch_memory | 将 OCI 属性OCI_ATTR_PREFETCH_MEMORY设置为指定值 |
OCI_AUTH_MODE | OCI_SYSDBA:为SYSDBA访问进行身份验证 OCI_SYSOPER:为SYSOPER访问进行身份验证 OCI_DEFAULT:为正常访问进行身份验证 有关访问模式的更多信息,请参阅OCISessionBegin。 |
如何在 Unix 和 macOS 上构建 OCI 插件
您只需要"- Basic "和 "Instant Client Package - SDK"。
构建驱动程序所需的 Oracle 库文件:
libclntsh.<so|dylib>
(所有版本)
告诉qt-cmake
在哪里找到 Oracle 头文件和共享库并进行编译。
我们假设您安装了 Instant Client Package SDK 的 RPM 包(需要相应调整版本号):
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DOracle_ROOT="/usr/include/oracle/21/client64" cmake --build . cmake --install .
注意: 如果使用的是 Oracle Instant Client 软件包,则在构建 OCI SQL 插件和运行使用 OCI SQL 插件的应用程序时,需要设置 LD_LIBRARY_PATH。
如何在 Windows 上构建 OCI 插件
在 Oracle Client 安装光盘的 Oracle Client 安装程序中选择 "程序员 "选项通常就足以构建插件。对于某些版本的 Oracle 客户端,如果有 "调用接口 (OCI) "选项,您可能还需要选择该选项。
按如下步骤构建插件(此处假定 Oracle Client 安装在C:\oracle
,SDK 安装在C:\oracle\sdk
):
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DOracle_ROOT="C:\oracle" cmake --build . cmake --install .
运行应用程序时,还需要将oci.dll
路径添加到PATH
环境变量中:
set PATH=%PATH%;C:\oracle
用于开放式数据库连接(ODBC)的 QODBC
ODBC 是一个通用接口,允许你使用一个通用接口连接到多个 DBMS。QODBC 驱动程序允许你连接到 ODBC 驱动程序管理器,并访问可用的数据源。请注意,你还需要为系统上安装的 ODBC 驱动程序管理器安装和配置 ODBC 驱动程序。QODBC 插件可让您在 Qt 应用程序中使用这些数据源。
注意: 如果有本地驱动程序,应使用本地驱动程序,而不是 ODBC 驱动程序。如果没有本地驱动程序,ODBC 支持可用作兼容数据库的后备。
在 Windows 系统中,默认安装了 ODBC 驱动程序管理器。对于 Unix 系统,必须先安装某些实现。请注意,应用程序的每个最终用户都必须安装 ODBC 驱动程序管理器,否则 QODBC 插件将无法运行。
连接到 ODBC 数据源时,应向QSqlDatabase::setDatabaseName() 函数传递 ODBC 数据源 (DSN) 的名称,而不是实际的数据库名称。也可以传递 FILEDSN (*.dsn) 文件名或完整的 ODBC 驱动程序字符串。在传递驱动程序字符串时,必须确保所有参数(用户名、密码......)都已正确转义。通过QSqlDatabase 函数传递用户名或密码时,转义将由 QODBC 插件完成。
QODBC 插件需要兼容 ODBC 的驱动管理器 2.0 或更高版本。有些 ODBC 驱动程序声称符合版本 2.0,但并不提供所有必要的功能。因此,QODBC 插件会在建立连接后检查是否可以使用数据源,如果检查失败,就会拒绝工作。如果不喜欢这种行为,可以删除qsql_odbc.cpp
文件中的#define ODBC_CHECK_DRIVER
行。风险自负!
默认情况下,Qt 会指示 ODBC 驱动程序以 ODBC 2.x 驱动程序的方式运行。然而,对于某些驱动程序管理器/ODBC 3.x 驱动程序组合(如unixODBC/MaxDB ODBC),指示 ODBC 驱动程序以 2.x 驱动程序的方式运行可能会导致驱动程序插件出现意外行为。为避免这一问题,请在open your database connection 之前通过setting the connect option "SQL_ATTR_ODBC_VERSION=SQL_OV_ODBC3"
指示 ODBC 驱动程序以 3.x 驱动程序的方式运行。请注意,这将影响 ODBC 驱动程序行为的多个方面,如 SQLSTATE。在设置此连接选项之前,请查阅 ODBC 文档,了解可能出现的行为差异。
如果访问 ODBC 数据源的速度非常慢,请确保在 ODBC 数据源管理器中关闭了 ODBC 调用跟踪。
某些驱动程序不支持可滚动游标。在这种情况下,只能成功使用QSqlQuery::setForwardOnly() 模式的查询。
时间戳支持
ODBC 使用的 TIMESTAMP_STRUCT 没有任何时区或类似信息。因此,在使用QDateTime 时完全不考虑时区。
注意: :将来可能会发生变化。
ODBC 存储过程支持
在 Microsoft SQL Server 中,只有在使用QSqlQuery::setForwardOnly() 将查询的转发模式设置为转发时,才能访问使用返回语句或返回多个结果集的存储过程返回的结果集。
// STORED_PROC uses the return statement or returns multiple result sets QSqlQuery query; query.setForwardOnly(true); query.exec("{call STORED_PROC}");
注意: 存储过程的返回语句返回的值将被丢弃。
ODBC Unicode 支持
如果定义了 UNICODE,QODBC 插件将使用 Unicode API。在基于 Windows 的系统中,这是默认设置。请注意,ODBC 驱动程序和 DBMS 也必须支持 Unicode。
对于 Oracle 9 ODBC 驱动程序(Windows),必须在 ODBC 驱动程序管理器中选中 "SQL_WCHAR 支持",否则 Oracle 将把所有 Unicode 字符串转换为本地 8 位表示。
连接选项
Qt ODBC 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
sql_attr_access_mode | SQL_MODE_READ_ONLY:以只读模式打开数据库 SQL_MODE_READ_WRITE:以读写模式打开数据库(默认值 |
sql_attr_login_timeout | 登录时等待数据库连接的秒数(值为 0 时将永远等待) |
sql_attr_connection_timeout | 请求数据库时等待的秒数(值为 0 将永远等待) |
sql_attr_current_catalog | 此连接要使用的目录(数据库 |
sql_attr_metadata_id | SQL_TRUE:目录函数的字符串参数被视为标识符 SQL_FALSE:目录函数的字符串参数不被视为标识符 |
sql_attr_packet_size | 以字节为单位指定网络数据包大小 |
sql_attr_tracefile | 包含跟踪文件名的字符串 |
SQL_ATTR_TRACE | SQL_OPT_TRACE_ON:启用数据库查询跟踪 SQL_OPT_TRACE_OFF:禁用数据库查询跟踪(默认值 |
sql_attr_connection_pooling | SQL_CP_DEFAULT、SQL_CP_OFF:关闭连接池(默认) SQL_CP_ONE_PER_DRIVER:每个驱动程序支持一个连接池 SQL_CP_ONE_PER_HENV:每个环境支持一个连接池 |
sql_attr_odbc_version | SQL_OV_ODBC3: 驱动程序应作为 ODBC 3.x 驱动程序运行 SQL_OV_ODBC2: 驱动程序应作为 ODBC 2.x 驱动程序运行(默认值 |
有关连接选项的更多详细信息,请参阅SQLSetConnectAttr()ODBC 文档。
如何在 Unix 和 macOS 上构建 ODBC 插件
建议使用 unixODBC。您可以在http://www.unixodbc.org 上找到最新版本和 ODBC 驱动程序。您需要 unixODBC 头文件和共享库。
告诉qt-cmake
在哪里可以找到 unixODBC 头文件和共享库(此处假定 unixODBC 已安装在/usr/local/unixODBC
中)并进行编译:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DODBC_INCLUDE_DIR="/usr/local/unixODBC/include" -DODBC_LIBRARY="/usr/local/unixODBC/lib/libodbc.<so|dylib>" cmake --build . cmake --install .
如何在 Windows 上构建 ODBC 插件
ODBC 头文件和包含文件应该已经安装在正确的目录中。你只需按如下步骤构建插件:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> cmake --build . cmake --install .
用于 PostgreSQL 的 QPSQL(7.3 及以上版本)
QPSQL 驱动程序支持 7.3 及以上版本的 PostgreSQL 服务器。
有关 PostgreSQL 的更多信息,请访问http://www.postgresql.org。
时间戳支持
自 Qt 6.8 起,QDateTime 值在插入前转换为 UTC,并在检索时从 UTC 返回。为了做到这一点,驱动程序会在 open() 时将连接时区设置为 UTC(SET TIME ZONE 'UTC')。虽然 PostgreSQL 有 "timestamptz "列类型,但插入时使用的时区不会被保留,因此所有检索到的QDateTime 值都是 UTC。
QPSQL Unicode 支持
QPSQL 驱动程序会自动检测所连接的 PostgreSQL 数据库是否支持 Unicode。如果服务器支持,就会自动使用 Unicode。请注意,驱动程序只支持UTF-8编码。如果你的数据库使用其他编码,服务器在编译时必须支持 Unicode 转换。
PostgreSQL 7.1 版引入了 Unicode 支持,只有在编译服务器和客户端库时都支持多字节的情况下才能使用。关于如何设置启用多字节的 PostgreSQL 服务器的更多信息,请参阅《PostgreSQL 管理员指南》第 5 章。
QPSQL 大小写敏感性
PostgreSQL 数据库只有在创建表格或字段名时加注了引号,才会尊重大小写敏感性。因此,举例来说,SQL 查询如
CREATE TABLE "testTable" ("id" INTEGER);
这样的 SQL 查询将确保能以与所用大小写相同的方式访问。如果创建表格或字段名时没有加引号,则实际的表名或字段名将是小写。当QSqlDatabase::record() 或QSqlDatabase::primaryIndex() 访问创建时未加引号的表或字段时,为确保找到该表或字段,传递给函数的名称必须为小写。例如
QString tableString("testTable"); QSqlQuery q; // Create table query is not quoted, therefore it is mapped to lower case q.exec(QString("CREATE TABLE %1 (id INTEGER)").arg(tableString)); // Call toLower() on the string so that it can be matched QSqlRecord rec = database.record(tableString.toLower());
QPSQL 仅向前查询支持
要使用只向前查询,必须使用 PostreSQL 客户端库 9.2 或更高版本构建 QPSQL 插件。如果使用旧版本构建插件,则只向前模式将不可用--使用true
调用QSqlQuery::setForwardOnly() 不会有任何效果。
警告: 如果使用 9.2 或更高版本的 PostgreSQL 构建 QPSQL 插件,则必须使用 9.2 或更高版本的 libpq 发布应用程序。否则,加载 QPSQL 插件将失败,并显示以下信息:
QSqlDatabase: QPSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMARIADB QODBC QPSQL Could not create database object
在只向前模式下浏览结果时,QSqlResult 的句柄可能会改变。使用 SQL 结果底层句柄的应用程序必须在每次调用QSqlResult 抓取函数后获取新句柄。示例
QSqlQuery query; QVariant v; query.setForwardOnly(true); query.exec("SELECT * FROM table"); while (query.next()) { // Handle changes in every iteration of the loop v = query.result()->handle(); if (qstrcmp(v.typeName(), "PGresult*") == 0) { PGresult *handle = *static_cast<PGresult **>(v.data()); if (handle) { // Do something... } } }
在使用 PostgreSQL 读取只向前查询的结果时,数据库连接不能用于执行其他查询。这是 libpq 库的限制。示例
int value; QSqlQuery query1; query1.setForwardOnly(true); query1.exec("select * FROM table1"); while (query1.next()) { value = query1.value(0).toInt(); if (value == 1) { QSqlQuery query2; query2.exec("update table2 set col=2"); // WRONG: This will discard all results of } // query1, and cause the loop to quit }
如果查询 1 和查询 2 使用不同的数据库连接,或者在 while 循环之后执行查询 2,就不会出现这个问题。
注意: QSqlDatabase 的某些方法(如 tables()、primaryIndex())会隐式执行 SQL 查询,因此在浏览只向前查询的结果时也不能使用这些方法。
注意: 如果 QPSQL 发现查询结果丢失,它将打印以下警告:
QPSQLDriver::getResult: Query results lost - probably discarded on executing another SQL query.
连接选项
Qt PostgreSQL 插件尊重所有在connect()PostgreSQL 文档中指定的连接选项。
如何在 Unix 和 macOS 上构建 QPSQL 插件
你需要安装 PostgreSQL 客户端库和头文件。
要让qt-cmake
找到 PostgreSQL 头文件和共享库,请按以下方式构建插件(假设 PostgreSQL 客户端已安装在/usr/local/pgsql
中):
mkdir build-psql-driver cd build-psql-driver qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers-DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DPostgreSQL_ROOT="/usr/local/pgsql" cmake --build . cmake --install .
如何在 Windows 上构建 QPSQL 插件
为你的编译器安装适当的 PostgreSQL 开发库。假设 PostgreSQL 已安装在C:\pgsql
中,则按如下步骤构建插件:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DPostgreSQL_ROOT="C:\pgsql" cmake --build . cmake --install .
MinGW 用户可参考以下在线文档:PostgreSQL MinGW/Native Windows。
分发应用程序时,请记住在安装包中包含 libpq.dll。它必须与应用程序可执行文件放在同一文件夹中。
用于 IBM DB2 的 QDB2(7.1 及以上版本)
Qt DB2 插件使访问 IBM DB2 数据库成为可能。它已通过 IBM DB2 v7.1 和 7.2 测试。您必须安装 IBM DB2 开发客户端库,该库包含编译 QDB2 插件所需的头文件和库文件。
QDB2 驱动程序支持准备查询、读/写 Unicode 字符串和读/写 BLOB。
我们建议在调用 DB2 中的存储过程时使用只向前查询(请参阅QSqlQuery::setForwardOnly() )。
连接选项
Qt IBM DB2 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
sql_attr_access_mode | SQL_MODE_READ_ONLY:以只读模式打开数据库 SQL_MODE_READ_WRITE:以读写模式打开数据库(默认值 |
sql_attr_login_timeout | 登录时等待数据库连接的秒数(最大值:32767,值为 0 时将永远等待) |
如何在 Unix 和 macOS 上构建 QDB2 插件
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DDB2_INCLUDE_DIR="/usr/local/db2/include" -DDB2_LIBRARY="/usr/local/db2/lib/libdb2.<so|dylib>" cmake --build . cmake --install .
如何在 Windows 上构建 QDB2 插件
DB2 头文件和包含文件应已安装在正确的目录中。您只需按以下步骤构建插件:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DDB2_INCLUDE_DIR="C:\db2\include" -DDB2_LIBRARY="C:\db2\lib\db2.lib" cmake --build . cmake --install .
用于 SQLite 的 QSQLITE(版本 3 及以上)
Qt SQLite 插件使访问 SQLite 数据库成为可能。SQLite 是一个进程内数据库,这意味着无需数据库服务器。SQLite 在单个文件上运行,打开连接时必须将该文件设为数据库名称。如果文件不存在,SQLite 将尝试创建它。SQLite 还支持内存数据库和临时数据库。只需分别传递":memory: "或空字符串作为数据库名称即可。
SQLite 对多用户和多事务有一些限制。如果您尝试从不同的事务中对资源进行读/写,您的应用程序可能会冻结,直到其中一个事务提交或回滚。Qt XML SQLite 驱动程序会重试写入锁定的资源,直到超时为止(请参阅QSQLITE_BUSY_TIMEOUT
atQSqlDatabase::setConnectOptions() )。
在 SQLite 中,除 INTEGER PRIMARY KEY 列外,任何列都可用于存储任何类型的值。例如,声明为 INTEGER 的列可能在一行中包含一个整数值,而在下一行中包含一个文本值。这是由于 SQLite 将值的类型与值本身相关联,而不是与所存储的列相关联。因此,QSqlField::type() 返回的类型仅表示字段的推荐类型。不应据此假定实际类型,而应检查各个值的类型。
在执行选择时,驱动程序被锁定以进行更新。这可能会在使用QSqlTableModel 时造成问题,因为 Qt 的项目视图会根据需要获取数据(在QSqlTableModel 的情况下使用 QSqlQuery::fetchMore())。
有关 SQLite 的信息,请访问http://www.sqlite.org。
时间戳支持
SQLite 没有特殊的时间戳列类型。QDateTime 以字符串形式存储,格式为Qt::ISODateWithMs ,因此在插入和选择时会保留QDateTime 时区信息。
连接选项
Qt SQLite 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
qsqlite_busy_timeout | 以毫秒为单位的忙处理程序超时(val <= 0:禁用),更多信息请参阅SQLite 文档 |
qsqlite_use_qt_vfs | 如果设置,数据库将使用 Qt 的 VFS 打开,它允许使用QFile 打开数据库。这样,它不仅能从任何读写位置(如 android 共享存储)打开数据库,还能从只读资源(如 qrc 或 android assets)打开数据库。请注意,从只读资源打开数据库时,请确保同时添加 QSQLITE_OPEN_READONLY 属性。否则将无法打开。 |
qsqlite_open_readonly | 如果设置了该属性,数据库将以只读模式打开,如果不存在数据库,打开将失败。否则,数据库将以读写模式打开,如果数据库文件尚不存在,则将创建数据库(默认值) |
qsqlite_open_uri | 给定的文件名被解释为 uri,参见SQLITE_OPEN_URI |
qsqlite_enable_shared_cache | 如果设置,数据库将以共享缓存模式打开,否则以私有缓存模式打开 |
qsqlite_enable_regexp | 如果设置,插件将定义一个可在查询中使用的函数 "regex",QRegularExpression 用于评估 regex 查询 |
qsqlite_no_use_extended_result_codes | 禁用 SQLite 中的扩展结果代码功能 |
qsqlite_enable_non_ascii_case_folding | 如果设置,插件会用QString 函数替换 "lower "和 "upper "函数,以正确折叠非大小写字符的大小写。 |
qsqlite_open_nofollow | 如果设置,则数据库文件名不允许包含符号链接 |
如何构建 QSQLITE 插件
SQLite 第 3 版作为第三方库包含在 Qt 中。可通过向qt-cmake
命令行传递-DFEATURE_system_sqlite=OFF
参数来构建它。
如果不想使用 Qt 包含的 SQLite 库,可以向qt-cmake
命令行传递-DFEATURE_system_sqlite=ON
,以使用操作系统的 SQLite 库。在可能的情况下,我们建议您这样做,因为这样可以减少安装文件的大小,并删除一个需要跟踪安全公告的组件。
在 Unix 和 macOS 上(将$SQLITE
替换为 SQLite 所在的目录):
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DFEATURE_system_sqlite=ON -DCMAKE_INCLUDE_PATH="$SQLITE/include" -DCMAKE_LIBRARY_PATH="$SQLITE/lib" cmake --build . cmake --install .
在 Windows 上(假设 SQLite 安装在C:\SQLITE
):
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DFEATURE_system_sqlite=ON -DCMAKE_INCLUDE_PATH="C:\SQLITE\include" -DCMAKE_LIBRARY_PATH="C:\SQLITE\lib" cmake --build . cmake --install .
启用 REGEXP 操作符
SQLite 自带 REGEXP 操作。不过,用户必须提供所需的实现。为方便起见,可通过setting the connect option QSQLITE_ENABLE_REGEXP
在the database connection is opened 之前启用默认实现。这样,类似 "列 REGEXP 'pattern'"的 SQL 语句基本上就可以扩展为 Qt SQL 代码了
column.contains(QRegularExpression("pattern"));
为了提高性能,正则表达式会在内部缓存。默认情况下缓存大小为 25,但可以通过选项值进行更改。例如,通过 "QSQLITE_ENABLE_REGEXP=10
" 可以将缓存大小减小到 10。
QSQLITE 文件格式兼容性
SQLite 小版本有时会破坏文件格式的兼容性。例如,SQLite 3.3 可以读取 SQLite 3.2 创建的数据库文件,但 SQLite 3.2 无法读取 SQLite 3.3 创建的数据库。有关版本间文件格式兼容性的信息,请参阅 SQLite 文档和更改日志。
Qt 小版本通常紧跟 SQLite 小版本,而 Qt 补丁版本紧跟 SQLite 补丁版本。因此,补丁发布既向后又向前兼容。
要强制 SQLite 使用特定的文件格式,必须如上图所示,构建并发布自己的数据库插件和自己的 SQLite 库。某些版本的 SQLite 可通过在构建 SQLite 时设置SQLITE_DEFAULT_FILE_FORMAT
定义来强制写入特定文件格式。
用于 Mimer SQL 11 及更高版本的 QMIMER
Qt Mimer SQL 插件使 Mimer SQL RDBMS 成为可能。Mimer SQL 提供符合 ISO SQL 国际标准的占用空间小、可扩展且稳健的关系数据库解决方案。Mimer SQL 可在 Windows、Linux、macOS 和 OpenVMS 以及 QNX、Android 和嵌入式 Linux 等多个嵌入式平台上使用。
Mimer SQL 完全支持 Unicode。要处理 Unicode 数据,必须使用列类型 National Character (NCHAR)、National Character Varying (NVARCHAR) 或 National Character Large Object (NCLOB)。有关 Mimer SQL 和 Unicode 的更多信息,请参阅https://developer.mimer.com/features/multilingual-support。
时间戳支持
MimerSQL 对时区一无所知,使用QDateTime 时完全不遵守时区。
注意: :将来可能会改变。
QMIMER 存储过程支持
Mimer SQL 具有符合 SQL 标准(PSM)的存储过程,插件完全支持 IN、OUT、INOUT 参数以及结果集过程。
带有 INOUT 和 OUT 参数的存储过程示例:
create procedure inout_proc (INOUT param1 INT, OUT param2 INT) BEGIN set param1 = param1 * 2; set param2 = param1 * param1; END
访问 INOUT 和 OUT 值的源代码:
QSqlDatabase db; QSqlQuery query; int i1 = 10, i2 = 0; query.prepare("call qtestproc(?, ?)"); query.bindValue(0, i1, QSql::InOut); query.bindValue(1, i2, QSql::Out); query.exec();
如何在 Unix 和 macOS 上构建 QMIMER 插件
您需要 Mimer SQL 头文件和共享库。安装https://developer.mimer.com 上的任何 Mimer SQL 变体即可获得它们。
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DMimer_INCLUDE_DIR="/usr/include" -DMimer_LIBRARIES="/usr/lib/libmimer.so" cmake --build . cmake --install .
如何在 Windows 上构建 QMIMER 插件
您需要 Mimer SQL 头文件和共享库。安装https://developer.mimer.com 上的任何 Mimer SQL 变体即可获得它们。
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DMimer_INCLUDE_DIR="C:\Program Files\Mimer SQL Experience 11.0\dev\include" -DMimer_LIBRARIES="C:\Program Files\Mimer SQL Experience 11.0\dev\lib\amd64\mimapi64.lib|C:\Program Files\Mimer SQL Experience 11.0\dev\lib\x86\mimapi32.lib" cmake --build . cmake --install .
用于 Borland InterBase 的 QIBASE
Qt InterBase 插件使访问 InterBase 和 Firebird 数据库成为可能。InterBase 可作为客户端/服务器使用,也可在没有服务器的情况下在本地文件上运行。在建立连接之前,数据库文件必须存在。Firebird 必须与服务器配置一起使用。
请注意,InterBase 要求您指定数据库文件的完整路径,无论该文件是存储在本地还是其他服务器上。
时间戳支持
Interbase 以 UTC 保存时间戳,不包含任何时区信息。因此,在使用QDateTime 时完全不考虑时区。
从 Firebird 4.0 开始,数据库支持带有时区的时间戳。时区信息与时间戳分开存储,以便日后正确检索。有关时间戳处理的更多信息,请参阅 Firebird文档。
连接选项
Qt Borland InterBase 插件支持以下连接选项:
属性 | 可能的值 |
---|---|
isc_dpb_sql_role_name | 指定登录角色名称 |
如何构建 QIBASE 插件
QSqlDatabase db; db.setHostName("MyServer"); db.setDatabaseName("C:\\test.gdb");
您需要 InterBase/Firebird 开发头文件和库来构建此插件。
由于与 GPL 许可证不兼容,Qt 开源版用户不能将此插件与 InterBase 商业版链接。请使用 Firebird 或免费版 InterBase。
QIBASE 存储过程
InterBase/Firebird 返回 OUT 值作为结果集,因此在调用存储过程时,只需通过QSqlQuery::bindValue() 绑定 IN 值。RETURN/OUT 值可通过QSqlQuery::value() 进行检索。示例
QSqlQueryq; q.exec("execute procedure my_procedure");if(q.next()) qDebug() << q.value(0); // outputs the first RETURN/OUT value
如何在 Unix 和 macOS 上构建 QIBASE 插件
以下假设 InterBase 或 Firebird 已安装在/opt/interbase
中:
如果您使用的是 InterBase:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_source_directory>/qtbase/src/plugins/sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>/<platform> -DInterbase_ROOT="/opt/interbase/" cmake --build . cmake --install .
可选择使用 CMake 变量Interbase_INCLUDE_DIR
和Interbase_LIBRARY
直接指定包含路径和库。
如何在 Windows 上构建 QIBASE 插件
以下假设 InterBase 或 Firebird 已安装在C:\interbase
中:
如果您使用的是 InterBase:
mkdir build-sqldrivers cd build-sqldrivers qt-cmake -G Ninja <qt_installation_path>\Src\qtbase\src\plugins\sqldrivers -DCMAKE_INSTALL_PREFIX=<qt_installation_path>\<platform> -DInterbase_ROOT="C:\interbase" cmake --build . cmake --install .
可选择使用 CMake 变量Interbase_INCLUDE_DIR
和Interbase_LIBRARY
直接指定包含路径和库。
注意C:\interbase\bin
必须位于PATH
.
故障排除
应始终使用与项目所用编译器相同的客户端库。如果无法获得源代码发行版来自行编译客户端库,则必须确保预编译库与编译器兼容,否则会出现大量 "未定义符号 "错误。
如果编译插件成功,但之后却无法加载,请通过以下步骤找出问题所在:
- 确保插件位于正确的目录下。您可以使用 QApplication::libraryPaths() 来确定 Qt 查找插件的位置。
- 确保 DBMS 的客户端库在系统上可用。在 Unix 上,运行
ldd
命令,并将插件名称作为参数传递,例如ldd libqsqlmysql.so
。如果找不到客户端库,系统会发出警告。在 Windows 系统中,可以使用 Visual Studio 的依赖关系步行器或依赖关系图形用户界面查找依赖库。使用Qt Creator 时,可以更新项目面板运行部分中的PATH
环境变量,使其包含客户端库文件夹的路径。 - 使用 MSVC 时,还要确保插件是以正确的构建类型构建的。由于调试和发布的 MSVC 运行时不同,Qt 调试构建无法加载 Qt 发布插件,反之亦然。
- 运行编译后的 Qt 可执行文件时设置环境变量QT_DEBUG_PLUGINS,以便在加载插件时获得非常详细的调试输出。
- 要从 SQL 子系统获取可能的调试信息,请将环境变量
QT_LOGGING_RULES
设置为qt.sql.*.debug=true
,以启用输出。在 Windows 上运行时,不要忘记启用控制台。有关如何设置日志记录规则的详细说明,请参阅Logging Rules 。
如何编写自己的数据库驱动程序
QSqlDatabase 负责加载和管理数据库驱动程序插件。添加数据库时(参见 () ),会加载相应的驱动程序插件(使用 )。 依靠驱动程序插件为 和 提供接口。QSqlDatabase::addDatabase QSqlDriverPlugin QSqlDatabase QSqlDriver QSqlResult
QSqlDriver 是一个抽象基类,定义了 SQL 数据库驱动程序的功能。 负责连接数据库、建立适当的环境等。此外, 可以创建适合特定数据库 API 的 对象。 将其许多函数调用直接转发给 ,后者提供具体实现。QSqlDriver::open QSqlDriver::close QSqlDriver QSqlDriver QSqlQuery QSqlDatabase QSqlDriver
QSqlResult 是一个抽象基类,定义了 SQL 数据库查询的功能。 包含 QSqlResult::next() 和 QSqlResult::value() 等函数。 负责向数据库发送查询、返回结果数据等。 将其许多函数调用直接转发给提供具体实现的 。SELECT
UPDATE
ALTER
TABLE
QSqlResult QSqlResult QSqlQuery QSqlResult
QSqlDriver QSqlResult 和 紧密相连。在实现 驱动程序时,必须对这两个类进行子类化,并实现每个类中的抽象虚拟方法。Qt SQL
要将Qt SQL 驱动程序作为插件实现(以便 Qt 库在运行时识别并加载该驱动程序),该驱动程序必须使用Q_PLUGIN_METADATA() 宏。阅读《如何创建 Qt 插件》,了解更多相关信息。您还可以在QTDIR/qtbase/src/plugins/sqldrivers
中查看随 Qt 提供的 SQL 插件是如何实现的。
以下代码可用作 SQL 驱动程序的骨架:
class XyzResult : public QSqlResult { public: XyzResult(const QSqlDriver *driver) : QSqlResult(driver) {} ~XyzResult() {} protected: QVariant data(int /* index */) override { return QVariant(); } bool isNull(int /* index */) override { return false; } bool reset(const QString & /* query */) override { return false; } bool fetch(int /* index */) override { return false; } bool fetchFirst() override { return false; } bool fetchLast() override { return false; } int size() override { return 0; } int numRowsAffected() override { return 0; } QSqlRecord record() const override { return QSqlRecord(); } }; class XyzDriver : public QSqlDriver { public: XyzDriver() {} ~XyzDriver() {} bool hasFeature(DriverFeature /* feature */) const override { return false; } bool open(const QString & /* db */, const QString & /* user */, const QString & /* password */, const QString & /* host */, int /* port */, const QString & /* options */) override { return false; } void close() override {} QSqlResult *createResult() const override { return new XyzResult(this); } };
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.