第 26 章:连接器

目录

26.1. MySQL Connector/ODBC
26.1.1. MyODBC 介绍
26.1.2. 关于 ODBC 和 MyODBC 的一般信息
26.1.3. 如何安装 MyODBC
26.1.4. 在 Windows 平台上从二进制版本安装 MyODBC
26.1.5. I 在 Unix 平台上从二进制版本安装 MyODBC
26.1.6. 在 Windows 平台上从源码版本安装 MyODBC
26.1.7. 在 Unix 平台上从源码版本安装 MyODBC
26.1.8. 从 BitKeeper 开发源码树安装 MyODBC
26.1.9. MyODBC 配置
26.1.10. 与 MyODBC 连接相关的事宜
26.1.11. MyODBC 和 Microsoft Access
26.1.12. MyODBC 和 Microsoft VBA 及 ASP
26.1.13. MyODBC 和第三方 ODBC 工具
26.1.14. MyODBC 通用功能
26.1.15. 基本的 MyODBC 应用步骤
26.1.16. MyODBC API 引用
26.1.17. MyODBC 数据类型
26.1.18. MyODBC 错误代码
26.1.19. MyODBC 与 VB:ADO、DAO 和 RDO
26.1.20. MyODBC 与 Microsoft.NET
26.1.21. 感谢
26.2. MySQL Connector/NET
26.2.1. 前言
26.2.2. 下载并安装 MySQL Connector/NET
26.2.3. Connector/NET 体系结构
26.2.4. 使用 MySQL Connector/NET
26.2.5. MySQL Connector/NET 变更史
26.3. MySQL Connector/J
26.3.1. 基本的 JDBC 概念
26.3.2. 安装 Connector/J
26.3.3. JDBC 引用
26.3.4. 与 J2EE 和其他 Java 框架一起使用 Connector/J
26.3.5. 诊断 Connector/J 方面的问题
26.3.6. Changelog
26.4. MySQL Connector/MXJ
26.4.1. 前言
26.4.2. 支持平台:
26.4.3. Junit 测试要求
26.4.4. 运行 Junit 测试
26.4.5. 作为 JDBC 驱动程序的一部分运行
26.4.6. 在 Java 对象中运行
26.4.7. MysqldResource API
26.4.8. 在 JMX 代理 (custom) 中运行
26.4.9. 部署在标准的 JMX 代理环境下 (JBoss)
26.4.10. 安装
在本章中,介绍了 MySQL 连接器,所谓连接器,是为客户端程序提供与 MySQL 服务器连接性的驱动程序。

26.1. MySQL Connector/ODBC

通过 MySQL Connector/ODBC(MyODBC 驱动程序系列),MySQL 为 ODBC 提供了支持。这是针对 MyODBC 驱动程序中 Connector/ODBC 产品系列的参考,它提供了对 MySQL 数据库系统的 ODBC 3.5x 兼容访问。介绍了安装 MyODBC 和使用 MyODBC 的方式。此外,在本章中还介绍了能够与 MyODBC 一起工作的公用程序信息,并回答了一些关于 MyODBC 的常见问题。

本参考适用于 MyODBC 3.51。对于相应的版本,你可以找到旧的二进制版或源码版 MyODBC 手册。

这是关于 MySQL ODBC 驱动程序的参考手册,而不是通用 ODBC 参考。关于 ODBC 的更多信息,请参阅http://www.microsoft.com/data/

对于本参考的应用程序开发部分,假定用户在 C 语言方面有着良好的实践知识,对 DBMS 有一般了解,最后,还应熟悉 MySQL。关于 MySQL 功能及其语法的更多信息,请参阅http://dev.mysql.com/doc/

如果你的问题未能在本文档中得到解答,请发送电子邮件至myodbc@lists.mysql.com

26.1.1. MyODBC 介绍

26.1.1.1. ;什么是 ODBC?

ODBC(开放式数据库连接性) 为客户端程序提供了访问众多数据库或数据源的一种方式。ODBC 是标准化的 API,允许与 SQL 数据库服务器进行连接。它是根据 SQL Access Group 的规范开发的,它定义了一套函数调用、错误代码和数据类型,可将其用于开发独立于数据库的应用程序。通常情况下,当需要数据库独立或需要同时访问不同的数据源时,将用到 ODBC。

关于 ODBC 的更多信息,请参阅http://www.microsoft.com/data/

26.1.1.2. ;什么是 Connector/ODBC?

Connector/ODBC 是描述 MySQL ODBC 驱动程序 MySQL AB 产品系列的名称。它们也称为 MyODBC 驱动程序。

26.1.1.3. ;什么是 MyODBC 2.50?

MyODBC 2.50 是 MySQL AB 的 32 位 ODBC 驱动程序,它基于 ODBC 2.50 规范层次 0(具有层次 1 和层次 2 的特性)。这是开放源码市场最流行的 ODBC 驱动程序之一,很多用户都使用它来访问 MySQL 提供的功能。

26.1.1.4. ;什么是 MyODBC 2.50?

MyODBC 3.51 是一种 32 位 ODBC 驱动程序,也称为 MySQL ODBC 3.51 驱动程序。与已有的 MyODBC 2.50 驱动程序相比,该版本有所增强。它支持 ODBC 3.5x 规范层次 1(全部核心 API +层次 2 特性),以便能够为访问 MySQL 提供所有的 ODBC 功能。

26.1.1.5. ;从哪获取 MyODBC

MySQL AB 依 GPL(通用公共许可) 发布其所有产品。你可以从 MySQL AB 的网站获取最新的 MyODBC 二进制版和源码版:http://dev.mysql.com/downloads/

关于 MyODBC 的更多信息,请访问 http://www.mysql.com/products/myodbc/。

关于许可的更多信息,请访问 http://www.mysql.com/company/legal/licensing/。

26.1.1.6. ;支持的平台

MyODBC 可用于 MySQL 支持的所有主要平台,如:

·         Windows 95, 98, Me, NT, 2000, XP 和 2003

·         所有 Unix 操作系统

o        AIX

o        Amiga

o        BSDI

o        DEC

o        FreeBSD

o        HP-UX 10, 11

o        Linux

o        Mac OS X Server

o        Mac OS X

o        NetBSD

o        OpenBSD

o        OS/2

o        SGI Irix

o        Solaris

o        SunOS

o        SCO OpenServer

o        SCO UnixWare

o        Tru64 Unix

对于特定平台,如果无法下载二进制版本,可通过下载驱动程序源码自行创建驱动程序。你也可以为 MySQL 贡献二进制代码,方式是发送邮件至myodbc@lists.mysql.com,这样其他用户就能使用你贡献的内容。

26.1.1.7. MyODBC 邮件列表

MySQL AB 通过其邮件列表为用户社区提供帮助。对于与 MyODBC 有关的事宜,可使用myodbc@lists.mysql.com邮件列表,从有经验的用户处获得帮助。

关于订阅 MySQL 邮件列表或浏览列表档案的更多信息,请访问http://lists.mysql.com/

其中,关注程度最高的是论坛 MySQL 连接器部分的 ODBC 论坛。

26.1.1.8. MyODBC 论坛

通过 MySQL 论坛 (位于http://forums.mysql.com),可获得有经验用户的支持和帮助。

26.1.1.9. ;如何通报 MyODBC 问题或缺陷

如果遇到与 MyODBC 有关的困难或问题,首先应使用ODBC 管理器和MyODBC 生成一份日志文件(请求来自 ODBC ADMIN 的日志时获得的日志文件)。关于完成该步骤的方式,请参见26.1.9.7 节,“获取 ODBC 跟踪文件”

检查 MyODBC 跟踪文件,找出可能出错的地方。通过在myodbc.log 文件中搜索字符串>mysql_real_query,可确定已执行的语句。

此外,你还应尝试从mysql客户端程序或admndemo 执行语句。这样,就能帮助你确定错误的出处,MyODBC 或 MySQL。

如果你发现了不正确的事项,请将相关行 (最多 40 行) 发送给 MyODBC 邮件列表。请参见1.7.1.1 节,“MySQL 邮件列表”。请勿发送整个 MyODBC 或 ODBC 日志文件!

如果你无法找出错误之所在,最后的选择是,以 tar 或 zip 格式创建包含 MyODBC 跟踪文件、ODBC 日志文件和 README 文件 (阐明问题) 的档案。你可以将该档案文件发送至ftp://ftp.mysql.com/pub/mysql/upload/。只有位于 MySQL AB 的我们才能访问你上传的文件,而且我们会十分谨慎地对待这类数据。

如果你创建了仍出现问题的程序,请将该程序也包含在档案文件中。

如果程序能够与某些其他 SQL 服务器一起工作,档案中还应包含在这类其他 SQL 服务器下工作的 ODBC 日志文件。

请记住,你提供给我们的信息越多,我们更正问题的机会就越大。

26.1.1.10. ;如何提交 MyODBC 补丁

你可以通过电子邮件,就已有代码或问题发送补丁或提出更好的解决方案:myodbc@lists.mysql.com

26.1.2. ;关于 ODBC 和 MyODBC 的一般信息

26.1.2.1. ODBC 介绍

开放式数据库连接性 (ODBC) 是广泛接受的用于数据库访问的应用程序编程接口 (API)。它基于针对数据库 API 的 CLI(调用层接口) 规范 (来自 X/Open 和 ISO/IEC),并采用了结构化查询语言 (SQL) 作为其数据库访问语言。

26.1.16 节,“MyODBC API 引用”中,概要介绍了 MyODBC 支持的 ODBC 功能。关于 ODBC 的更多信息,请参阅http://www.microsoft.com/data/

26.1.2.2. MyODBC 体系结构

MyODBC 体系结构建立在 5 个组件上,如下图所示:

MyODBC Architecture

·         应用程序:

应用程序指的是通过调用 ODBC API 来访问 MySQL 服务器上数据的程序。应用程序使用标准的 ODBC 调用与驱动管理器进行通信。应用程序不关心数据的存储位置,存储方式,甚至不关心为访问数据而进行的系统配置方式。它仅需要知道数据源名 (DSN)。

对于所有的应用程序,无论它们使用 OBDC 的方式是什么,很多任务是共同的。这些任务包括:

o        选择 MySQL 服务器,并与之连接。

o        提交将要执行的 SQL 语句。

o        检索结果 (如果有的话)。

o        处理错误。

o        提交或回滚包含 SQL 语句的事务。

o        断开与 MySQL 服务器的连接。

由于大多数数据访问工作是使用 SQL 完成,对于使用 OBDC 的应用程序来说,其主要任务是提交 SQL 语句,并检索由这些语句生成的结果。

·         驱动管理器:

驱动管理器是用于管理应用程序和驱动程序间通信的库。它负责执行下述任务:

o        解析数据源名 (DSN)。

o        加载和卸载驱动程序。

o        处理 ODBC 调用,或将其传递给驱动程序。

·         MyODBC 驱动程序:

MyODBC 驱动程序是用于实施 ODBC API 所提供功能的库。它负责处理 ODBC 函数调用,将 SQL 请求提交给 MySQL 服务器,并将结果返回给应用程序。如有必要,驱动程序会更改应用程序的请求,以便该请求符合 MySQL 支持的语法。

·         ODBC.INI:

ODBC.INI是 ODBC 配置文件,其中保存了连接到服务器所需的驱动信息和数据库信息。驱动管理器将使用它来确定加载哪个驱动程序 (使用数据源名)。驱动程序将根据指定的 DSN 使用它来读取连接参数。更多信息,请参见26.1.9 节,“MyODBC 配置”

·         MySQL 服务器:

MySQL 服务器是数据源。MySQL 是:

o        一种数据库管理系统 (DBMS)

o        一种关联数据库管理系统 (RDBMS)

o        开放源码软件

26.1.2.3. ODBC 驱动管理器

ODBC 驱动管理器是用于管理 ODBC 应用程序和驱动程序间通信的库。其主要功能包括:

·         解析数据源名 (DSN)。

·         加载和卸载驱动程序。

·         处理 ODBC 函数调用,或将其传递给驱动程序。

下面给出了一些常用的驱动程序:

·         Microsoft Windows ODBC 驱动管理器 (odbc32.dll),http://www.microsoft.com/data/

·         unixODBC Unix 驱动管理器 (libodbc.so),http://www.unixodbc.org

·         iODBC ODBC Unix 驱动管理器 (libiodbc.so),http://www.iodbc.org

从 2.1.2 版开始,UnixODBC 也提供 MyODBC 3.51。

26.1.2.4. MySQL ODBC 驱动程序的类型

MySQL AB 支持两种通过 ODBC API 访问 MySQL 功能的开放源码 ODBC 驱动程序: MyODBC (MyODBC 2.50) 和 MySQL ODBC 3.51 驱动 (MyODBC 3.51)。

注释: 从本节起,我们将这两类驱动程序统称为 MyODBC。但当存在差异时,我们将使用它们的本名。

26.1.3. ;如何安装 MyODBC

MyODBC 能够工作在 Windows 9x, Me, NT, 2000, XP 和 2003,以及大多数 Unix 平台上。

MyODBC 是开放源码软件。你可以在网站http://dev.mysql.com/downloads/connector/odbc/上找到它的最新版本。请注意,2.50.x 版采用的是 LGPL 许可,而 3.51.x 版采用的是 GPL 许可。

如果使用 MyODBC 时出现了问题,而且你的程序还能与 OLEDB 一起工作,应尝试使用 OLEDB 驱动程序。

正常情况下,在 Windows 机器上仅需安装 MyODBC。仅当你拥有运行在 Unix 机器上的程序 (如 ColdFusion),而且该程序将使用 ODBC 来访问数据库时,才需安装用于 Unix 的 MyODBC。

如果你打算在 Unix 机器上安装 MyODBC,还需要 1 个 ODBC 管理器。MyODBC 能够与大多数 Unix ODBC 管理器一起工作。

·         要想使用 ODBC 应用程序 (不支持 MySQL 的应用程序),建立从 Windows 平台到 Unix 平台的连接,首先必须在 Windows 机器上安装 MyODBC。

·         用户和 Windows 机器必须具有访问位于 Unix 机器上的 MySQL 服务器的权限。这可通过 GRANT 命令设置。请参见13.5.1.3 节,“GRANT 和 REVOKE 语法”

·         必须创建 ODBC DSN 条目,方式如下:

1.    打开 Windows 机器上的控制面板。

2.    双击ODBC 数据源 32 位图标。

3.    点击选项卡“用户 DSN”。

4.    点击“添加”按钮。

5.    在“创建新数据源”屏幕上选择 MySQL,并点击“完成”按钮。

6.    显示 MySQL 驱动程序的默认配置屏幕。请参见26.1.9.2 节,“在 Windows 上配置 MyODBC DSN”

·         启动应用程序,并使用在 ODBC 管理器中指定的 DSN 选择 ODBC 驱动程序。

注意,在 MySQL 屏幕上还显示了其他选项,如果遇到问题,可尝试这些选项 (如跟踪、连接时不提示等)。

26.1.4. ;在 Windows 平台上从二进制版本安装 MyODBC

要想在 Windows 平台上安装 MyODBC,应从下述站点下载恰当的分发文件,http://dev.mysql.com/downloads/connector/odbc/,解压该文件,并执行MyODBC-VERSION.exe文件。

在 Windows 平台上,安装较旧的 MyODBC 2.50 驱动时,可能会遇到下述错误:

拷贝 C:\WINDOWS\SYSTEM\MFC30.DLL 时出现错误。

 
重启 Windows,并再次安装 (在运行任何使用 ODBC 的应用程序之前)。

问题在于其他程序正使用 ODBC。由于 Windows 的设计方式,在这种情况下,你可能无法使用 Microsoft 的 ODBC 设置程序安装新的 ODBC 驱动。在大多数情况下,可以通过连续按“忽略”键拷贝剩余的 MyODBC 文件,最终安装应仍能工作。如不然,解决方案是在“安全模式”下重新启动计算机。在重启的过程中,在机器启动 Windows 前按 F8,选择“安全模式”,安装 MyODBC,然后在正常模式下重新启动计算机。

26.1.5. I 在 Unix 平台上从二进制版本安装 MyODBC

26.1.5.1. ;从 RPM 分发版安装 MyODBC

要想使用 RPM 分发版在 Linux 平台上安装或升级 MyODBC,可简单地下载最新 MyODBC 的 RPM 分发版,并按照下面介绍的方式操作。使用su root成为根用户,然后安装 RPM 文件。

如果是首次安装:

shell> su root
shell> rpm -ivh MyODBC-3.51.01.i386-1.rpm

如果驱动程序已存在,可按照下述方式升级它:

shell> su root
shell> rpm -Uvh MyODBC-3.51.01.i386-1.rpm

如果存在关于 MySQL 客户端库libmysqlclient 的任何依存错误,可使用-nodeps选项简单地忽略它,然后确保 MySQL 客户端共享库位于路径中或通过LD_LIBRARY_PATH 进行了设置。

这样,就会将驱动程序库和相关文件分别安装到/usr/local/lib/usr/share/doc/MyODBC目录下。请转至26.1.9.3 节,“在 Unix 平台上配置 MyODBC DSN”

要想卸载驱动程序,请首先成为根用户,然后执行rpm命令:

shell> su root
shell> rpm -e MyODBC

26.1.5.2. ;从二进制 Tarball 分发版安装 MyODBC

要想从 tarball 分发版 (.tar.gz 文件) 安装驱动程序,请下载针对你所使用操作系统的最新版驱动程序,然后按照下述步骤操作:

shell> su root
shell> gunzip MyODBC-3.51.01-i686-pc-linux.tar.gz
shell> tar xvf MyODBC-3.51.01-i686-pc-linux.tar
shell> cd MyODBC-3.51.01-i686-pc-linux

请阅读INSTALL-BINARY 文件中的安装说明,并执行下述命令:

shell> cp libmyodbc* /usr/local/lib
shell> cp odbc.ini /usr/local/etc
shell> export ODBCINI=/usr/local/etc/odbc.ini

然后,请跳至26.1.9.3 节,“在 Unix 平台上配置 MyODBC DSN”为 MyODBC 配置 DSN。更多信息,请参见与发布版一起提供的INSTALL-BINARY文件。

26.1.6. ;在 Windows 平台上从源码版本安装 MyODBC

26.1.6.1. ;要求

·         MDAC, Microsoft Data Access SDK:http://www.microsoft.com/data/

·         MySQL 客户端库以及 MySQL 4.0.0 或更高版本的包含文件。(最好是 MySQL 4.0.16 或更高版本)。应满足上述要求,这是因为 MyODBC 需要用到该版本以上的库才提供的新调用和结构。要想获得客户端库和包含文件,请访问http://dev.mysql.com/downloads/

26.1.6.2. ;构建 MyODBC 3.51

MyODBC 3.51 源码分发版包括使用nmakeMakefiles。在分发版中,你可以找到用于创建发布版的Makefile,以及用于创建驱动库和 DLL 调试版的 Makefile_debug

要想创建驱动程序,请采取下述步骤:

1.    下载并将源码展开到文件夹,然后将位置切换到该文件夹。在下述命令中,假定文件夹为myodbc3-src:

2.           C:\> cd myodbc3-src

3.    编辑Makefile,为MySQL 客户端库和头文件指定正确的路径。然后使用下述命令创建并安装发布版。

4.           C:\> nmake -f Makefile
5.           C:\> nmake -f Makefile install

nmake -f Makefile用于创建驱动程序的发布版并将二进制码放入名为 Release 的子目录下。

nmake -f Makefile install用于将驱动程序 DLL 和库 (myodbc3.dll, myodbc3.lib) 安装 (拷贝) 到系统目录下。

6.    要想创建调试版,请使用Makefile_Debug 而不是 Makefile,如下所示:

7.           C:\> nmake -f Makefile_debug
8.           C:\> nmake -f Makefile_debug install

9.    使用下述命令,可清除并重新创建驱动程序:

10.       C:\> nmake -f Makefile clean
11.       C:\> nmake -f Makefile install

注释:

·         确保在 Makefiles 中指定了正确的 MySQL 客户端库和头文件路径 (设置MYSQL_LIB_PATHMYSQL_INCLUDE_PATH变量)。默认的头文件路径是C:\mysql\include。对于发布版 DLL,默认的库路径是C:\mysql\lib\opt,对于调试版,默认路径是 C:\mysql\lib\debug。

·         关于nmake的完整用法,请参见http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vcce4/html/evgrfRunningNMAKE.asp

·         如果你正在使用 BitKeeper 树来进行编译,所有的针对 Windows 的Makefiles 均将被命名为 Win_Makefile*

26.1.6.3. ;测试

将驱动程序库拷贝/安装到系统目录后,可使用示例子目录下提供的示例测试这些库是否已正确创建:
C:\> cd samples
C:\> nmake -f Makefile all

26.1.6.4. ;构建 MyODBC 2.50

MyODBC 2.50 源码分发版包含 VC 工作空间文件。通过在 Microsoft Visual Studio 6.0 中加载这些文件 (.dsp.dsw),可使用它们直接创建驱动程序。

26.1.7. ;在 Unix 平台上从源码版本安装 MyODBC

26.1.7.1. ;要求

·         MySQL 客户端库以及 MySQL 4.0.0 或更高版本的包含文件。(最好是 MySQL 4.0.16 或更高版本)。应满足上述要求,这是因为 MyODBC 需要用到该版本以上的库才提供的新调用和结构。要想获得客户端库和包含文件,请访问http://dev.mysql.com/downloads/

·         必须使用“--enable-thread-safe-client”选项配置 MySQL 库。Libmysqlclient 是作为共享库安装的。

·         必须安装下述 Unix ODBC 驱动管理器之一:

o        iodbc 3.0 或更高版本 (http://www.iodbc.org)

o        unixodbc Alpha 3 或更高版本 (http://www.unixodbc.org)

·         如果使用了未编译在 MySQL 客户端库中的字符集 (默认字符集为: latin1 big5 czech euc_kr gb2312 gbk sjis tis620 ujis),就需要从字符集目录下将 mysql 字符定义安装到SHAREDIR中 (默认情况下位于/usr/local/mysql/share/mysql/charsets)。如果在相同机器上安装了 MySQL,它们应位于恰当位置。

一旦完成了所有所需文件的安装,将源码文件解包到单独目录下,并按照下面给出的说明进行操作。

26.1.7.2. ;典型配置选项

使用configure脚本,能够对你所创建 MyODBC 的配置方式进行多种控制。典型情况下,可在“configure”命令行使用选项完成该配置操作。也可以使用环境变量来影响配置。要想了解“configure”命令支持的选项列表和环境变量,可运行下述命令:
shell> ./configure --help

下面介绍了一些常用的“configure”选项。

1.    要想编译 MyODBC,须使用“--with-mysql-path=DIR”选项来提供 MySQL 客户端库文件和包含文件路径,其中,“DIR”是 MySQL 的安装目录。

可通过运行“DIR/bin/mysql_config”来确定 MySQL 编译选项。

2.    为 ODBC 驱动管理器 (iodbcunixobc) 提供标准的头文件和库文件路径。

·         如果你正在使用iodbc,而且iodbc 未安装在其默认位置(/usr/local),可能需要使用--with-iodbc=DIR”选项,其中,“DIR”是 iodbc 的安装目录。

如果 iodbc 头文件未位于DIR/include 目录下,可使用--with-iodbc-includes=INCDIR选项指定它们的位置。

上面所述也适用于库文件。如果库文件未位于DIR/lib目录下,可使用“--with-iodbc-libs=LIBDIR”选项。

·         如果你正在使用unixODBC,可使用--with-unixODBC=DIR”选项 (区分大小写),让configure寻找unixODBC 而不是默认的 iodbc,其中,“DIR”是 unixODBC 的安装目录。

如果 unixODBC 头文件和库文件未位于目录DIR/includeDIR/lib 下,可使用--with-unixODBC-includes=INCDIR”和“--with-unixODBC-libs=LIBDIR”选项。

3.    或许你也希望指定不同于“/usr/local”的安装前缀。例如,要想将 MyODBC 驱动安装到“/usr/local/odbc/lib”目录下,可使用“--prefix=/usr/local/odbc”选项。

最终的配置命令应与下面给出的相似:

shell> ./configure --prefix=/usr/local \
         --with-iodbc=/usr/local \
         --with-mysql-path=/usr/local/mysql

26.1.7.3. ;线程安全客户端

为了将驱动程序与 MySQL 线程安全客户端库libmysqlclient_r.solibmysqlclient_r.a 链接起来,必须指定下述configure选项:
--enable-thread-safe

也可以使用下述选项禁止它:

--disable-thread-safe

使用该选项,能够通过 mysql 线程安全客户端库libmysqlclient_r.so(扩展名与操作系统有关) 的链接,创建驱动程序线程安全库 libmyodbc3_r.so。

在配置线程安全选项时,如果出现了配置错误,应检查config.log,检查错误是否是因系统中缺少线程库而导致的,如果是,使用 LIBS 选项提供一个,即

LIBS="-lpthread" ./configure ..

26.1.7.4. ;共享或静态选项

可以使用下述选项启用或禁止共享和静态选项:

--enable-shared[=yes/no]
--disable-shared
--enable-static[=yes/no]
--disable-static

26.1.7.5. ;启用调试信息

默认情况下,所有的二进制分发版均会被创建为非调试版 (采用“--without-debug”进行配置)。

要想启用调试信息,请使用源码分发版创建驱动程序,并在运行“configure”时使用“--with-debug选项

26.1.7.6. ;允许文档功能

该选项仅能用于 BK 克隆树,而不是一般的源码分发版。

默认情况下,驱动程序是使用“--without-docs创建的。如果希望在正常创建过程中观察文档信息,可使用下述选项进行配置:

--with-docs

26.1.7.7. ;创建和编译

要想创建驱动程序库,仅需执行“make”,该命令能完成所有事项。
shell> make

如果出现错误,更正后,继续执行创建进程。如果无法创建,请发送详细的电子邮件至myodbc@lists.mysql.com,以获取进一步帮助。

26.1.7.8. ;创建共享库

在大多数平台上,默认情况下,MySQL 不会创建或支持“.so(共享) 客户端库,这是因为,创建共享库在过去造成过很多问题。

在这种情况下,你可以下载 MySQL 分发版,并使用以下选项进行配置:

--without-server --enable-shared

要想创建共享驱动程序库,必须为“configure”指定“--enable-shared选项。默认情况下,“configure”不启用该选项。

如果使用“--disable-shared”选项进行了配置操作,可使用下述命令,从静态库创建“.so”文件。

shell> cd MyODBC-3.51.01
shell> make
shell> cd driver
shell> CC=/usr/bin/gcc \
     $CC -bundle -flat_namespace -undefined error \
         -o .libs/libmyodbc3-3.51.01.so \
         catalog.o connect.o cursor.o dll.o error.o execute.o \
         handle.o info.o misc.o myodbc3.o options.o prepare.o \
         results.o transact.o utility.o \
         -L/usr/local/mysql/lib/mysql/ \
         -L/usr/local/iodbc/lib/ \
         -lz -lc -lmysqlclient -liodbcinst

如果你正在使用 unixODBC 而不是 iODBC,务必将“-liodbcinst更改为-lodbcinst,并相应地配置库路径。

这样,就创建了libmyodbc3-3.51.01.so 文件,并将其放在.libs目录下。将该文件拷贝到 MyODBC 库目录下 (/usr/local/lib,或使用--prefix提供的安装目录下的lib目录)。

shell> cd .libs
shell> cp libmyodbc3-3.51.01.so /usr/local/lib
shell> cd /usr/local/lib
shell> ln -s libmyodbc3-3.51.01.so libmyodbc3.so

要想创建线程安全驱动程序库:

shell> CC=/usr/bin/gcc \
     $ CC -bundle -flat_namespace -undefined error
      -o .libs/libmyodbc3_r-3.51.01.so
      catalog.o connect.o cursor.o dll.o error.o execute.o
      handle.o info.o misc.o myodbc3.o options.o prepare.o
      results.o transact.o utility.o
      -L/usr/local/mysql/lib/mysql/
      -L/usr/local/iodbc/lib/
      -lz -lc -lmysqlclient_r -liodbcinst

26.1.7.9. ;安装驱动库

要想安装驱动程序库,请执行下述命令:
shell> make install

该命令将安装下述库集合之一:

对于 MyODBC 3.51:

·         libmyodbc3.so

·         libmyodbc3-3.51.01.so,其中,3.51.01 是驱动程序的版本

·         libmyodbc3.a

对于线程安全 MyODBC 3.51:

·         libmyodbc3_r.so

·         libmyodbc3-3_r.51.01.so

·         libmyodbc3_r.a

对于 MyODBC 2.5.0:

·         libmyodbc.so

·         libmyodbc-2.50.39.so,其中,2.50.39 是驱动程序的版本

·         libmyodbc.a

关于创建进程的更多信息,请参阅与源码分发版一起提供的INSTALL 文件。注意,如果你试图使用 Sun 的“make”,可能会以错误结束。从另一方面来说,GNU gmake在所有平台上均能良好工作。

26.1.7.10. 在 Unix 平台上测试 MyODBC

要想与你创建的库一起运行分发版中提供的示例,可执行:
shell> make test

首先,务必在odbc.ini 中配置DSN 'myodbc3',并将环境变量ODBCINI 指向正确的 odbc.ini 文件;同时MySQL 服务器应处于运行状态。在驱动分发版中,可找到一个示例用odbc.ini 文件。

你甚至可以更改示例/运行示例脚本,以命令行参数的形式将所需的 DSN、UID 和 PASSWORD 值传递给示例。

26.1.7.11. Mac OS X 注意事项

要想在 Mac OS X (Darwin) 环境下创建驱动程序,可使用下述configure示例:
shell> ./configure --prefix=/usr/local
           --with-unixODBC=/usr/local
           --with-mysql-path=/usr/local/mysql
           --disable-shared
           --enable-gui=no
           --host=powerpc-apple

该命令假定 unixODBC 和 MySQL 均安装在默认位置。如不然,请进行相应配置。

在 Mac OS X 环境下,“--enable-shared选项将默认创建.dylib文件。你也可以采用下述方式创建“.so”文件:

shell> make
shell> cd driver
shell> CC=/usr/bin/gcc \
     $CC -bundle -flat_namespace -undefined error
         -o .libs/libmyodbc3-3.51.01.so *.o
         -L/usr/local/mysql/lib/
         -L/usr/local/iodbc/lib
         -liodbcinst -lmysqlclient -lz -lc

要想创建线程安全驱动程序库:

shell> CC=/usr/bin/gcc \
     $ CC -bundle -flat_namespace -undefined error
     -o .libs/libmyodbc3-3.51.01.so *.o
     -L/usr/local/mysql/lib/
     -L/usr/local/iodbc/lib
     -liodbcinst -lmysqlclienti_r -lz -lc -lpthread

如果你正在使用 unixODBC 而不是 iODBC,务必将“-liodbcinst更改为-lodbcinst,并相应地配置库路径。

在 Apple 的 GCC 版本中,ccgcc实际上均是gcc3的符号链接。

将该库拷贝到$prefix/lib 目录下,并将symlink 拷贝到libmyodbc3.so

可以使用下述命令交叉检验输出的共享库属性:

shell> otool -LD .libs/libmyodbc3-3.51.01.so

26.1.7.12. HP-UX 注意事项

要想在 HP-UX 10.x 或 11.x 环境下创建驱动程序,可使用下述configure示例:

如果使用cc

shell> CC="cc" \
     CFLAGS="+z" \
     LDFLAGS="-Wl,+b:-Wl,+s" \
     ./configure --prefix=/usr/local
           --with-unixodbc=/usr/local
           --with-mysql-path=/usr/local/mysql/lib/mysql
           --enable-shared
           --enable-thread-safe

如果使用gcc

shell> CC="gcc" \
     LDFLAGS="-Wl,+b:-Wl,+s" \
     ./configure --prefix=/usr/local
           --with-unixodbc=/usr/local
           --with-mysql-path=/usr/local/mysql
           --enable-shared
           --enable-thread-safe

一旦创建了驱动程序,使用“chatr .libs/libmyodbc3.sl”交叉检查其属性,查看是否需要使用SHLIB_PATH 环境变量的 MySQL 客户端库。对于静态版,忽略所有的共享库选项,并使用“--disable-shared”选项运行“configure”。

26.1.7.13. AIX 注意事项

要想在 AIX 环境下创建驱动程序,可使用下述configure示例:

shell> ./configure --prefix=/usr/local
           --with-unixodbc=/usr/local
           --with-mysql-path=/usr/local/mysql
           --disable-shared
           --enable-thread-safe
注释: 关于在不同平台上创建和设置静态和共享库方式的更多信息,请参见跨平台使用静态和共享库

26.1.8. ;从 BitKeeper 开发源码树安装 MyODBC

注释: 如果你对协助我们测试新的代码感兴趣,应阅读本节的内容。

要想获得我方的最新开发源码树,请:

1.    参见2.8.3 节,“从开发源码树安装”,关于如何下载和安装 BitKeeper 的说明。

2.    安装完 BitKeeper 后,首先进入打算在其中工作的目录,然后,如果打算克隆 MyODBC 3.51 分支,请使用该命令:

3.           shell> bk clone bk://mysql.bkbits.net/myodbc3 myodbc-3.51

在前面的示例中,源码树是在myodbc-3.51/中设置的,或在当前目录的 myodbc3/子目录下设置的 (默认)。如果你位于防火墙后,而且仅能启动 HTTP 连接,也可以通过 HTTP 使用 BitKeeper。如果要求使用代理服务器,可简单地设置环境变量http_proxy,使之指向代理服务器:

shell> export http_proxy="http://your.proxy.server:8080/"

执行克隆操作时,用http://替换 bk://。例如:

shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc-3.51

首次下载源码树时需要一段时间,具体情况取决于连接速度,请耐心等候。

4.    要想运行下一组命令,需要 GNU autoconf 2.52(或更新版本)automake 1.4libtool 1.4,以及m4

5.           shell> cd myodbc-3.51
6.           shell> bk -r edit
7.           shell> aclocal; autoheader; autoconf;  automake;
8.           shell> ./configure  # Add your favorite options here
9.           shell> make

关于如何创建的更多信息,请参阅位于相同目录下的INSTALL 文件。在 Windows 平台下,创建驱动程序时,请使用 Windows Makefiles WIN-MakefileWIN-Makefile_debug,更多信息,请参见26.1.6 节,“在 Windows 平台上从源码版本安装 MyODBC”

10.完成创建后,运行make install,将 MyODBC 3.51 驱动程序安装到你的系统上。

11.如果进入了make阶段,但并未编译分发版本,请将其通报给myodbc@lists.mysql.com

12.启动了bk clone操作获得源码树后,应定期运行bk pull进行更新。

13.可以使用“bk sccstool”检查树的变更史。如果你发现了有趣的差异,并对代码存在一问,请立刻发送电子邮件至myodbc@lists.mysql.com

此外,如果你认为有更好的主意,请发送电子邮件至相同的地址并附上补丁。更改了源码后,使用“bk diffs”可生成补丁。如果你没有时间就你的观点编写代码,可发送描述性信息。

14.BitKeeper 具有一个可通过bk helptool访问的帮助工具。

通过浏览http://mysql.bkbits.net:8080/myodbc3,也能在线浏览变化集、注释和源代码。

26.1.9. MyODBC 配置

本节介绍了配置 MyODBC 的方法,包括 DSN 创建,以及驱动程序在连接字符串中作为输入参数的不同参数。此外,还介绍了创建 ODBC 跟踪文件的方法。

26.1.9.1. ;什么是数据源名?

“数据源”是提供数据的地点。数据源必须有稳定的标识符,即数据源名。使用数据源名,MySQL 可访问初始化信息。通过初始化信息,MySQL 能够了解去哪里访问数据库,以及在开始访问时使用什么设置。

事实上,数据源就是数据的路径。在不同的情况下,它可能有着不同的内容,但是在典型情况下,它指明了正在运行的 MySQL 服务器 (例如,通过网络地址或服务器名),连接时该服务器的默认数据库,以及必要的连接信息 (如端口)。MySQL 驱动程序 (以及 Windows 系统上的 ODBC 驱动管理器) 将使用数据源进行连接。对于该目的,名为 Microsoft ODBC 数据源管理器的管理工具可能十分有用。

有两处可能保存初始化信息的位置: Windows 注册表 (Windows 系统),或 DSN 文件 (任何系统)。

如果信息位于 Windows 注册表中,它称为“机器数据源”。它可以是“用户数据源”,在这种情况下,只有一位用户能看到它。它也可以是“系统数据源”,在这种情况下,计算机上的所有用户均能访问它,如果用户是通过 Microsoft Windows NT 服务连接在一起的话,与该计算机相连的所有用户均能访问它。运行 ODBC 数据管理程序时,可以选择是否使用“用户”或“系统”,它们位于不同的选项卡上。

如果信息位于 DSN 文件中,它称为“文件数据源”。这是一种文本文件。其优点在于: (a) 它适合于任何类型的计算机,而不仅仅是使用 Windows 操作系统的计算机;(b) 其内容的拷贝或传输相对容易。

26.1.9.2. ;在 Windows 上配置 MyODBC DSN

要想在 Windows 平台上添加和配置新的 MyODBC 数据源,请使用ODBC 数据源管理器。ODBC 管理器能够更新数据源连接信息。添加了数据源时,ODBC 管理器能够更新注册信息。

要想从控制面板打开ODBC 管理器:

1.    点击“开始”,将指针指向“设置”,然后点击“控制面板”。

2.    在运行 Microsoft Windows 2000 或更新版本的计算机上,双击“管理工具”,然后双击“数据源”(ODBC)。在运行旧版本 Windows 的计算机上,双击32 位 ODBCODBC

ODBC Data Sources
              Icon

打开 ODBC 数据源管理器对话框,如下图所示:

ODBC Data Source
              Administrator Dialog

点击“帮助”以了解 ODBC 数据源管理器对话框各选项卡的详细信息。

要想在 Windows 平台上添加数据源:

1.    打开 ODBC 数据源管理器。

2.    在 ODBC 数据源管理器对话框中,点击“添加”。打开“创建新数据源”对话框。

3.    选择MySQL ODBC 3.51 驱动程序,然后点击完成打开“MySQL ODBC 3.51 驱动程序-DSN 配置对话框,如下图所示:

MySQL ODBC DSN
              Configuration Dialog

4.    在“数据源名”框中,输入打算访问的数据源的名称。它可以是你选择的任何有效名称。

5.    在“描述”框中,输入 DSn 所需的描述信息。

6.    在“主机”或“服务器名”(或 IP) 框中,输入准备访问的 MySQL 服务器主机的名称。默认情况下为localhost(本地主机)。

7.    在“数据库名”框中,输入准备用作默认数据库的 MySQL 数据库名称。

8.    在“用户”框中,输入你的 MySQL 用户名 (数据库用户 ID)。

9.    在“密码”框中输入密码。

10.在“端口”框中,如果端口不是默认端口,输入端口号。

11.在“SQL 命令”框中,可输入建立连接后自动执行的 SQL 语句。

最后,对话框与下图显示的类似:

Filled-In MySQL ODBC DSN
              Configuration Dialog

点击“OK”添加该数据源。

注释: 点击“OK”后,将打开“数据源”对话框,ODBC 管理器将更新注册信息。连接到该数据源时,你所输入的用户名和连接字符串将成为该数据源的默认连接值。

你也可以使用“测试数据源”按钮,测试你的设置是否适合于连接到服务器。该特性仅对 MyODBC 3.51 驱动程序有效。成功完成测试后,将显示下述窗口:

MyODBC Successful Connection
          Message

如果测试失败,将显示错误消息。

MyODBC Failed Connection Message

DNS 配置对话框也有一个“选项”按钮。如果选择了它,将打开下述选项对话框,显示控制驱动程序的行为。关于这些选项的含义,请参见26.1.9.4 节,“连接参数”

MyODBC Options Dialog

注释: 在“驱动程序跟踪”选项下列出的选项已被禁止 (灰色),除非你使用的是驱动 DLL 的调试版本。

要想在 Windows 平台上更改数据源:

1.    打开 ODBC 数据源管理器。点击恰当的选项卡“DSN”。

2.    选择打算更改的 MySQL 数据源,然后点击“配置”。打开“MySQL ODBC 3.51 驱动程序-DSN 配置对话框。

3.    更改适用的数据源字段,然后点击“OK”。

更改完该对话框中的信息后,ODBC 管理器将更新注册信息。

26.1.9.3. ;在 Unix 平台上配置 MyODBC DSN

Unix 平台上,可以直接在 odbc.ini 文件中配置 DSN 条目。这里给出了 1 个典型的odbc.ini 文件,在该文件中,分别将 myodbc 和 myodbc3 配置为MyODBC 2.50 和 MyODBC 3.51 的 DSN 名称:

;
;  odbc.ini 对 MyODBC 和 MyODBC 3.51 驱动程序的配置
;

[ODBC Data Sources]
myodbc      = MyODBC 2.50 Driver DSN
myodbc3     = MyODBC 3.51 Driver DSN

[myodbc]
Driver       = /usr/local/lib/libmyodbc.so
Description  = MyODBC 2.50 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

[myodbc3]
Driver       = /usr/local/lib/libmyodbc3.so
Description  = MyODBC 3.51 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

[Default]
Driver       = /usr/local/lib/libmyodbc3.so
Description  = MyODBC 3.51 Driver DSN
SERVER       = localhost
PORT         =
USER         = root
Password     =
Database     = test
OPTION       = 3
SOCKET       =

关于可提供连接参数的清单,请参见26.1.9.4 节,“连接参数”

注释: 如果你正在使用 unixODBC,可使用下述工具设置 DSN:

·         ODBCConfig GUI tool(HOWTO: ODBCConfig)

·         odbcinst

在某些情况下使用 unixODBC,可能会出现下述错误:

Data source name not found and no default driver specified(数据源名不存在,未指定默认驱动程序)

如果出现该情况,请确认ODBCINIODBCSYSINI 环境变量指向正确的 odbc.ini文件。例如,如果你的odbc.ini 文件位于目录“/usr/local/etc下,可将环境变量设为:

export ODBCINI=/usr/local/etc/odbc.ini
export ODBCSYSINI=/usr/local/etc

26.1.9.4. ;连接参数

你可以在ODBC.INI 文件的 [Data Source Name](数据源名) 部分、或通过 SQLDriverConnect() call 的InConnectionString参量为 MyODBC 指定下述参数

参数

默认值

注释

user

ODBC (on Windows)

用于链接至 MySQL 的用户名。

server

localhost

MySQL 服务器的主机名。

database

 

默认数据库。

option

0

指定 MyODBC 工作方式的选项。参见下面。

port

3306

如果服务器不是本地主机将要使用的 TCP/IP 端口。

stmt

 

连接至 MySQL 时将要执行的语句。

password

 

服务器上用户账户的密码。

socket

 

当服务器是本地主机是将要连接的 Unix 套接字文件或 Windows 命名管道。

选项参量用于通知 MyODBC:客户端不是 100% ODBC 兼容的。在 Windows 平台下,正常情况下,应通过切换连接屏幕上的复选框选择选项,但也能在选项参量中选择它们。下述选项是按照它们在 MyODBC 连接屏幕上显示的顺序排列的:

描述

1

客户端无法处理,MyODBC 返回列的实际宽度。

2

客户端无法处理,MyODBC 返回受影响行的真值。如果设置了该标志,MySQL 将返回“发现的行”取而代之。MySQL 的版本必须是 3.21.14 或更高版本,该功能才能生效。

4

c:\myodbc.log 中生成调试日志。它与将 MYSQL_DEBUG=d:t:O,c::\myodbc.log 放到 AUTOEXEC.BAT 中的效果相同(在 Unix 平台下,该文件是/tmp/myodbc.log)。

8

不为结果和参数设置任何信息报限制。

16

即使驱动程序可能会给出提示,对出现的问题不予提示。

32

允许或禁止动态光标支持。(在 MyODBC 2.50 中不允许)。

64

db_name.tbl_name.col_name 中忽略数据库名的使用。

128

强制使用 ODBC 管理器光标 (实验性)。

256

禁止使用扩展取数据 (实验性)。

512

CHAR 列填充为全列宽。

1024

SQLDescribeCol()返回完全合格的列名。

2048

使用压缩客户端/服务器协议。

4096

通知服务器忽略函数名之后和“(”之前的空格 (PowerBuilder 要求这样)。这会使所有的函数名成为关键字。

8192

用命名管道链接至运行在 NT 环境下的mysqld服务器。

16384

LONGLONG 列更改为 INT 列 (某些应用程序不能处理 LONGLONG 列)

32768

SQLTables 返回作为 Table_qualifierTable_owner 的用户(实验性)。

65536

my.cnf 的 [client][odbc] 组读取参数。

131072

增加一些额外检查 (不应需要之,但)。

262144

禁止事务。

524288

允许将查询记录到c:\myodbc.sql(/tmp/myodbc.sql) 文件。(仅在调试模式下才能启用)。

1048576

不要驱动中的结果进行缓冲处理,而应从服务器读取“mysql_use_result()”。仅对正向光标才能起作用。当你不希望缓冲处理整个结果集时,对于大表处理,该选项十分重要。

2097152

强制使用正向光标类型。在应用程序设置了默认静态/动态光标类型的情况下,如果希望驱动程序使用非缓冲结果集,那么该选项能够保证正向光标的行为。

要想选择多个选项,可将它们的值加在一起。例如,将选项设置为 12(4+8),就能获得调试功能,但没有信息包限制。

默认的myodbc3.dll 是为优化性能而编译的。如果希望调试 MyODBC 3.51(例如,启用跟踪功能),应使用myodbc3d.dll。要想安装该文件,请拷贝myodbc3d.dll,使之覆盖已安装的 myodbc3.dll 文件。一旦完成了调试操作,务必恢复至驱动 DLL 的发布版本,这是因为调试版本可能会导致性能问题。注意,在 MyODBC 3.51.07 至 3.51.11 中未包含myodbc3d.dll。如果你正在使用这些版本中的一个,应从之前的版本 (例如 3.51.06) 拷贝该 DLL 文件。

对于 MyODBC 2.50,采用了myodbc.dll 和 myodbcd.dll 取而代之。

在下面的表各中,给出了针对各种配置的推荐选项值:

配置

选项值

Microsoft Access

3

Microsoft Visual Basic

3

具有很多行的大表

2049

驱动跟踪生成 (调试模式)

4

查询日志生成 (调试模式)

524288

生成驱动跟踪和查询日志 (调试模式)

524292

具有非缓冲结果的大表

3145731

26.1.9.5. ;没有预定义 DSN 下的连接

是。通过指定DRIVER 名称字段,可使用SQLDriverConnect 连接到 MySQL 服务器。下面给出了使用 DSN-Less 连接的 MyODBC 连接字符串:

对于 MyODBC 2.50:

ConnectionString = "DRIVER={MySQL};\
                  SERVER=localhost;\
                  DATABASE=test;\
                  USER=venu;\
                  PASSWORD=venu;\
                  OPTION=3;"

对于 MyODBC 3.51:

ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};\
                  SERVER=localhost;\
                  DATABASE=test;\
                  USER=venu;\
                  PASSWORD=venu;\
                  OPTION=3;"

如果你使用的编程语言会将后跟空格的反斜杠转换为空格,最好将连接字符串指定为单个长字符串,或使用不会在其中添加空格的多个字符串串接。例如:

ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"
                  "SERVER=localhost;"
                  "DATABASE=test;"
                  "USER=venu;"
                  "PASSWORD=venu;"
                  "OPTION=3;"

关于可提供连接参数的清单,请参见26.1.9.4 节,“连接参数”

26.1.9.6. ;建立从系统 A 到系统 B 的远程连接

如果你打算使用myusermypassword 作为用户名和密码从系统 B 连接到系统 A,可参考下面给出的简单步骤。

在系统 A 上,执行下述步骤:

1.    启动 MySQL 服务器。

2.    使用 GRANT 建立用户名为myuser 的账户,该账户可使用密码 myuser 从系统 B 建立连接。

3.             GRANT ALL ON *.* to 'myuser'@'B' IDENTIFIED BY 'mypassword';

4.    GRANT 语句为用户 myuser 授予了使用密码 mypassword 从系统 B 进行连接的所有权限。要想执行该语句,必须在系统 A 上拥有根用户权限,或是具有恰当权限的另一用户。关于 MySQL 权限的更多信息,请参见5.8 节,“MySQL 用户账户管理”

在系统 B 上,执行下述步骤:

1.    使用下述连接参数配置 MyODBC DSN:

2.           DSN            = remote_test
3.           SERVER or HOST = A (or IP address of system A)
4.           DATABASE       = test (The default database or an appropriate one)
5.           USER           = myuser
6.           PASSWORD       = mypassword

关于建立 DSN-less 连接的更多信息,请参见26.1.9.5 节,“没有预定义 DSN 下的连接”

7.    使用 Ping 命令或其它方式检查是否能从系统 B 访问系统 A。如果无法访问系统 A,请检查网络或 Internet 连接,或与你的系统管理员联系。

8.    尝试使用DSN=remote_test进行连接。如果失败,请跟踪查询 MyODBC 日志,并根据日志给出的错误信息采取进一步的步骤。如果需要进一步帮助,请发送详细的电子邮件至myodbc@lists.mysql.com

在下述站点,你可以找到关于如何完成该操作的简单示例:http://www.phphelp.com/tutorial/using-myodbc-to-connect-to-a-remote-database.html.

26.1.9.7. ;获取 ODBC 跟踪文件

如果遇到与 MyODBC 有关的困难或问题,首先应使用ODBC 管理器和MyODBC 生成一份日志文件(请求来自 ODBC ADMIN 的日志时获得的日志文件)。

要想通过驱动管理器获得 ODBC 跟踪文件,可采取下述步骤:

·         打开 ODBC 数据源管理器:

1.    点击“开始”,将指针指向“设置”,然后点击“控制面板”。

2.    在运行 Microsoft Windows 2000、XP 或 2003 的计算机上,双击“管理工具”,然后双击“数据源”(ODBC),如下图所示。

ODBC Data Sources
                  Icon

在运行早期 Microsoft Windows 版本的计算机上,双击“控制面板”中的 32 位ODBC 或 ODBC。

3.    打开 ODBC 数据源管理器对话框,如下图所示:

ODBC Data Source
                  Administrator Dialog

4.    点击“帮助”以了解 ODBC 数据源管理器对话框各选项卡的详细信息。

·         启用跟踪选项 对于 Windows 和 Unix 平台,该步骤不同。

要想在 Windows 平台上启用跟踪选项:

1.    通过“ODBC 数据源管理器”对话框的“跟踪”选项卡,可对跟踪 ODBC 函数的方式进行配置。

2.    从“跟踪”选项卡激活了跟踪功能后,驱动管理器会对后续运行的所有应用程序的 ODBC 函数调用进行跟踪。

3.    激活跟踪功能前所运行应用程序的 ODBC 函数调用不会被记录。ODBC 函数调用将被记录在你指定的日志文件中。

4.    点击“现在停止跟踪”后,跟踪功能将停止。请记住,启动跟踪功能后,日志文件将不断增大,而且跟踪功能会影响所有 ODBC 应用程序的性能。

ODBC Tracing
                  Tab

要想在 Unix 平台上启用跟踪选项:

5.    在 Unix 平台上,需要在ODBC.INI 文件中明确设置跟踪选项。

使用TraceFile 和 odbc.ini 中的 Trace(跟踪) 参数打开或关闭跟踪功能,如下所示:

TraceFile  = /tmp/odbc.trace
Trace      = 1

TraceFile指明了跟踪文件的名称和完整路径,将Trace(跟踪) 设为 ONOFF。也可以使用“1”或“Yes”表示 ON,以及“0”或“No”表示 OFF。如果正在使用unixODBC 的ODBCConfig,然后遵照HOWTO-ODBCConfig中介绍的关于跟踪unixODBC 调用的指示说明。

要想生成 MyODBC 日志,可采取下述步骤:

6.    确保你所使用的是驱动程序调试 DLL(对于 MyODBC 3.51,它是myodbc3d.dll 而不是 myodbc3.dll,对于MyODBC 2.50,它是myodbcd.dll)。

最简单的方法是从 MyODBC 3.51 分发版找到myodbc3d.dll(或 myodbcd.dll),并用其覆盖myodbc3.dll(或myodbc.dll),该文件通常位于C:\windows\system32C:\winnt\system32 目录下。注意,完成测试后,你或许希望恢复旧的myodbc.dll 文件,这是因为它比 myodbc3d.dll(或myodbcd.dll) 快很多,因此,请保存原始 DLL 的备份。

7.      在“MyODBC 连接/配置”屏幕上启用“跟踪MyODBC”选项。日志将被写入文件C:\myodbc.log。当你返回上述屏幕时,如果你设置的跟踪选项未被记住,表明你正在使用的是 myodbcd.dll 驱动 (参见前面的介绍)。在 Linux 平台上,或你使用的是 DSN-Less 连接,需在连接字符串中提供“OPTION=4

8.    启动应用程序,并尝试着使其出现问题。然后检查 MyODBC 跟踪文件,找出可能出错的地方。

如果发现某些事项出错,请发送电子邮件至myodbc@lists.mysql.com(或support@mysql.com,如果有与MySQL AB 签订的支持合同),简要描述出现的问题,并提供下述额外信息:

o        MyODBC 版本

o        ODBC 驱动管理器的类型和版本

o        MySQL 服务器的版本

o        驱动管理器的 ODBC 跟踪

o        来自 MyODBC 驱动的 MyODBC 日志文件

o        简单的可复制示例

请记住,你提供给我们的信息越多,我们更正问题的机会就越大。

此外,在提供缺陷信息前,请检查 MyODBC 邮件列表 (http://lists.mysql.com/)。

26.1.9.8. ;用 MyODBC 测试的应用程序

使用下述应用程序测试了 MyODBC:

如果你知道能够与 MyODBC 一起工作的其他应用程序,请以电子邮件的方式指明它:myodbc@lists.mysql.com

26.1.9.9. ;已知的能与 MyODBC 一起工作的程序

大多数程序均能与 MyODBC 一起工作,对上面所列的每一程序,我们自己进行了测试,或得到用户的确认。很多介绍中均给出了你可能会遇到问题的描述。

·         程序

注释

·         Access

要想使 Access 工作:

o        如果你正在使用 Access 2000,应从下述地址获取并安装最新的 (2.6 版或更高)Microsoft MDAC(Microsoft 数据访问组件),http://www.microsoft.com/data/。它更正了 Access 在将数据导出至 MySQL 时存在的一个缺陷,未指定表名和列名。另一种解决该缺陷的方法是,升级到 MyODBC 2.50.33 和 MySQL 3.23.x,它们共同提供了避免该问题的一种方式。

此外,你还应获取并应用 Microsoft Jet 4.0 Service Pack 5 (SP5),可在下述地址找到它:http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114。它修正了某些情况下在 Access 中列被标注为“#DELETED#的问题。

注释: 如果你正使用 MySQL 3.22,必须安装 MDAC 补丁,并使用 MyODBC 2.50.32 或 2.50.34 或更高版本以解决该问题。

o        对于所有版本的 Access,应启用“MyODBC 返回匹配行”选项。对于 Access 2.0,还应额外启用“模拟 ODBC 1.0选项

o        在希望能够更新的所有表中,均应有时间戳。为了获得最大的可移植性,在列声明中不要使用长度规范。也就是说,应使用TIMESTAMP,而不是 TIMESTAMP(n), n < 14。

o        在表中应有 1 个主键。如不然,新的或更新的行可能会显示为“#DELETED#”。

o        仅应使用DOUBLE 浮点字段。与单精度浮点进行比较时,Access 将失败。其征兆是新的或更新的行可能会显示为“#DELETED#”,或无法找到或更新行。

o        如果你正使用 MyODBC 来链接到有 BIGINT 列的表,结果会显示为“#DELETED”。排除它的解决方案是:

§         有 1 个以TIMESTAMP 作为数据类型的虚拟列。

§         在“ODBC DSN 管理器”的连接对话框中选择“将 BIGINT 列更改为 INT”选项。

§         删除与 Access 的表链接,并重新创建它。

旧记录仍将显示为“#DELETED#”,但新增/更新的记录会恰当显示。

o        添加了 TIMESTAMP 列后,另一位用户更改了数据,如果错误依旧出现,下述技巧或许有所帮助:

不要使用表数据表视图。取而代之的是,从你希望使用的表创建一个表单,并使用表单数据表视图。应将TIMESTAM 列的 DefaultValue 属性设置为 NOW()。在视图中隐藏TIMESTAMP 列或许是个好主意,这样就不会使你的用户感到迷惑。

o        在某些情况下,Access 可能会生成 MySQL 无法理解的 SQL 语句。可通过在 Access 菜单中选择“Query|SQLSpecific|Pass-Through”来更正该问题。

o        在 NT 平台上,Access 会将BLOB列通报为OLE OBJECTS(OLE 对象)。如果你打算用MEMO 列取而代之,应使用 ALTER TABLE 将 BLOB 列更改为 TEXT。

o        Access 无法在任何时候均恰当处理DATE 列。如果遇到这类问题,请将列更改为DATETIME

o        如果在 Access 中存在定义为BYTE 的列,Access 会视图将其导出为TINYINT 而不是 TINYINT UNSIGNED。如果列中的值大于 127,将出现问题。

·         ADO

使用 ADO API 和 MyODBC 进行编码时,需要注意某些不被 MySQL 服务器支持的默认属性。例如,对于RecordCount 属性,如果将 CursorLocation 属性用作 adUseServer,将返回结果-1要想获得正确的值,需要将该属性设置为adUseClient,如下面给出的 VB 代码示例所示:

Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long
 
myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount
 
myrs.Close
myconn.Close

另一种处理方式是,对类似查询使用SELECT COUNT(*) 语句以获取正确的行计数。

·         主动服务器页 (ASP)

应选择“返回匹配行”选项。

·         BDE 应用程序

要想使这类应用程序工作,应选择“不优化列宽度并返回匹配行”选项。

·         Borland Builder 4

开始查询时,可使用Active 属性或 Open 方法。注意,Active 将通过自动发出SELECT * FROM ...查询开始。如果表很大,这不是什么好事。

·         ColdFusion(在 Unix 平台上)

下述信息取自 ColdFusion 文档:

使用下述信息来配置用于 Linux 的 ColdFusion 服务器,以便使用针对 MySQL 数据源的 unixODBC 驱动和 MyODBC。Allaire 已证明,MyODBC 2.50.26 能够与 MySQL 3.22.27 以及用于 Linux 的 ColdFusion 一起工作。(任何较新的版本也应能正确工作)。你可以在网站http://dev.mysql.com/downloads/connector/odbc/上下载 MyODBC。

通过 ColdFusion 4.5.1 版,可以使用“ColdFusion 管理器”来添加 MySQL 数据源。但是,驱动程序未包含在 ColdFusion 4.5.1 版中。在 MySQL 驱动程序出现在 ODBC 数据源下拉列表之前,必须创建 MyODBC 驱动程序,并将其拷贝到/opt/coldfusion/lib/libmyodbc.so

在 Contrib 目录下包含程序mydsn-xxx.zip,使用它,对于Coldfusion 应用程序,可创建并删除用于 MyODBC 驱动的 DSN 注册文件。

·         DataJunction

应对其进行更改,使之输出VARCHAR 而不是 ENUM,因为其导出 ENUM 的方式会造成 MySQL 问题。

·         Excel

工作。一些提示:

o        如果遇到日期方面的问题,请使用CONCAT() 函数,将其选择为字符串。例如:

o                     SELECT CONCAT(rise_time), CONCAT(set_time)
o                       FROM sunrise_sunset;

采用该方式以字符串提取的值应能被 Excel97 正确识别为时间值。

在本例中,CONCAT() 的目的是让 ODBC 认为列是字符串类型如果没有CONCAT(),ODBC 会将列视为时间类型,Excel 无法理解它。

注意,Excel 存在 1 个缺陷,这是因为它会自动将字符串转换为时间。如果源是文本文件,不存在问题,但当源是通报各列准确类型的 ODBC 连接时,将出现问题。

·         Word

要想将数据从 MySQL 提取到 Word/Excel 文档,需要使用 MyODBC 驱动程序以及“Microsoft 查询帮助”插件。

例如,用含有两列文本的表创建 1 个数据库:

o        使用mysql客户端命令行工具插入行。

o        使用 ODBC 管理器创建 1 个 DSN 文件,例如,针对刚创建数据库的“my”。

o        打开 Word 应用程序。

o        创建 1 个新的空白文档。

o        在数据库工具栏上,按“插入数据库”按钮。

o        按“获取数据”按钮。

o        在“获取数据”屏幕右侧,按“Ms Query”按钮。

o        在“Ms Query”中使用“my DSN”文件创建 1 个新数据源。

o        选择新查询。

o        选择打算使用的列。

o        如果愿意,创建 1 个过滤器。

o        如果愿意,创建 1 个分类。

o        选择“将数据返回到Microsoft Word”。

o        点击“完成”。

o        点击“插入数据”并选择记录。

o        点击 OK,在你的 Word 文档中将看到插入的行。

·         odbcadmin

ODBC 的测试程序。

·         Delphi

必须使用 BDE 3.2 版或更新的版本。连接到 MySQL 时,选择“不优化列宽度”选项。

此外,这里给出了一些可能有用的 Delphi 代码,这些代码可设置为 MyODBC 设置 ODBC 条目和 BDE 条目。BDE 条目要求用到“BDE 别名编辑器”,它位于靠近你的“Delphi Super Page”上,可自由拖动。(下述内容由 Bryan Brunton <bryan@flesherfab.com>提供):

fReg:= TRegistry.Create;
fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
fReg.WriteString('Database', 'Documents');
fReg.WriteString('Description', ' ');
fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
fReg.WriteString('Flag', '1');
fReg.WriteString('Password', '');
fReg.WriteString('Port', ' ');
fReg.WriteString('Server', 'xmark');
fReg.WriteString('User', 'winuser');
fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
fReg.WriteString('DocumentsFab', 'MySQL');
fReg.CloseKey;
fReg.Free;
 
Memo1.Lines.Add('DATABASE NAME=');
Memo1.Lines.Add('USER NAME=');
Memo1.Lines.Add('ODBC DSN=DocumentsFab');
Memo1.Lines.Add('OPEN MODE=READ/WRITE');
Memo1.Lines.Add('BATCH COUNT=200');
Memo1.Lines.Add('LANGDRIVER=');
Memo1.Lines.Add('MAX ROWS=-1');
Memo1.Lines.Add('SCHEMA CACHE DIR=');
Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
Memo1.Lines.Add('SQLQRYMODE=');
Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
Memo1.Lines.Add('ENABLE BCD=FALSE');
Memo1.Lines.Add('ROWSET SIZE=20');
Memo1.Lines.Add('BLOBS TO CACHE=64');
Memo1.Lines.Add('BLOB SIZE=32');
 
AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);

·         C++ Builder

用 BDE 3.0 版进行了测试。目前已知的唯一问题是,更改表方案时,查询字段不更新。然而,BDE 看上去不会识别主键,它仅是名为 PRIMARY 的索引,尽管这谈不上是问题。

·         Vision

应选择“返回匹配行”选项。

·         Visual Basic

要想更新表,必须为表定义主键。

带有 ADO 的 Visual Basic 不能处理大整数。这意味着某些查询 (如SHOW PROCESSLIST 等) 不会正确工作。更正方法是,在 ODBC 连接字符串中使用OPTION=16384,或在MyODBC 连接屏幕上选择“将BIGINT 列更改为 INT”选项。或许,你也希望选择“返回匹配行”选项。

·         VisualInterDev

如果在结果中有BIGINT,可能会出现错误[Microsoft][ODBC Driver Manager] 驱动程序不支持该参数。请MyODBC 连接屏幕上选择“将BIGINT 列更改为 INT”选项。

·         Visual Objects

应选择“不优化列宽度”选项。

·         MS Visio Enterprise 2000

通过 MyODBC(2.50.37 或更高版本),通过连接 MS Vision Enterprise 2000 和 MySQL,并使用 Visio 的逆向工程师功能,我们建立了数据库模型,使用它来检索关于 DB 的信息 (Visio 显示了所有的列定义、主键、索引等)。此外,我们还通过指定 Visio 中的新表进行了测试,并通过 MyODBC 将其导出至 MySQL。

26.1.10. ;与 MyODBC 连接相关的事宜

在本节中,回答了与 MyODBC 连接有关的问题。

26.1.10.1. ;配置 MyODBC DSN 时,出现不能加载翻译器或设置库错误

更多信息,请参见MS 知识库文章 (Q260558)。此外,请确认在你的系统目录下有最新的有效ctl3d32.dll 文件。

26.1.10.2. ;连接时,出现拒绝访问错误

请参见5.7.8 节,“拒绝访问错误的原因

26.1.10.3. INFO:关于 ODBC 连接池

关于连接池方面的信息,请参阅下述文档: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q169470

26.1.11. MyODBC 和 Microsoft Access

在本节中,回答了与 MyODBC 和 Microsoft Access 有关的问题。

26.1.11.1. ;如何设置 Microsoft Access,使之能够与使用 MyODBC 的 MySQL 一起工作?

要想使 Microsoft Access 能够与 MyODBC 一起工作,在你的客户端 PC 上必须完成下述操作。

1.    如果你正在使用 Access 2000,应从下述地址获取并安装最新的 (2.6 版或更高)Microsoft MDAC(Microsoft 数据访问组件),http://www.microsoft.com/data/。它更正了 Access 在将数据导出至 MySQL 时存在的一个缺陷,未指定表名和列名。另一种解决该缺陷的方法是,升级到 MyODBC 2.50.33 和 MySQL 3.23.x,它们共同提供了避免该问题的一种方式。

此外,你还应获取并应用 Microsoft Jet 4.0 Service Pack 5 (SP5),可在下述地址找到它:http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114。它修正了某些情况下在 Access 中列被标注为“#DELETED#的问题。

注释: 如果你正使用 MySQL 3.22,必须安装 MDAC 补丁,并使用 MyODBC 2.50.32 或 2.50.34 或更高版本以解决该问题。

2.    安装最新版 MySQL,http://dev.mysql.com/downloads/

3.    安装最新版 MyODBC 3.51 或 2.50,http://dev.mysql.com/downloads/connector/odbc/

4.    对于所有版本的 Access,应启用“MyODBC 返回匹配行”选项。

5.    通过 MyODBC,将 Access 用作 MySQL 服务器的前端程序。

26.1.11.2. ;如何将表或查询从 Access 导出到 MySQL?

除非已安装了 MyODBC,否则不能将表或查询导出到 MySQL。

要想将表从 Access 导入 MySQL,请遵循下述说明:

1.    打开 Access 数据库或 Access 项目时,出现“数据库”窗口。其中显示了用于创建新数据库对象和打开已有对象的快捷方式。

Access Database

2.    点击打算导出的表名或查询名,然后在“文件”菜单中选择“导出”。

3.    在“导出对象类型对象名”对话框中,在“另存为类型”框中,选择ODBC 数据库 (),如下图所示

Selecting an ODBC Database

4.    在“导出”对话框中,输入文件名 (或使用建议的文件名),然后选择 OK。

5.    显示“选择数据源”对话框,其中列出了为计算机上已安装的各 ODBC 驱动定义的数据源。点击“文件数据源”或“机器数据源”选项卡,然后双击打算导出至的 MyODBC 或 MyODBC 3.51 数据源。关于为 MyODBC 定义新数据源的方法,请参见26.1.9.2 节,“在 Windows 上配置 MyODBC DSN”

Microsoft Access 通过该数据源连接至 MySQL 服务器,并导出新的表和/或数据。

26.1.11.3. ;如何导入 MySQL 数据库表或将其链接到 Access?

除非已安装了 MyODBC,否则不能将表或查询导出到 MySQL 数据库。

要想将表从 MySQL 导入或链接到 Access,请采取下述步骤:

1.    打开数据库,或切换到“数据库”窗口以打开数据库。

2.    要想导入表,在“文件”菜单上,将鼠标指针指向“获取外部数据”,然后点击“导入”。要想链接表,在“文件”菜单上,将鼠标指针指向“获取外部数据”,然后点击“链接表”。

3.    在“导入”(或“链接”) 对话框中,在“文件类型”框中选择“ODBC Databases ()”。在“选择数据源”对话框中,列出了定义的数据源。显示“选择数据源”对话框,其中列出了为安装在计算机上的任何 ODBC 驱动定义的数据源。点击“文件数据源”或“机器数据源”选项卡,然后双击打算导出至的 MyODBC 或 MyODBC 3.51 数据源。关于为 MyODBC 或 MyODBC 3.51 驱动定义新数据源的方法,请参见26.1.9.2 节,“在 Windows 上配置 MyODBC DSN”

4.    如果所选的数据源要求登录,请输入登录 ID 和密码 (可能还需要额外信息),然后点击 OK。

5.    Microsoft Access 通过 ODBC 数据源连接到 MySQL 服务器,并显示可导入或链接的表清单。

6.    点击希望导入或链接的每个表,然后点击 OK。如果你正在链接 1 个表,但它没有唯一识别各条记录的索引,Microsoft Access 将显示链接表中的字段列表。点击能唯一标识各记录的字段或字段组合,然后点击 OK。

26.1.11.4. ;链接表的结构或位置已改变,我能看到链接表中的这些变化吗?

是。当链接表的结构或位置发生变化时,可采取下述步骤查看或刷新链接。“链接表管理器”列出了当前链接的所有表的路径。

要想查看或刷新链接:

1.    打开包含表链接的数据库。

2.    在“工具”菜单上,指向“加载项”(在 Access 2000 或更新版本中为“数据库实用工具”),然后点击“链接表管理器”。

3.    选中打算刷新链接的表的复选框。

4.    点击 OK,刷新链接。

Microsoft Access 将确认成功的刷新操作,或者,如果未找到表,将显示“选择<table name>新位置”对话框,在该对话框中,可指定表的新位置。如果你所选择的数个表已被移至你所指定的新位置,链接表管理器将针对所有所选的表搜索该位置,并一次性地更新所有链接。

要想更改链接表集合的路径:

1.    打开包含表链接的数据库。

2.    在“工具”菜单上,指向“加载项”(在 Access 2000 或更新版本中为“数据库实用工具”),然后点击“链接表管理器”。

3.    选中“对新位置始终提示”复选框。

4.    选中打算更改链接的表的复选框,然后点击 OK。

5.    在“选择<table name>;新位置”对话框中,指定新位置,点击“打开”,然后点击 OK。

26.1.11.5. ;当我在链接表中插入记录或更新其中的记录时,遇到“#DELETED#”

如果在 Access 中插入或更新的记录显示为“#DELETED#”:

·         如果你正在使用 Access 2000,应从下述地址获取并安装最新的 (2.6 版或更高)Microsoft MDAC(Microsoft 数据访问组件),http://www.microsoft.com/data/。它更正了 Access 在将数据导出至 MySQL 时存在的一个缺陷,未指定表名和列名。另一种解决该缺陷的方法是,升级到 MyODBC 2.50.33 和 MySQL 3.23.x,它们共同提供了避免该问题的一种方式。

此外,你还应获取并应用 Microsoft Jet 4.0 Service Pack 5 (SP5),可在下述地址找到它:http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114。它修正了某些情况下在 Access 中列被标注为“#DELETED#的问题。

注释: 如果你正使用 MySQL 3.22,必须安装 MDAC 补丁,并使用 MyODBC 2.50.32 或 2.50.34 或更高版本以解决该问题。

·         对于所有版本的 Access,应启用“MyODBC 返回匹配行”选项。对于 Access 2.0,还应额外启用“模拟 ODBC 1.0选项

·         在希望能够更新的所有表中,均应有时间戳。为了获得最大的可移植性,在列声明中不要使用长度规范。也就是说,应使用TIMESTAMP,而不是 TIMESTAMP(n), n < 14。

·         在表中应有 1 个主键。如不然,新的或更新的行可能会显示为“#DELETED#”。

·         仅应使用DOUBLE 浮点字段。与单精度浮点进行比较时,Access 将失败。其征兆是新的或更新的行可能会显示为“#DELETED#”,或无法找到或更新行。

·         如果你正使用 MyODBC 来链接到有 BIGINT 列的表,结果会显示为“#DELETED”。排除它的解决方案是:

o        有 1 个以TIMESTAMP 作为数据类型的虚拟列。

o        在“ODBC DSN 管理器”的连接对话框中选择“将BIGINT 列更改为 INT”选项。

o        删除与 Access 的表链接,并重新创建它。

旧记录仍将显示为“#DELETED#”,但新增/更新的记录会恰当显示。

26.1.11.6. ;如何处理写冲突或行位置错误?

如果看到下述错误,请在“DSN 配置”对话框中选择“返回匹配行”选项,或将连接参数指定为“OPTION=2
写冲突。另一用户更改了你的数据。
 
无法找到需更新行的位置。自上次读取操作以来,某些值可能已被改变。

26.1.11.7. ;无论何时,当我从 Access 97 导出表时,出现陌生的语法错误

对于 Access 97,这是件奇怪的事宜,但在 Access 2000 或 2002 中并未出现。将 MyODBC 升级至 MyODBC 3.51.02 或以上,可以克服该问题。

26.1.11.8. ;编辑记录时,Access 返回“另一用户更改了你修改的记录”

对于某些程序,可能会出现该错误: 另一用户更改了你所修改的记录。在大多数情况下,可通过下述措施解决该问题:

·         如果主键不存在,为表添加 1 个主键。

·         如果时间戳不存在,添加 1 个时间戳列。

·         仅应使用DOUBLE 浮点字段。与单精度浮点值比较时,某些程序会出错。

如果这些措施未能解决问题,首先应从 ODBC 管理器生成 1 个日志文件 (请求来自 ODBC ADMIN 的日志时获得的日志文件),以及 1 个 MyODBC 日志,使用它们找出出错的原因。具体介绍,请参见26.1.9.7 节,“获取 ODBC 跟踪文件”

26.1.11.9. ;如何在 Access 中俘获 ODBC 登录错误消息?

请阅读“如何在 Access 中俘获 ODBC 登录错误消息”,http://support.microsoft.com/support/kb/articles/Q124/9/01.asp?LN=EN-US&SD=gn&FR=0%3CP%3E

26.1.11.10. ;如何优化 Access 与 MyODBC 一起工作的性能?

26.1.11.11. ;我有很长的表,MyODBC 访问这些 Access 表的最佳配置是什么?

如果在 Access 中有很大 (长) 的表,可能需要相当长的时间才能打开。或者,也可能是虚拟内存较低的情况下运行,最终导致 ODBC 查询失败错误,并无法打开表。为了解决该问题,可选择下述选项:

·         返回匹配行 (2)

·         允许 BIG 结果 (8)

这样可将值增加到 10(OPTION=10)。

26.1.11.12. ;如何为 ODBC 连接设置 QueryTimeout 值?

请参阅“为 ODBC 连接设置QueryTimeout 值”,http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B153756

26.1.11.13. INFO:用于 Access 和 MySQL 间导入/导出的工具

关于可用工具列表,请参阅http://www.mysql.com/portal/software/convertors/一节。

26.1.12. MyODBC 和 Microsoft VBA 及 ASP

在本节中,回答了与 Microsoft Visual Basic(ADO, DAO & RDO) 和 ASP 一起使用 MyODBC 有关的问题。

26.1.12.1. ;为什么 SELECT COUNT(*) FROM tbl_name 返回错误?

这是因为COUNT(*) 表达式返回了1 个BIGINT,ADO 不理解这个大值的含义。选择“将BIGINT 列更改为 INT选项 (选项值 16384)。

26.1.12.2. ;无论何时,当我使用 AppendChunk() 或 GetChunk() ADO 方法时,遇到错误“多步操作导致错误,请检查每个状态值”

将光标位置指定为 adUseServer 时,ADO 的GetChunk()AppendChunk()方法不能按预期的方式工作。从另一方面上讲,可使用 adUseClient 克服该问题。

http://www.dwam.net/iishelp/ado/docs/adomth02_4.htm上给出了一个简单示例。

26.1.12.3. ;在 ADO 中如何发现受特定 SQL 语句影响的总行数?

在 ADO 执行方法中使用RecordsAffected 属性。关于使用执行方法的更多信息,请参见http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcnnexecute.asp

26.1.12.4. ;在 Visual Basic 中如何处理 Blob 数据?

下面给出了 Mike Hillyer(m.hillyer@telusplanet.net) 写的一篇好文章,其中解释了如何在 ADO 中通过 MyODBC 插入数据和/或从 Blob 列获取数据的方法。MySQL BLOB 列和 Visual Basic 6

26.1.12.5. ;如何将 Visual Basic 的数据类型映射到 MySQL 类型?

下面给出了 Mike Hillyer(m.hillyer@telusplanet.net) 的另一篇好文章。如何将 Visual basic 数据类型映射为 MySQL 类型

26.1.12.6. ;示例:VB 与 ADO、DAO 和 RDO

下面给出了 ADO、DAO 和 RDO 与 VB 一起使用的用法示例:

·         ADO 示例: 26.1.19 节,“MyODBC 与 VB:ADO、DAO 和 RDO”

·         DAO 示例: 26.1.19 节,“MyODBC 与 VB:ADO、DAO 和 RDO”

·         RDO 示例: 26.1.19 节,“MyODBC 与 VB:ADO、DAO 和 RDO”

如果你有其他好的例子,或关于 ADO/DAO/RDO 的基本知识,请将详情发送至myodbc@lists.mysql.com

26.1.12.7. ASP 和 MySQL 以及 MyODBC

关于如何使用 MyODBC 通过 ASP 访问 MySQL 的更多信息,请参阅下述文章:

·         使用 MyODBC 通过 ASP 访问你的 MySQL 数据库

·         ASP and MySQL at DWAM.NT

http://support.microsoft.com/default.aspx?scid=/Support/ActiveServer/faq/data/adofaq.asp中,给出了关于 ASP 的常见问题清单。

26.1.12.8. INFO:关于 ActiveX 数据对象 (ADO) 的常见问题

更多信息,请参见ActiveX 数据对象 (ADO) 常见问题

26.1.13. MyODBC 和第三方 ODBC 工具

在本节中,回答了与 MyODBC 和各种 ODBC 相关工具有关的问题,如 Microsoft Word、Excel 和 ColdFusion。

26.1.13.1. ;如何将数据从 MySQL 提取到 MS-Word/Excel 文档?

要想将数据从 MySQL 提取到 Word/Excel 文档,需要使用 MyODBC 驱动程序以及“Microsoft 查询帮助”插件。

例如,用含有两列文本的表创建 1 个数据库:

·         使用mysql客户端命令行工具插入行。

·         使用 ODBC 管理器创建 1 个 DSN 文件,例如,针对刚创建数据库的“my”。

·         打开 Word 应用程序。

·         创建 1 个新的空白文档。

·         在数据库工具栏上,按“插入数据库”按钮。

·         按“获取数据”按钮。

·         在“获取数据”屏幕右侧,按“Ms Query”按钮。

·         在“Ms Query”中使用“my DSN”文件创建 1 个新数据源。

·         选择新查询。

·         选择打算使用的列。

·         如果愿意,创建 1 个过滤器。

·         如果愿意,创建 1 个分类。

·         选择“将数据返回到Microsoft Word”。

·         点击“完成”。

·         点击“插入数据”并选择记录。

·         点击 OK,在你的 Word 文档中将看到插入的行。

26.1.13.2. ;使用 MyODBC 将表从 MS DTS 导出到 MySQL 时出现语法错误

这与当表由 TEXT 或 VARCHAR 数据类型构成时 Access 97 遇到的问题类似。通过将 MyODBC 驱动升级到 3.51.02 或更高版本,即可排除该错误。

26.1.13.3. 如何在 Solaris 平台上配置 MySQL+MyODBC+unixODBC+ColdFusion

请参见MySQL ColdFusion unixODBC MyODBC 和 Solaris:如何成功

26.1.14. MyODBC 通用功能

在本节中,回答了与 MyODBC 一般功能有关的问题。

26.1.14.1. ;如何在 ODBC 中获取 AUTO_INCREMENT 列的值

一个常见问题是,如何获取从 INSERT 语句自动生成的 ID 的值。使用 ODBC,你可以作与以下示例类似的任何事 (假定“auto”为AUTO_INCREMENT 字段):

INSERT INTO tbl (auto,text) VALUES(NULL,'text');
SELECT LAST_INSERT_ID();

或者,如果你仅打算将 ID 插入到另一表中,你可以:

INSERT INTO tbl (auto,text) VALUES(NULL,'text');
INSERT INTO tbl2 (id,text) VALUES(LAST_INSERT_ID(),'text');

请参见25.2.13.3 节,“如何获得上次插入行的唯一 ID”

为了使某些 ODBC 应用程序 (至少是 Delphi 和 Access) 获得更好的性能,可使用下述查询来找到新插入的行:

SELECT * FROM tbl WHERE auto IS NULL;

26.1.14.2. MyODBC 支持动态光标类型吗?

是。MyODBC 3.51 支持动态光标类型以及正向和静态特性。

由于性能方面的原因,在默认情况下,驱动程序不支持该特性。你可以启用该特性,方法是,将连接选项标志指定为“OPTION=32,或在DSN 配置中选中“启用动态光标”选项。

26.1.14.3. ;导致事务无法启用错误的原因是什么?

当应用程序发出事务调用,但底层 MySQL 服务器不支持事务或禁止事务时,驱动程序将返回该错误。

为了避免该问题,必须使用启用了InnoDBBDB 存储引擎 (或两者) 的服务器,并使用这类表。从 4.0 版以后,默认情况下,MySQL 服务器均支持InnoDB。在 BDB 可用的平台上,MySQL-Max 服务器也支持BDB

此外,如果你的服务器支持事务表类型 (InnoDB 和 BDB),请确保在 DSN 配置中未设置“禁止事务”选项。

26.1.14.4. ;导致无法找到光标错误的原因是什么?

这是因为应用程序正在使用旧的 MyODBC 2.50 版本,不能通过 SQLSetCursorName 明确设置光标名称。更正它的方法是升级到 MyODBC 3.51 版。

26.1.14.5. ;我能与 MyODBC 3.51 一起使用 MyODBC 2.50 应用程序吗?

是。如果你发现不能与 MyODBC 3.51 一起工作,但能与 MyODBC 2.50 一起工作的任何事项,请发送电子邮件至myodbc@lists.mysql.com

26.1.14.6. ;我能使用 MyODBC 从。NET 环境访问 MySQL 吗?

是。你可以使用odbc.net,通过 MyODBC 连接到 MySQL。这里给出了一些从 VC.NET 和 VB.NET 连接到 MySQL 的基本示例。

·         请参见26.1.20.1 节,“ODBC.NET: CSHARP(C#)”

·         请参见26.1.20.2 节,“ODBC.NET: VB”

这里给出了Venu(MyODBC 开发人员) 撰写的另一篇好文章http://www.mysql.com/newsletter/2002-07/a0000000035.html,其中,给出了所有的 MySQL .NET 接口以及一些有用的例子。

注意: 在与 MyODBC 一起使用 ODBC.NET 的过程中,在获取空字符串的同时 (长度为 0),将给出 SQL_NO_DATA 异常。从站点http://support.microsoft.com/default.aspx?scid=kb;EN-US;q319243,可获取针对它的补丁。

26.1.14.7. MyODBC 的性能为什么很差,对于相对较小的查询也会导致大量的磁盘动作?

MyODBC 比其他 ODBC 驱动程序快很多。缓慢可能是因未使用下述选项造成的:

·         打开“ODBC 跟踪”选项。遵循这里给出的指示说明,交叉检查是否未启用该选项。

ODBC Tracing
              Tab

如上图所示,“ODBC 数据源管理器”“跟踪”选项卡的“何时跟踪”选项应始终指向“现在开始跟踪”,而不是“现在停止跟踪”。

·         使用了驱动程序的调试版本。如果你正在使用驱动 DLL 的调试版本,也会使查询处理变慢。你可以执行交叉检查,通过驱动 DLL 属性 (在系统目录下,右击驱动 DLL 并点击“属性”) 的“注释”区,检查 DLL 是否是调试版或发布版,如下图所示:

DLL Properties Dialog

·         启用了“驱动跟踪和查询日志”。即使你打算使用驱动程序的调试版 (在生产环境下总应使用发布版),也应确保禁止了“驱动跟踪和查询日志”选项 (OPTION=4,524288),如下图所示:

MyODBC Options Dialog

26.1.15. ;基本的 MyODBC 应用步骤

从 MyODBC 应用程序执行的与 MySQL 服务器的交互包含以下操作:

·         配置 MyODBC DSN。

·         连接到 MySQL 服务器。

·         初始化操作。

·         执行 SQL 语句。

·         检索结果。

·         执行事务。

·         断开与服务器的连接。

大多数应用程序均使用了这些步骤的某些变体。在下图中,给出了基本的应用步骤:

MyODBC Programming Flowchart

26.1.16. MyODBC API 引用

在本节中,概要介绍了按功能分类的 ODBC 子程序。

关于全部 ODBC API 参考,请参见 ODBC 程序员参考,http://msdn.microsoft.com/library/en-us/odbc/htm/odbcabout_this_manual.asp

应用程序可以调用SQLGetInfo 函数来获得关于MyODBC 的一致性信息。为了获得驱动程序对特定函数的支持信息,应用程序可调用SQLGetFunctions

注释: 为了向后兼容,MyODBC 3.51 驱动程序支持所有已不使用的函数。

在下面的表各中,按任务分组列出了 MyODBC API 调用:

连接到数据源:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLAllocHandle

No

Yes

ISO 92

获取环境、连接、语句或描述符句柄。

SQLConnect

Yes

Yes

ISO 92

按数据源名、用户 ID 和密码连接到特定驱动程序。

SQLDriverConnect

Yes

Yes

ODBC

通过连接字符串,或驱动管理器和驱动显示对话框发出的请求,连接到特定驱动程序。

SQLAllocEnv

Yes

Yes

Deprecated

获得驱动程序分配的环境句柄。

SQLAllocConnect

Yes

Yes

Deprecated

获取连接句柄。

获取关于驱动程序和数据源的信息:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLDataSources

No

No

ISO 92

返回可用数据源的列表,由驱动管理器处理。

SQLDrivers

No

No

ODBC

返回已安装驱动程序和器属性的列表,由驱动管理器处理。

SQLGetInfo

Yes

Yes

ISO 92

返回关于特定驱动程序和数据源的信息。

SQLGetFunctions

Yes

Yes

ISO 92

返回支持的驱动函数。

SQLGetTypeInfo

Yes

Yes

ISO 92

返回关于所支持数据类型的信息。

设置并检索驱动属性:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLSetConnectAttr

No

Yes

ISO 92

设置连接属性。

SQLGetConnectAttr

No

Yes

ISO 92

返回连接属性的值。

SQLSetConnectOption

Yes

Yes

Deprecated

设置连接选项。

SQLGetConnectOption

Yes

Yes

Deprecated

返回连接选项的值。

SQLSetEnvAttr

No

Yes

ISO 92

设置环境属性。

SQLGetEnvAttr

No

Yes

ISO 92

返回环境属性的值。

SQLSetStmtAttr

No

Yes

ISO 92

设置语句属性。

SQLGetStmtAttr

No

Yes

ISO 92

返回语句属性的值。

SQLSetStmtOption

Yes

Yes

Deprecated

设置语句选项。

SQLGetStmtOption

Yes

Yes

Deprecated

返回语句选项的值。

准备 SQL 请求:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLAllocStmt

Yes

Yes

Deprecated

分配语句句柄。

SQLPrepare

Yes

Yes

ISO 92

准备随后执行的 SQL 语句。

SQLBindParameter

Yes

Yes

ODBC

为 SQL 语句中的参数分配存储器。

SQLGetCursorName

Yes

Yes

ISO 92

返回与语句句柄相关的光标名。

SQLSetCursorName

Yes

Yes

ISO 92

指定光标名。

SQLSetScrollOptions

Yes

Yes

ODBC

设置控制光标行为的选项。

提交请求:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLExecute

Yes

Yes

ISO 92

执行准备好的语句。

SQLExecDirect

Yes

Yes

ISO 92

执行语句。

SQLNativeSql

Yes

Yes

ODBC

返回由驱动程序翻译的 SQL 语句的文本。

SQLDescribeParam

Yes

Yes

ODBC

返回语句中特定参数的描述。

SQLNumParams

Yes

Yes

ISO 92

返回语句中的参数数目。

SQLParamData

Yes

Yes

ISO 92

SQLPutData 一起使用,以便在执行时提供参数。(对于长数据值很有用)。

SQLPutData

Yes

Yes

ISO 92

发送某一参数数据值的部分或全部。(对于长数据值很有用)。

检索结果以及关于结果的信息:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLRowCount

Yes

Yes

ISO 92

返回插入、更新或删除请求影响的行数。

SQLNumResultCols

Yes

Yes

ISO 92

返回结果集中的列数。

SQLDescribeCol

Yes

Yes

ISO 92

描述结果集中的列。

SQLColAttribute

No

Yes

ISO 92

描述结果集中的某 1 列的属性。

SQLColAttributes

Yes

Yes

Deprecated

描述结果集中的某 1 列的多个属性。

SQLFetch

Yes

Yes

ISO 92

返回多个结果行。

SQLFetchScroll

No

Yes

ISO 92

返回可滚动结果行。

SQLExtendedFetch

Yes

Yes

Deprecated

返回可滚动结果行。

SQLSetPos

Yes

Yes

ODBC

将光标定为在获取的数据块中,允许应用程序更新行集合中的数据,或更新或删除结果集中的数据。

SQLBulkOperations

No

Yes

ODBC

执行批量插入和批量书签操作,包括更新、删除和按书签获取。

检索错误和诊断信息:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLError

Yes

Yes

Deprecated

返回额外的错误或状态信息。

SQLGetDiagField

Yes

Yes

ISO 92

返回额外的诊断信息 (诊断性数据结构的单个字段)。

SQLGetDiagRec

Yes

Yes

ISO 92

返回额外的诊断信息 (诊断性数据结构的多个字段)。

获取关于数据源的系统表 (目录函数) 条目的信息:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLColumnPrivileges

Yes

Yes

ODBC

返回关于一个或多个表的列和相关属性的列表。

SQLColumns

Yes

Yes

X/Open

返回指定表中列名的列表。

SQLForeignKeys

Yes

Yes

ODBC

在指定表中如果存在外键,返回构成外键的列名列表。

SQLPrimaryKeys

Yes

Yes

ODBC

返回构成某 1 表的主键的列名列表。

SQLSpecialColumns

Yes

Yes

X/Open

返回关于最佳列集合的信息,该列集合唯一地指明了指定表中的行,或当某 1 事务更新了行中的任何值时自动更新的列。

SQLStatistics

Yes

Yes

ISO 92

返回关于单个表的统计信息,以及与表相关的索引列表。

SQLTablePrivileges

Yes

Yes

ODBC

返回表列表,以及与各表相关的权限。

SQLTables

Yes

Yes

X/Open

返回存储在特定数据源内的表名列表。

执行事务:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLTransact

Yes

Yes

Deprecated

提交或回滚事务。

SQLEndTran

No

Yes

ISO 92

提交或回滚事务。

中止语句:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLFreeStmt

Yes

Yes

ISO 92

结束语句处理,舍弃未决结果,并释放与语句句柄相关的所有资源 (可选)。

SQLCloseCursor

Yes

Yes

ISO 92

关闭在语句句柄上打开的指针。

SQLCancel

Yes

Yes

ISO 92

取消 SQL 语句。

中止连接:

函数名

MyODBC

MyODBC

一致性

目的

 

2.50

3.51

 

 

SQLDisconnect

Yes

Yes

ISO 92

关闭连接。

SQLFreeHandle

No

Yes

ISO 92

释放环境、连接、语句或描述符句柄。

SQLFreeConnect

Yes

Yes

Deprecated

释放连接句柄。

SQLFreeEnv

Yes

Yes

Deprecated

释放连接句柄。

26.1.17. MyODBC 数据类型

在下表中,介绍了驱动程序将服务器数据类型映射为默认 SQL 和 C 数据类型的方法:

SQL 类型

C 类型

bit

SQL_BIT

SQL_C_BIT

tinyint

SQL_TINYINT

SQL_C_STINYINT

tinyint unsigned

SQL_TINYINT

SQL_C_UTINYINT

bigint

SQL_BIGINT

SQL_C_SBIGINT

bigint unsigned

SQL_BIGINT

SQL_C_UBIGINT

long varbinary

SQL_LONGVARBINARY

SQL_C_BINARY

blob

SQL_LONGVARBINARY

SQL_C_BINARY

longblob

SQL_LONGVARBINARY

SQL_C_BINARY

tinyblob

SQL_LONGVARBINARY

SQL_C_BINARY

mediumblob

SQL_LONGVARBINARY

SQL_C_BINARY

long varchar

SQL_LONGVARCHAR

SQL_C_CHAR

text

SQL_LONGVARCHAR

SQL_C_CHAR

mediumtext

SQL_LONGVARCHAR

SQL_C_CHAR

char

SQL_CHAR

SQL_C_CHAR

numeric

SQL_NUMERIC

SQL_C_CHAR

decimal

SQL_DECIMAL

SQL_C_CHAR

integer

SQL_INTEGER

SQL_C_SLONG

integer unsigned

SQL_INTEGER

SQL_C_ULONG

int

SQL_INTEGER

SQL_C_SLONG

int unsigned

SQL_INTEGER

SQL_C_ULONG

mediumint

SQL_INTEGER

SQL_C_SLONG

mediumint unsigned

SQL_INTEGER

SQL_C_ULONG

smallint

SQL_SMALLINT

SQL_C_SSHORT

smallint unsigned

SQL_SMALLINT

SQL_C_USHORT

real

SQL_FLOAT

SQL_C_DOUBLE

double

SQL_FLOAT

SQL_C_DOUBLE

float

SQL_REAL

SQL_C_FLOAT

double precision

SQL_DOUBLE

SQL_C_DOUBLE

date

SQL_DATE

SQL_C_DATE

time

SQL_TIME

SQL_C_TIME

year

SQL_SMALLINT

SQL_C_SHORT

datetime

SQL_TIMESTAMP

SQL_C_TIMESTAMP

timestamp

SQL_TIMESTAMP

SQL_C_TIMESTAMP

text

SQL_VARCHAR

SQL_C_CHAR

varchar

SQL_VARCHAR

SQL_C_CHAR

enum

SQL_VARCHAR

SQL_C_CHAR

set

SQL_VARCHAR

SQL_C_CHAR

bit

SQL_CHAR

SQL_C_CHAR

bool

SQL_CHAR

SQL_C_CHAR

26.1.18. MyODBC 错误代码

在下表中,列出了驱动程序返回的除服务器错误之外的错误代码列表:

本机代码

SQLSTATE 2

SQLSTATE 3

错误消息

500

01000

01000

一般警告

501

01004

01004

字符串数据,右截

502

01S02

01S02

选项值被更改

503

01S03

01S03

未更新/删除行

504

01S04

01S04

更新/删除了 1 个以上的行

505

01S06

01S06

在结果集合返回第 1 个行集合之前视图获取数据。

506

07001

07002

对于所有参数,未使用 SQLBindParameter

507

07005

07005

精制语句不符合光标规范

508

07009

07009

无效的描述符索引。

509

08002

08002

连接名正在使用。

510

08003

08003

连接不存在。

511

24000

24000

无效的光标状态。

512

25000

25000

无效的事务状态。

513

25S01

25S01

事务状态未知。

514

34000

34000

无效光标名。

515

S1000

HY000

一般的驱动程序定义错误。

516

S1001

HY001

内存分配错误。

517

S1002

HY002

无效的列编号。

518

S1003

HY003

无效的应用缓冲类型。

519

S1004

HY004

无效的 SQL 数据类型。

520

S1009

HY009

空指针的无效使用。

521

S1010

HY010

函数顺序错误。

522

S1011

HY011

现在无法设置属性。

523

S1012

HY012

无效的事务操作码。

524

S1013

HY013

内存管理错误。

525

S1015

HY015

无可用的光标名。

526

S1024

HY024

无效的属性值。

527

S1090

HY090

无效字符串或缓冲长度。

528

S1091

HY091

无效的描述符字段标识符。

529

S1092

HY092

无效的属性/选项标识符。

530

S1093

HY093

无效的参数编号。

531

S1095

HY095

函数类型超出范围。

532

S1106

HY106

获取类型超出范围。

533

S1117

HY117

行值超出范围。

534

S1109

HY109

无效的光标位置。

535

S1C00

HYC00

可选特性未实施。

0

21S01

21S01

列计数与值计数不匹配。

0

23000

23000

完整性约束违反。

0

42000

42000

语法错误或访问冲突。

0

42S02

42S02

未发现基本表或视图。

0

42S12

42S12

未发现索引。

0

42S21

42S21

列已存在。

0

42S22

42S22

未发现列。

0

08S01

08S01

通信链接失败。

26.1.19. MyODBC 与 VB:ADO、DAO 和 RDO

在本节中,给出了 MySQL ODBC 3.51 驱动程序与 ADO、DAO 和 RDO 一起使用的一些简单示例。

26.1.19.1. ADO: rs.addNew, rs.delete 和 rs.update

在下面的 ADO(ActiveX 数据对象) 示例中,创建了表my_ado,并演示了 rs.addNewrs.deleters.update的用法。

Private Sub myodbc_ado_Click()
 
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim fld As ADODB.Field
Dim sql As String
 
'connect to MySQL server using MySQL ODBC 3.51 Driver(使用 MySQL ODBC 3.51 驱动程序连接到 MySQL 服务器)
Set conn = New ADODB.Connection
conn.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"_
                      & "SERVER=localhost;"_
                      & " DATABASE=test;"_
                      & "UID=venu;PWD=venu; OPTION=3"
 
conn.Open
 
'create table(创建表)
conn.Execute "DROP TABLE IF EXISTS my_ado"
conn.Execute "CREATE TABLE my_ado(id int not null primary key, name varchar(20)," _
                               & "txt text, dt date, tm time, ts timestamp)"
 
'direct insert(直接插入)
conn.Execute "INSERT INTO my_ado(id,name,txt) values(1,100,'venu')"
conn.Execute "INSERT INTO my_ado(id,name,txt) values(2,200,'MySQL')"
conn.Execute "INSERT INTO my_ado(id,name,txt) values(3,300,'Delete')"
 
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseServer
 
'fetch the initial table ..(获取初始表…)
rs.Open "SELECT * FROM my_ado", conn
  Debug.Print rs.RecordCount
  rs.MoveFirst
  Debug.Print String(50, "-") & "Initial my_ado Result Set " & String(50, "-")
  For Each fld In rs.Fields
    Debug.Print fld.Name,
    Next
    Debug.Print
 
    Do Until rs.EOF
    For Each fld In rs.Fields
    Debug.Print fld.Value,
    Next
    rs.MoveNext
    Debug.Print
  Loop
rs.Close
 
'rs insert(rs插入)
rs.Open "select * from my_ado", conn, adOpenDynamic, adLockOptimistic
rs.AddNew
rs!Name = "Monty"
rs!txt = "Insert row"
rs.Update
rs.Close
 
'rs update(rs更新)
rs.Open "SELECT * FROM my_ado"
rs!Name = "update"
rs!txt = "updated-row"
rs.Update
rs.Close
 
'rs update second time..(rs更新第2次…)
rs.Open "SELECT * FROM my_ado"
rs!Name = "update"
rs!txt = "updated-second-time"
rs.Update
rs.Close
 
'rs delete(rs删除)
rs.Open "SELECT * FROM my_ado"
rs.MoveNext
rs.MoveNext
rs.Delete
rs.Close
 
'fetch the updated table ..(获取更新的表…)
rs.Open "SELECT * FROM my_ado", conn
  Debug.Print rs.RecordCount
  rs.MoveFirst
  Debug.Print String(50, "-") & "Updated my_ado Result Set " & String(50, "-")
  For Each fld In rs.Fields
    Debug.Print fld.Name,
    Next
    Debug.Print
 
    Do Until rs.EOF
    For Each fld In rs.Fields
    Debug.Print fld.Value,
    Next
    rs.MoveNext
    Debug.Print
  Loop
rs.Close
conn.Close
End Sub

26.1.19.2. DAO: rs.addNew, rs.update 和滚动

在下面的 DAO(数据访问对象) 示例中,创建了表my_dao,并演示了 rs.addNewrs.update、以及结果集滚动的用法。
Private Sub myodbc_dao_Click()
 
Dim ws As Workspace
Dim conn As Connection
Dim queryDef As queryDef
Dim str As String
 
'connect to MySQL server using MySQL ODBC 3.51 Driver(使用 MySQL ODBC 3.51 驱动程序连接到 MySQL)
Set ws = DBEngine.CreateWorkspace("", "venu", "venu", dbUseODBC)
str = "odbc;DRIVER={MySQL ODBC 3.51 Driver};"_
                      & "SERVER=localhost;"_
                      & " DATABASE=test;"_
                      & "UID=venu;PWD=venu; OPTION=3"
Set conn = ws.OpenConnection("test", dbDriverNoPrompt, False, str)
 
'Create table my_dao(创建表my_dao)
Set queryDef = conn.CreateQueryDef("", "drop table if exists my_dao")
queryDef.Execute
 
Set queryDef = conn.CreateQueryDef("", "create table my_dao(Id INT AUTO_INCREMENT PRIMARY KEY, " _
                                                         & "Ts TIMESTAMP(14) NOT NULL, Name varchar(20), Id2 INT)")
queryDef.Execute
 
'Insert new records using rs.addNew(使用rs.addNew插入新记录)
Set rs = conn.OpenRecordset("my_dao")
Dim i As Integer
 
  For i = 10 To 15
  rs.AddNew
  rs!Name = "insert record" & i
  rs!Id2 = i
  rs.Update
  Next i
           rs.Close
 
'rs update..(rs更新)
Set rs = conn.OpenRecordset("my_dao")
rs.Edit
rs!Name = "updated-string"
rs.Update
rs.Close
 
'fetch the table back...(向后获取表…)
Set rs = conn.OpenRecordset("my_dao", dbOpenDynamic)
str = "Results:"
rs.MoveFirst
While Not rs.EOF
str = " " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print "DATA:" & str
rs.MoveNext
Wend
 
'rs Scrolling(rs滚动)
rs.MoveFirst
str = " FIRST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str
 
rs.MoveLast
str = " LAST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str
 
rs.MovePrevious
str = " LAST-1 ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2
Debug.Print str
 
'free all resources(释放所有资源)
rs.Close
queryDef.Close
conn.Close
ws.Close
 
End Sub

26.1.19.3. RDO: rs.addNew 和 rs.update

在下面的 RDO(远程数据对象) 示例中,创建了表my_rdo,并演示了 rs.addNewrs.update的用法。
Dim rs As rdoResultset
  Dim cn As New rdoConnection
  Dim cl As rdoColumn
  Dim SQL As String
 
  'cn.Connect = "DSN=test;"
  cn.Connect = "DRIVER={MySQL ODBC 3.51 Driver};"_
                      & "SERVER=localhost;"_
                      & " DATABASE=test;"_
                      & "UID=venu;PWD=venu; OPTION=3"
 
  cn.CursorDriver = rdUseOdbc
  cn.EstablishConnection rdDriverPrompt
 
 
  'drop table my_rdo(舍弃表my_rdo)
  SQL = "drop table if exists my_rdo"
  cn.Execute SQL, rdExecDirect
 
  'create table my_rdo(创建表my_rdo)
  SQL = "create table my_rdo(id int, name varchar(20))"
  cn.Execute SQL, rdExecDirect
 
  'insert  direct(插入,直接)
  SQL = "insert into my_rdo values (100,'venu')"
  cn.Execute SQL, rdExecDirect
 
  SQL = "insert into my_rdo values (200,'MySQL')"
  cn.Execute SQL, rdExecDirect
 
  'rs insert(rs插入)
  SQL = "select * from my_rdo"
  Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
  rs.AddNew
  rs!id = 300
  rs!Name = "Insert1"
  rs.Update
  rs.Close
 
  'rs insert(rs插入)
  SQL = "select * from my_rdo"
  Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
  rs.AddNew
  rs!id = 400
  rs!Name = "Insert 2"
  rs.Update
  rs.Close
 
  'rs update(rs更新)
  SQL = "select * from my_rdo"
  Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
  rs.Edit
  rs!id = 999
  rs!Name = "updated"
  rs.Update
  rs.Close
 
  'fetch back...
  SQL = "select * from my_rdo"
  Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect)
  Do Until rs.EOF
  For Each cl In rs.rdoColumns
              Debug.Print cl.Value,
    Next
    rs.MoveNext
    Debug.Print
             Loop
  Debug.Print "Row count="; rs.RowCount
 
  'close(关闭)
  rs.Close
  cn.Close
 
End Sub

26.1.20. MyODBC 与 Microsoft.NET

本节包含一些简单示例,介绍了 MyODBC 驱动程序与 ODBC.NET 一起使用的用法。

26.1.20.1. ODBC.NET: CSHARP(C#)

在下面的简单示例中创建了表my_odbc_net,并介绍了它在 C#中的使用。

/**
* @sample    : mycon.cs
* @purpose   : Demo sample for ODBC.NET using MyODBC
* @author    : Venu, <venu@mysql.com>
*
* (C) Copyright MySQL AB, 1995-2004
*
**/

/* build command
*
*  csc /t:exe
*      /out:mycon.exe mycon.cs
*      /r:Microsoft.Data.Odbc.dll
*/

using Console = System.Console;
using Microsoft.Data.Odbc;

namespace myodbc3
{
class mycon
{
  static void Main(string[] args)
  {
    try
    {
      //Connection string for MyODBC 2.50
      /*string MyConString = "DRIVER={MySQL};" +
                           "SERVER=localhost;" +
                           "DATABASE=test;" +
                           "UID=venu;" +
                           "PASSWORD=venu;" +
                           "OPTION=3";
      */
      //Connection string for MyODBC 3.51
      string MyConString = "DRIVER={MySQL ODBC 3.51 Driver};" +
                           "SERVER=localhost;" +
                           "DATABASE=test;" +
                           "UID=venu;" +
                           "PASSWORD=venu;" +
                           "OPTION=3";

      //Connect to MySQL using MyODBC
      OdbcConnection MyConnection = new OdbcConnection(MyConString);
      MyConnection.Open();

      Console.WriteLine("\n !!! success, connected successfully !!!\n");

      //Display connection information
      Console.WriteLine("Connection Information:");
      Console.WriteLine("\tConnection String:" + MyConnection.ConnectionString);
      Console.WriteLine("\tConnection Timeout:" + MyConnection.ConnectionTimeout);
      Console.WriteLine("\tDatabase:" + MyConnection.Database);
      Console.WriteLine("\tDataSource:" + MyConnection.DataSource);
      Console.WriteLine("\tDriver:" + MyConnection.Driver);
      Console.WriteLine("\tServerVersion:" + MyConnection.ServerVersion);

      //Create a sample table
      OdbcCommand MyCommand = new OdbcCommand("DROP TABLE IF EXISTS my_odbc_net",MyConnection);
      MyCommand.ExecuteNonQuery();
      MyCommand.CommandText = "CREATE TABLE my_odbc_net(id int, name varchar(20), idb bigint)";
      MyCommand.ExecuteNonQuery();

      //Insert
      MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(10,'venu', 300)";
      Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());;

      //Insert
      MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',400)";
      Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());

      //Insert
      MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',500)";
      Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());

      //Update
      MyCommand.CommandText = "UPDATE my_odbc_net SET id=999 WHERE id=20";
      Console.WriteLine("Update, Total rows affected:" + MyCommand.ExecuteNonQuery());

      //COUNT(*)
      MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_odbc_net";
      Console.WriteLine("Total Rows:" + MyCommand.ExecuteScalar());

      //Fetch
      MyCommand.CommandText = "SELECT * FROM my_odbc_net";
      OdbcDataReader MyDataReader;
      MyDataReader =  MyCommand.ExecuteReader();
      while (MyDataReader.Read())
      {
       if(string.Compare(MyConnection.Driver,"myodbc3.dll") == 0) {
         Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
                                     MyDataReader.GetString(1) + " " +
                                     MyDataReader.GetInt64(2)); //Supported only by MyODBC 3.51
       }
       else {
         Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " +
                                     MyDataReader.GetString(1) + " " +
                                     MyDataReader.GetInt32(2)); //BIGINTs not supported by MyODBC
       }
      }

      //Close all resources
      MyDataReader.Close();
      MyConnection.Close();
    }
    catch (OdbcException MyOdbcException)//Catch any ODBC exception ..
    {
      for (int i=0; i < MyOdbcException.Errors.Count; i++)
      {
        Console.Write("ERROR #" + i + "\n" +
          "Message: " + MyOdbcException.Errors[i].Message + "\n" +
          "Native: " + MyOdbcException.Errors[i].NativeError.ToString() + "\n" +
          "Source: " + MyOdbcException.Errors[i].Source + "\n" +
          "SQL: " + MyOdbcException.Errors[i].SQLState + "\n");
      }
    }
  }
}
}

26.1.20.2. ODBC.NET: VB

在下面的简单示例中创建了表my_vb_net,并介绍了它在 VB 中的用法。

' @sample    : myvb.vb
' @purpose   : Demo sample for ODBC.NET using MyODBC
' @author    : Venu, <venu@mysql.com>
'
' (C) Copyright MySQL AB, 1995-2004
'
'

'
' build command
'
' vbc /target:exe
'     /out:myvb.exe
'     /r:Microsoft.Data.Odbc.dll
'     /r:System.dll
'     /r:System.Data.dll
'

Imports Microsoft.Data.Odbc
Imports System

Module myvb
  Sub Main()
      Try

          'MyODBC 3.51 connection string
          Dim MyConString As String = "DRIVER={MySQL ODBC 3.51 Driver};" & _
                         "SERVER=localhost;" & _
                         "DATABASE=test;" & _
                         "UID=venu;" & _
                         "PASSWORD=venu;" & _
                         "OPTION=3;"

          'Connection
          Dim MyConnection As New OdbcConnection(MyConString)
          MyConnection.Open()

          Console.WriteLine ("Connection State::" & MyConnection.State.ToString)

          'Drop
          Console.WriteLine ("Dropping table")
          Dim MyCommand As New OdbcCommand()
          MyCommand.Connection = MyConnection
          MyCommand.CommandText = "DROP TABLE IF EXISTS my_vb_net"
          MyCommand.ExecuteNonQuery()

          'Create
          Console.WriteLine ("Creating....")
          MyCommand.CommandText = "CREATE TABLE my_vb_net(id int, name varchar(30))"
          MyCommand.ExecuteNonQuery()

          'Insert
          MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(10,'venu')"
          Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

          'Insert
          MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
          Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

          'Insert
          MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')"
          Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

          'Insert
          MyCommand.CommandText = "INSERT INTO my_vb_net(id) VALUES(30)"
          Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery())

          'Update
          MyCommand.CommandText = "UPDATE my_vb_net SET id=999 WHERE id=20"
          Console.WriteLine("Update, Total rows affected:" & MyCommand.ExecuteNonQuery())

          'COUNT(*)
          MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_vb_net"
          Console.WriteLine("Total Rows:" & MyCommand.ExecuteScalar())

          'Select
          Console.WriteLine ("Select * FROM my_vb_net")
          MyCommand.CommandText = "SELECT * FROM my_vb_net"
          Dim MyDataReader As OdbcDataReader
          MyDataReader = MyCommand.ExecuteReader
          While MyDataReader.Read
              If MyDataReader("name") Is DBNull.Value Then
                  Console.WriteLine ("id = " & CStr(MyDataReader("id")) & "  name = " & _
                    "NULL")
              Else
                  Console.WriteLine ("id = " & CStr(MyDataReader("id")) & "  name = " & _
                                        CStr(MyDataReader("name")))
              End If
          End While

      'Catch ODBC Exception
      Catch MyOdbcException As OdbcException
          Dim i As Integer
          Console.WriteLine (MyOdbcException.ToString)

      'Catch program exception
      Catch MyException As Exception
          Console.WriteLine (MyException.ToString)
  End Try
  End Sub
End Module

26.1.21. ;感谢

下面列出了一些 MySQL AB 公司负责 MyODBC 和 MyODBC 3.51 驱动程序开发的人员。

  • Micheal (Monty) Widenius

  • Venu Anuganti

  • Peter Harvey

26.2. MySQL Connector/NET

26.2.1. ;前言

使用 MySQL Connector/NET,开发人员能够方便地创建需要安全和高性能数据连接 (与 MySQL) 的。NET 应用程序。它实施了所需的 ADO.NET 接口,并将其集成到了 ADO.NET aware 工具中。开发人员能够使用他们选择的。NET 语言创建应用程序。MySQL Connector/NET 是用 100%纯 C#语言编写的可完全管理的 ADO.NET 驱动程序。

MySQL Connector/NET 包括对下述事宜的完整支持:

·         MySQL 5.0 特性 (存储程序等)。

·         MySQL 4.1 特性 (服务器端的精制语句、Unicode、以及共享内存访问等)。

·         大信息包支持,可发送和接收高达 2GB 的行和 BLOB。

·         协议压缩,允许压缩客户端和服务器之间的数据流。

·         支持使用 CP/IP 套接字、命名管道、以及 Windows 共享内存的连接。

·         支持使用 CP/IP 套接字、或 Unix 套接字的连接。

·         支持由 Novell 开发的开放源码 Mono 框架。

·         可完全管理,不利用 MySQL 客户端库。

MySQL Connector/NET 的开发人员高度尊重用户在软件开发过程中提供的帮助。如果你发现 MySQL Connector/NET 缺少对你来说很重要的某些特性,或者如果你发现了缺陷,请使用我们的MySQL 缺陷系统请求该特性或通报问题。

通过http://forums.mysql.com上的论坛以及http://lists.mysql.com上的邮件列表,可找到针对 MySQL Connector/NET 的社区支持信息。MySQL AB 公司提供付费支持,更多信息请参见http://www.mysql.com/support/

本文档的目的是作为 MySQL Connector/NET 的用户指南,而不是语法参考。如果你打算了解详细的语法信息,请阅读 MySQL Connector/NET 分发版中提供的Documentation.chm 文件。

26.2.2. ;下载并安装 MySQL Connector/NET

MySQL Connector/NET 能够运行在任何支持。NET 框架的平台上。.NET 框架主要被最近的 Microsoft Windows 版本支持,通过由 Novell 开发的 Mono 框架,在 Linux 上也支持它 (请参见http://www.mono-project.com)。

MySQL Connector/NET 可通过使用 Windows Installer (.msi) 安装软件包进行安装,使用该软件包,可在任何 Windows 操作系统上安装 MySQL Connector/NET。MSI 软件包包含在名为mysql-connector-net-version.zip 的压缩文件中,其中,version(版本) 指明了MySQL Connector/NET 的版本。

可从下述网站下载 MySQL Connector/NET:http://dev.mysql.com/downloads/connector/net/1.0.html

随着 Windows XP 的发布,Windows Installer(安装器) 引擎也予以了更新,对于使用旧版本的用户,可参阅该 Microsoft 知识库文章以了解升级至最新版本的更多信息。

要想安装 MySQL Connector/NET,请右击 MSI 文件并选择“安装”。在安装器提示你完成安装参数选择后,安装将自动开始。对于大多数用户,建议采用典型安装。

如果在运行安装器时遇到问题,可下载不带安装器的 ZIP 文件。该文件名为mysql-connector-net-version-noinstall.zip。使用 ZIP 程序,将其解压至你所选择的目录。

除非作了其他选择,否则 MySQL Connector/NET 将被安装到“C:\Program Files\MySQL\MySQL Connector Net X.X.X”,其中,“X.X.X”是你所安装的 MySQL Connector/NET 的版本号。新安装不会覆盖已有的 MySQL Connector/NET 版本。

26.2.3. Connector/NET 体系结构

MySQL Connector/NET 包含数个类,这些类可用于连接到数据库,执行查询和语句,并管理查询结果。

下面介绍了 MySQL Connector/NET 的主要类:

·         MySqlCommand:代表对 MySQL 数据库进行执行操作的 SQL 语句。

·         MySqlCommandBuilder:自动生成单个表的命令,用于协调对 DataSet 所作的更改和相关的 MySQL 数据库。

·         MySqlConnection:代表与 MySQL 服务器数据库的开放式连接。

·         MySqlDataAdapter:代表一组数据命令和数据库连接,用于填充数据库和更新 MySQL 数据库。

·         MySqlDataReader:提供了从 MySQL 数据库读取行的“仅正向”流的一种方式。

·         MySqlException:当 MySQL 返回错误时抛出的异常。

·         MySqlHelper:助手类,能使工作变的更简单。

·         MySqlTransaction:代表将在 MySQL 数据库中进行的 SQL 事务。

在后续段落中,将分别介绍这些对象。这些章节的目的是概要介绍 MySQL Connector/NET 的主要类,而不是语法参考。如果你打算了解详细的语法信息,请阅读 MySQL Connector/NET 分发版中提供的Documentation.chm 文件。

26.2.3.1. MySqlCommand 类

MySqlCommand 类代表对 MySQL 数据库进行执行操作的 SQL 语句。

注释:在以前的版本中,采用符号“@”来标识 SQL 中的参数。它与 MySQL 用户变量不兼容,因此,现采用符号“?”来定位 SQL 中的参数。为了支持早期代码,也可以在连接字符串中设置“old syntax=yes”。如果进行了这类设置,请注意,如果无法定义希望在 SQL 中使用的参数 (定义失败),不会给出异常提示。

26.2.3.1.1. ;属性
可用属性如下:

·         CommandText:获取或设置将在数据源上执行的 SQL 语句。

·         CommandTimeout:获取或设置中止执行命令并生成错误之前应等待的时间。

·         CommandType:获取或设置值,该值指明了解释 CommandText 的方式。可能的值包括StoredProcedureTableDirectText

·         Connection:获取或设置该 MySqlCommand 实例使用的 MySqlConnection。

·         IsPrepared:如果该命令已准备好,为“真”,否则为“假”。

·         Parameters:获取 MySqlParameterCollection。

·         Transaction:获取或设置 MySqlTransaction,MySqlCommand 将在其中执行。

·         UpdatedRowSource:当 DbDataAdapter 的 Update 方法使用它时,用于获取或设置命令结果作用在 DataRow 上的方式。

26.2.3.1.2. ;方法
可用方法如下:

·         Cancel:尝试取消 MySqlCommand 的执行。不支持该操作。

·         Clone:创建该 MySqlCommand 对象的克隆对象。包括 CommandText、Connection 和 Transaction 属性,以及整个参数列表。

·         CreateParameter:创建 MySqlParameter 对象的新实例。

·         Dispose:处理该 MySqlCommand 实例。

·         ExecuteNonQuery:根据连接情况执行 SQL 语句,并返回受影响的行数。

·         ExecuteReader:将 CommandText 发送给 Connection,并创建 MySqlDataReader。

·         ExecuteScalar:执行查询,并返回查询操作所返回的结果集中第 1 行的第 1 列。多余的列或行将被忽略。

·         Prepare:在 MySQL 服务器的 1 个实例上创建命令的预制版本。

26.2.3.1.3. ;用法
在下面的示例中,创建了 1 个 MySqlCommand 和 1 个 MySqlConnection。打开了 MySqlConnection,并将其设置为用于 MySqlCommand 的连接。随后,调用 ExecuteNonQuery,并关闭连接。为了完成该任务,为 ExecuteNonQuery 传递了 1 个连接字符串和 1 个查询字符串 (查询字符串是 1 条 SQL INSERT 语句)。
26.2.3.1.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlCommand 类的方法:

Public Sub InsertRow(myConnectionString As String)
    ' If the connection string is null, use a default.
    If myConnectionString = "" Then
        myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"
    End If
    Dim myConnection As New MySqlConnection(myConnectionString)
    Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"
    Dim myCommand As New MySqlCommand(myInsertQuery)
    myCommand.Connection = myConnection
    myConnection.Open()
    myCommand.ExecuteNonQuery()
    myCommand.Connection.Close()
End Sub
26.2.3.1.3.2. C#

在下例中,介绍了在 C#中使用 MySqlCommand 类的方法:

public void InsertRow(string myConnectionString)
{
    // If the connection string is null, use a default.
    if(myConnectionString == "")
    {
        myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass";
    }
    MySqlConnection myConnection = new MySqlConnection(myConnectionString);
    string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)";
    MySqlCommand myCommand = new MySqlCommand(myInsertQuery);
    myCommand.Connection = myConnection;
    myConnection.Open();
    myCommand.ExecuteNonQuery();
    myCommand.Connection.Close();
}

26.2.3.2. MySqlCommandBuilder 类

MySqlDataAdapter 不会自动生成所需的 SQL 语句 (用于协调对 DataSet 所作的更改和相关的 MySQL 实例)。但是,如果设置了 MySqlDataAdapter 的 SelectCommand 属性,可以创建 MySqlCommandBuilder 对象来自动生成针对单个表更新的 SQL 语句。随后,MySqlCommandBuilder 将生成你未设置的任何附加的 SQL 语句。

一旦你设置了 DataAdapter 属性,MySqlCommandBuilder 会将自己注册为针对 OnRowUpdating 事件的监听程序。一次只能将 1 个 MySqlDataAdapter 或 MySqlCommandBuilder 对象关联起来。

为了生成 INSERT、UPDATE 或 DELETE 语句,MySqlCommandBuilder 使用了 SelectCommand 属性来自动检索所需的元数据集合。如果在检索完元数据后更改了 SelectCommand(例如首次更新后),应调用 RefreshSchema 方法来更新元数据。

SelectCommand 也必须返回至少 1 个主键或唯一列。如果未显示任何返回信息,将生成 InvalidOperation 异常,而且不会生成命令。

MySqlCommandBuilder 还会使用 SelectCommand 引用的 Connection、CommandTimeout 和 Transaction 属性。如果更改了这些属性中的任何 1 个,或者,如果替换了 SelectCommand 本身,用户应调用 RefreshSchema。如不然,InsertCommand、UpdateCommand 和 DeleteCommand 属性将保持它们以前的值。

如果调用了 Dispose,MySqlCommandBuilder 将解除与 MySqlDataAdapter 的关联,已生成的命令将不再使用。

26.2.3.2.1. ;属性

可用属性如下:

·         DataAdapter:MySqlCommandBuilder 将自己注册为针对 RowUpdating 事件的监听程序,RowUpdating 事件是由在该属性中指定的 MySqlDataAdapter 生成的。创建了新的 MySqlCommandBuilder 实例时,将释放任何已有的与 MySqlDataAdapter 关联的 MySqlCommandBuilder。

·         QuotePrefix, QuoteSuffix:MySQL 中的数据库对象能够包含特殊字符,如空格等,这会使得正常的 SQL 字符串无法解析。使用 QuotePrefix 和 QuoteSuffix 属性,MySqlCommandBuilder 能够创建处理该问题的 SQL 命令。

26.2.3.2.2. ;方法

可用方法如下:

·         DeriveParameters:从 MySqlCommand 指定的存储程序中检索参数信息,并填充所指定 MySqlCommand 对象的参数集。目前不支持该方法,这是因为 MySQL 中未提供存储程序。

·         GetDeleteCommand:获取用于在数据库上执行删除操作所需的、自动生成的 MySqlCommand 对象。

·         GetInsertCommand:获取用于在数据库上执行插入操作所需的、自动生成的 MySqlCommand 对象。

·         GetUpdateCommand:获取用于在数据库上执行更新操作所需的、自动生成的 MySqlCommand 对象。

·         RefreshSchema:刷新用于生成 INSERT、UPDATE 或 DELETE 语句的数据库方案信息。

26.2.3.2.3. ;用法
在下面给出的示例中,使用了 MySqlCommand、MySqlDataAdapter 和 MySqlConnection,用于从数据源选择行。为该示例传递了 1 个初始化的 DataSet、1 个连接字符串、1 个查询字符串 (是 SQL SELECT 语句)、以及 1 个作为数据库表名称的字符串。随后,该示例创建了 1 个 MySqlCommandBuilder。
26.2.3.2.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlCommandBuilder 类的方法:

  Public Shared Function SelectRows(myConnection As String, mySelectQuery As String, myTableName As String) As DataSet
        Dim myConn As New MySqlConnection(myConnection)
        Dim myDataAdapter As New MySqlDataAdapter()
        myDataAdapter.SelectCommand = New MySqlCommand(mySelectQuery, myConn)
        Dim cb As SqlCommandBuilder = New MySqlCommandBuilder(myDataAdapter)

        myConn.Open()

        Dim ds As DataSet = New DataSet
        myDataAdapter.Fill(ds, myTableName)

        ' Code to modify data in DataSet here

        ' Without the MySqlCommandBuilder this line would fail.
        myDataAdapter.Update(ds, myTableName)

        myConn.Close()
    End Function 'SelectRows
    
26.2.3.2.3.2. C#

在下例中,介绍了在 C#中使用 MySqlCommandBuilder 类的方法:

    public static DataSet SelectRows(string myConnection, string mySelectQuery, string myTableName)
    {
      MySqlConnection myConn = new MySqlConnection(myConnection);
      MySqlDataAdapter myDataAdapter = new MySqlDataAdapter();
      myDataAdapter.SelectCommand = new MySqlCommand(mySelectQuery, myConn);
      MySqlCommandBuilder cb = new MySqlCommandBuilder(myDataAdapter);

      myConn.Open();

      DataSet ds = new DataSet();
      myDataAdapter.Fill(ds, myTableName);

      //code to modify data in DataSet here

      //Without the MySqlCommandBuilder this line would fail
      myDataAdapter.Update(ds, myTableName);

      myConn.Close();

      return ds;
    }
    

26.2.3.3. MySqlConnection 类

MySqlConnection 对象代表与 MySQL 服务器数据源的会话。创建 MySqlConnection 实例时,所有属性均将被设置为它们的初始值。关于这些值的列表,请参见 MySqlConnection 构造函数。

如果 MySqlConnection 超出范围,不会被关闭。因此,必须通过调用 Close 或 Dispose 明确地关闭连接。

26.2.3.3.1. ;属性
可用属性如下:

·         ConnectionString:设置或获取用于连接至 MySQL 服务器数据库的字符串。

·         ConnectionTimeout:获取在中止尝试并生成错误之前为建立连接所需的等待时间。

·         Database:获取当前数据库的名称或打开连接后将使用的数据库的名称。

·         DataSource:获取将要连接的 MySQL 服务器的名称。

·         ServerThread:返回该连接所使用的服务器线程的 ID。

·         ServerVersion:获取包含客户端与之相连的 MySQL 服务器版本的字符串。

·         State:获取连接的当前连接的状态。

·         UseConnection:与服务器进行通信时,指明该连接是否将使用压缩特性。

26.2.3.3.2. ;方法
可用方法如下:

·         BeginTransaction:开始数据库事务。

·         ChangeDatabase:针对打开的 MySqlConnection,更改当前数据库。

·         Close:关闭与数据库的连接。这是关闭任何打开连接的首选方法。

·         CreateCommand:创建并返回与 MySqlConnection 相关的 MySqlCommand 对象。

·         Dispose:释放 MySqlConnection 使用的资源。

·         Open:用 ConnectionString 指定的属性设置打开数据库连接。

·         Ping:对 MySQL 服务器执行 Ping 操作。

26.2.3.3.3. ;用法
在下面的示例中,创建了 1 个 MySqlCommand 和 1 个 MySqlConnection。打开了 MySqlConnection,并将其设置为用于 MySqlCommand 的连接。随后,调用 ExecuteNonQuery,并关闭连接。为了完成该任务,为 ExecuteNonQuery 传递了 1 个连接字符串和 1 个查询字符串 (查询字符串是 1 条 SQL INSERT 语句)。
26.2.3.3.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlConnection 类的方法:

Public Sub InsertRow(myConnectionString As String)
    ' If the connection string is null, use a default.
    If myConnectionString = "" Then
        myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"
    End If
    Dim myConnection As New MySqlConnection(myConnectionString)
    Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"
    Dim myCommand As New MySqlCommand(myInsertQuery)
    myCommand.Connection = myConnection
    myConnection.Open()
    myCommand.ExecuteNonQuery()
    myCommand.Connection.Close()
End Sub
      
26.2.3.3.3.2. C#

在下例中,介绍了在 C#中使用 MySqlConnection 类的方法:

public void InsertRow(string myConnectionString)
{
    // If the connection string is null, use a default.
    if(myConnectionString == "")
    {
        myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass";
    }
    MySqlConnection myConnection = new MySqlConnection(myConnectionString);
    string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)";
    MySqlCommand myCommand = new MySqlCommand(myInsertQuery);
    myCommand.Connection = myConnection;
    myConnection.Open();
    myCommand.ExecuteNonQuery();
    myCommand.Connection.Close();
}

      

26.2.3.4. MySqlDataAdapter 类

MySQLDataAdapter 起着 DataSet 和 MySQL 之间桥梁的作用,用于检索和保存数据。MySQLDataAdapter 通过映射 Fill(填充) 和 Update(更新) 提供了该桥,Fill 能改变 DataSet 中的数据以便与数据源中的数据匹配,Update 能改变数据源中的数据以便与 DataSet 中的数据匹配 (通过对数据源使用恰当的 SQL 语句)。

当 MySQLDataAdapter 填充 DataSet 时,如果表或列不存在,它将为返回的数据创建必要的表和列。但是,在隐式创建的方案中不包括主键信息,除非将 MissingSchemaAction 属性设为 AddWithKey。在使用 FillSchema 用数据填充它之前,也能让 MySQLDataAdapter 创建 DataSet 方案,包含主键信息。

MySQLDataAdapter 用于 MySqlConnection 和 MySqlCommand 的连接,用以提升连接至 MySQL 数据库时的性能。

MySQLDataAdapter 还包括 SelectCommand、InsertCommand、DeleteCommand、UpdateCommand 和 TableMappings 属性,用于简化数据的加载和更新操作。

26.2.3.4.1. ;属性

可用属性如下:

·         AcceptChangesDuringFill:获取或设置值,该值指明了在任何填充操作过程中,在将 DataRow 添加到 DataTable 后,是否要在 DataRow 上调用 AcceptChanges。

·         ContinueUpdateOnError:获取或设置值,该值指定了在行更新过程中出现错误时是否要生成异常项。

·         DeleteCommand:获取或设置用于将记录从数据集中删除的 SQL 语句或存储程序。

·         InsertCommand:获取或设置用于在数据集中插入记录的 SQL 语句或存储程序。

·         MissingMappingAction:确定当进入的数据不含匹配表或列时需要采取的动作。

·         MissingSchemaAction:确定当已有的 DataSet 方案与进入数据不匹配时需要采取的动作。

·         SelectCommand:获取或设置用于在数据源中选择记录的 SQL 语句或存储程序。

·         TableMappings:获取提供了源表和 DataTable 之间主映射的集合。

·         UpdateCommand:获取或设置用于在数据源中更新记录的 SQL 语句或存储程序。

26.2.3.4.2. ;方法
可用方法如下:

·         Fill:使用 DataSet 名称添加或刷新 DataSet 中的行,以便与数据源中的行匹配,并创建名为“Table”的 DataTable。

·         FillSchema:将名为“Table”的 DataTable 添加到指定的 DataSet,并配置方案,以便与基于指定 SchemaType 的数据源中的表匹配。

·         GetFillParameters:执行 SQL SELECT 语句时,按用户获取参数集。

·         Update:为指定 DataSet 中的各插入行、更新行或删除行分别调用 INSERT、UPDATE 或 DELETE 语句。

26.2.3.4.3. ;用法
在下面的示例中,创建了 1 个 MySqlCommand 和 1 个 MySqlConnection。打开 MySqlConnection,并将其设置为用于 MySqlCommand 的连接。随后,调用 ExecuteNonQuery,并关闭连接。为了完成该任务,为 ExecuteNonQuery 传递了 1 个连接字符串和 1 个查询字符串 (查询字符串是 1 条 SQL INSERT 语句)。
26.2.3.4.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlDataAdapter 类的方法:

Public Function SelectRows(dataSet As DataSet, connection As String, query As String) As DataSet
    Dim conn As New MySqlConnection(connection)
    Dim adapter As New MySqlDataAdapter()
    adapter.SelectCommand = new MySqlCommand(query, conn)
    adapter.Fill(dataset)
    Return dataset
End Function
26.2.3.4.3.2. C#

在下例中,介绍了在 C#中使用 MySqlDataAdapter 类的方法:

public DataSet SelectRows(DataSet dataset,string connection,string query)
{
    MySqlConnection conn = new MySqlConnection(connection);
    MySqlDataAdapter adapter = new MySqlDataAdapter();
    adapter.SelectCommand = new MySqlCommand(query, conn);
    adapter.Fill(dataset);
    return dataset;
}
  

26.2.3.5. MySqlDataReader 类

MySqlDataReader 类提供了从 MySQL 数据库读取行的“仅正向”流的一种方式。

要想创建 MySQLDataReader,必须调用 MySqlCommand 对象的 ExecuteReader 方法,而不是直接使用构造函数。

使用 MySqlDataReader 的同时,相关的 MySqlConnection 将忙于 MySqlDataReader。除了关闭它之外,不能在 MySqlConnection 上执行任何操作。该情况将一直持续到调用了 MySqlDataReader 的“Close”方法为止。

关闭了 MySqlDataReader 后,你只能调用 IsClosed 和 RecordsAffected 属性。尽管在 MySqlDataReader 存在同时能够访问 RecordsAffected 属性,但在返回 RecordsAffected 的值之前总应调用“Close”,以确保准确的返回值。

为了获得最佳性能,MySqlDataReader 将避免创建不必要的对象或执行不必要的数据拷贝。其结果是,对诸如 GetValue 等方法的多个调用会返回对相同对象的引用。如果你准备更改由诸如 GetValue 等方法返回的对象的基本值,请仔细小心。

26.2.3.5.1. ;属性
可用属性如下:

·         Depth:获取指明当前行嵌套深度的值。目前并不支持方法,总会返回 0。

·         FieldCount:获取当前行中的列数。

·         HasRows:获取值,该值指明了 MySqlDataReader 是否包含 1 行或多行。

·         IsClosed:获取值,该值指明了和苏剧阅读器是否已关闭。

·         Item:以固有格式获取列的值。在 C#,该属性是 MySqlDataReader 类的索引属性。

·         RecordsAffected:获取隐执行 SQL 语句而更改、插入、或删除的行数。

26.2.3.5.2. ;方法
可用方法如下:

·         Close:关闭 MySqlDataReader 对象。

·         GetBoolean:获取指定列的布尔值。

·         GetByte:以字节形式获取指定列的值。

·         GetBytes:读取从指定列偏移至缓冲的字节流,数组从给定的缓冲偏移位置开始。

·         GetChar:以单字符形式获取指定列的值。

·         GetChars:读取从指定列偏移至缓冲的字符流,数组从给定的缓冲偏移位置开始。

·         GetDataTypeName:获取源数据类型的名称。

·         GetDateTime:以 DateTime 对象形式获取指定列的值。

·         GetDecimal:以 DateTime 对象形式获取指定列的值。

·         GetDouble:以双精度浮点数的形式获取指定列的值。

·         GetFieldType:获取作为对象数据类型的类型。

·         GetFloat:以单精度浮点数的形式获取指定列的值。

·         GetGuid:以 GUID 的形式获取指定列的值。

·         GetInt16:以 16 位带符号整数的形式获取指定列的值。

·         GetInt32:以 32 位带符号整数的形式获取指定列的值。

·         GetInt64:以 64 位带符号整数的形式获取指定列的值。

·         GetMySqlDateTime:以 MySqlDateTime 对象的形式获取指定列的值。

·         GetName:获取指定列的名称。

·         GetOrdinal:给定列名,获取列的顺序。

·         GetSchemaTable:返回描述了 MySqlDataReader 的列元数据的 DataTable。

·         GetString:以 String 对象的形式获取指定列的值。

·         GetTimeSpan:以 TimeSpan 对象的形式获取指定列的值。

·         GetUInt16:以 16 位无符号整数的形式获取指定列的值。

·         GetUInt32:以 32 位无符号整数的形式获取指定列的值。

·         GetUInt64:以 64 位无符号整数的形式获取指定列的值。

·         GetValue:以固有格式获取指定列的值。

·         GetValues:获取当前行集合中的所有属性列。

·         IsDBNull:获取值,该值指明了列中是否包含不存在或丢失的值。

·         NextResult:读取批 SQL 语句的结果时,使数据阅读器跳到下一个结果。

·         Read:使 MySqlDataReader 跳到下一条记录。

26.2.3.5.3. ;用法
在下面的示例中,创建了 1 个 MySqlConnection,1 个 MySqlCommand 和 1 个 MySqlDataReader。该示例读取数据,并将数据输出到控制台。最后,本例关闭了 MySqlDataReader,然后关闭了 MySqlConnection。
26.2.3.5.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlDataReader 类的方法:

Public Sub ReadMyData(myConnString As String)
    Dim mySelectQuery As String = "SELECT OrderID, CustomerID FROM Orders"
    Dim myConnection As New MySqlConnection(myConnString)
    Dim myCommand As New MySqlCommand(mySelectQuery, myConnection)
    myConnection.Open()
    Dim myReader As MySqlDataReader
    myReader = myCommand.ExecuteReader()
    ' Always call Read before accessing data.
    While myReader.Read()
        Console.WriteLine((myReader.GetInt32(0) & ", " & myReader.GetString(1)))
    End While
    ' always call Close when done reading.
    myReader.Close()
    ' Close the connection when done with it.
    myConnection.Close()
End Sub 'ReadMyData
      
26.2.3.5.3.2. C#

在下例中,介绍了在 C#中使用 MySqlDataReader 类的方法:

public void ReadMyData(string myConnString) {
    string mySelectQuery = "SELECT OrderID, CustomerID FROM Orders";
    MySqlConnection myConnection = new MySqlConnection(myConnString);
    MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection);
    myConnection.Open();
    MySqlDataReader myReader;
    myReader = myCommand.ExecuteReader();
    // Always call Read before accessing data.
    while (myReader.Read()) {
       Console.WriteLine(myReader.GetInt32(0) + ", " + myReader.GetString(1));
    }
    // always call Close when done reading.
    myReader.Close();
    // Close the connection when done with it.
    myConnection.Close();
 }
      

26.2.3.6. MySqlException 类

当 MySql 数据提供方遇到服务器生成的错误时将创建该类。

抛出异常时,打开的连接不会自动关闭。如果客户端应用程序判定该异常是致命的,应关闭任何打开的 MySqlDataReader 对象或 MySqlConnection 对象。

26.2.3.6.1. ;属性
可用属性如下:

·         HelpLink:获取或设置指向与该异常相关的帮助文件的链接。

·         InnerException:获取导致当前异常的异常实例。

·         IsFatal:如果该异常是致命的,为“真”,并关闭连接,如果不是致命的,为“假”。

·         Message:获取描述当前异常的消息。

·         Number:获取指明错误类型的编号。

·         Source:获取或设置导致错误的应用程序或对象的名称。

·         StackTrace:获取抛出当前异常时在调用堆栈上帧的字符串表征。

·         TargetSite:获取抛出当前异常的方法。

26.2.3.6.2. ;方法
MySqlException 类没有相应的方法。
26.2.3.6.3. ;用法
在下述示例中,因丢失了服务器而生成了 MySqlException,然后显示异常。
26.2.3.6.3.1. VB.NET

该示例介绍在 VB.NET 下使用 MySqlException 类的方法。

Public Sub ShowException()
     Dim mySelectQuery As String = "SELECT column1 FROM table1"
     Dim myConnection As New MySqlConnection ("Data Source=localhost;Database=Sample;")
     Dim myCommand As New MySqlCommand(mySelectQuery, myConnection)

     Try
         myCommand.Connection.Open()
     Catch e As MySqlException
        MessageBox.Show( e.Message )
     End Try
 End Sub
      
26.2.3.6.3.2. C#

该示例介绍在 C#下使用 MySqlException 类的方法。

public void ShowException()
{
   string mySelectQuery = "SELECT column1 FROM table1";
   MySqlConnection myConnection =
      new MySqlConnection("Data Source=localhost;Database=Sample;");
   MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection);

   try
   {
      myCommand.Connection.Open();
   }
   catch (MySqlException e)
   {
        MessageBox.Show( e.Message );
   }
}
    

26.2.3.7. MySqlHelper 类

助手类,能使与提供方 (Provider) 一起进行的工作变的更简单。开发人员可以使用该类提供的方法自动执行共同任务。
26.2.3.7.1. ;属性
MySqlHelper 类没有相应的属性。
26.2.3.7.2. ;方法
可用方法如下:

·         ExecuteDataRow:执行单个 SQL 语句并返回结果集的第 1 行。在该方法的执行过程中,将创建、打开并关闭 1 个新的 MySqlConnection 对象。

·         ExecuteDataset:执行单个 SQL 命令并返回 DataSet 中的结果集。在该方法的执行过程中,将创建、打开并关闭 1 个新的 MySqlConnection 对象。

·         ExecuteNonQuery:在 MySQL 数据库上执行单个命令。调用该方法时,将认为 MySqlConnection 已打开,方法执行完后,MySqlConnection 仍保持打开状态。

·         ExecuteReader:Overloaded:在 MySQL 数据库上执行单个命令。

·         ExecuteScalar:在 MySQL 数据库上执行单个命令。

·         UpdateDataSet:用来自给定 DataSet 的数据更新给定表。

26.2.3.8. MySqlTransaction 类

代表将在 MySQL 数据库中进行的 SQL 事务。
26.2.3.8.1. ;属性
可用属性如下:

·         Connection:获取与事务相关的 MySqlConnection 对象,如果事务不再有效,获取空引用 (在 Visual Basic 中为 Nothing)。

·         IsolationLevel:为该事务指定 IsolationLevel。

26.2.3.8.2. ;方法
可用方法如下:

·         Commit:提交数据库事务。

·         Rollback:从挂起状态回滚事务。

26.2.3.8.3. ;用法
在下面的示例中,创建了 1 个 MySqlConnection 和 1 个 MySqlTransaction。此外,在示例中还介绍了如何使用 BeginTransaction、Commit 和 Rollback 方法。
26.2.3.8.3.1. VB.NET

在下例中,介绍了在 VB.NET 中使用 MySqlTransaction 类的方法:

Public Sub RunTransaction(myConnString As String)
    Dim myConnection As New MySqlConnection(myConnString)
    myConnection.Open()

    Dim myCommand As MySqlCommand = myConnection.CreateCommand()
    Dim myTrans As MySqlTransaction

    ' Start a local transaction
    myTrans = myConnection.BeginTransaction()
    ' Must assign both transaction object and connection
    ' to Command object for a pending local transaction
    myCommand.Connection = myConnection
    myCommand.Transaction = myTrans

    Try
      myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"
      myCommand.ExecuteNonQuery()
      myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"
      myCommand.ExecuteNonQuery()
      myTrans.Commit()
      Console.WriteLine("Both records are written to database.")
    Catch e As Exception
      Try
        myTrans.Rollback()
      Catch ex As MySqlException
        If Not myTrans.Connection Is Nothing Then
          Console.WriteLine("An exception of type " & ex.GetType().ToString() & _
                            " was encountered while attempting to roll back the transaction.")
        End If
      End Try

      Console.WriteLine("An exception of type " & e.GetType().ToString() & _
                      "was encountered while inserting the data.")
      Console.WriteLine("Neither record was written to database.")
    Finally
      myConnection.Close()
    End Try
End Sub 'RunTransaction
      
26.2.3.8.3.2. C#

在下例中,介绍了在 C#中使用 MySqlTransaction 类的方法:

public void RunTransaction(string myConnString)
 {
    MySqlConnection myConnection = new MySqlConnection(myConnString);
    myConnection.Open();

    MySqlCommand myCommand = myConnection.CreateCommand();
    MySqlTransaction myTrans;

    // Start a local transaction
    myTrans = myConnection.BeginTransaction();
    // Must assign both transaction object and connection
    // to Command object for a pending local transaction
    myCommand.Connection = myConnection;
    myCommand.Transaction = myTrans;

    try
    {
      myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
      myCommand.ExecuteNonQuery();
      myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
      myCommand.ExecuteNonQuery();
      myTrans.Commit();
      Console.WriteLine("Both records are written to database.");
    }
    catch(Exception e)
    {
      try
      {
        myTrans.Rollback();
      }
      catch (MySqlException ex)
      {
        if (myTrans.Connection != null)
        {
          Console.WriteLine("An exception of type " + ex.GetType() +
                            " was encountered while attempting to roll back the transaction.");
        }
      }

      Console.WriteLine("An exception of type " + e.GetType() +
                        " was encountered while inserting the data.");
      Console.WriteLine("Neither record was written to database.");
    }
    finally
    {
      myConnection.Close();
    }
}
      

26.2.4. ;使用 MySQL Connector/NET

26.2.4.1. ;前言

在本节中,介绍的 Connector/NET 的一些常用方式,包括 BLOB 处理,日期处理,以及与诸如 Crystal Reports 等常见工具一起使用 Connector/NET 的方法。

26.2.4.2. ;使用 MySQL Connector/NET 连接到 MySQL

26.2.4.2.1. ;前言
.NET 应用程序和 MySQL 服务器之间的所有交互均是通过MySqlConnection 对象传送的。在应用程序能够与服务器进行交互之前,必须获取、配置、并打开MySqlConnection对象。

即使在使用MySqlHelper类时,MySqlConnection对象也会被Helper 类创建。

在本节中,介绍了使用MySqlConnection 对象连接到 MySQL 的方法。

26.2.4.2.2. ;创建连接字符串

MySqlConnection对象是使用连接字符串配置的。1 个连接字符串包含服务器键/值对,由分号隔开。每个键/值对由等号连接。

下面给出了 1 个简单的连接字符串示例:

    Server=127.0.0.1;Uid=root;Pwd=12345;Database=test;
    

在本例中,对MySqlConnection 对象进行了配置,使用用户名root和密码12345与位于 127.0.0.1 的MySQL 服务器相连。所有语句的默认数据库为测试数据库。

典型的选项如下 (关于选项的完整清单,请参见 API 文档):

·         Server:将要连接的 MySQL 实例的名称或网络地址。默认为本地主机。别名包括 Host, Data Source, DataSource, Address, AddrNetwork Address。

·         Uid:连接时使用的 MySQL 用户账户。别名包括User Id, UsernameUser name。

·         Pwd:MySQL 账户的密码。也可以使用别名密码。

·         Database:所有语句作用于的默认数据库。默认为mysql。也可以使用别名Initial Catalog

·         Port:MySQL 用于监听连接的端口。默认为3306。将该值指定为“-1将使用命名管道连接。

26.2.4.2.3. ;打开连接

一旦创建了连接字符串,可使用它打开与 MySQL 服务器的连接。

下述代码用于创建MySqlConnection对象,指定连接字符串,并打开连接。

[VB]

Dim conn As New MySql.Data.MySqlClient.MySqlConnection
Dim myConnectionString as String

myConnectionString = "server=127.0.0.1;" _
            & "uid=root;" _
            & "pwd=12345;" _
            & "database=test;"

Try
  conn.ConnectionString = myConnectionString
  conn.Open()

Catch ex As MySql.Data.MySqlClient.MySqlException
  MessageBox.Show(ex.Message)
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;

myConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn = new MySql.Data.MySqlClient.MySqlConnection();
    conn.ConnectionString = myConnectionString;
    conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message);
}

你也可以将连接字符串传递给MySqlConnection 类的构造函数:

[VB]

Dim myConnectionString as String

myConnectionString = "server=127.0.0.1;" _
              & "uid=root;" _
              & "pwd=12345;" _
              & "database=test;"

Try
    Dim conn As New MySql.Data.MySqlClient.MySqlConnection(myConnectionString)
    conn.Open()
Catch ex As MySql.Data.MySqlClient.MySqlException
   MessageBox.Show(ex.Message)
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;

myConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString);
    conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message);
}
一旦打开了连接,其他 MySQL Connector/NET 类也能使用该连接与 MySQL 服务器进行通信。
26.2.4.2.4. ;处理连接错误

由于与外部服务器的连接不可预测,应为你的。NET 应用程序添加错误处理功能,这点很重要。出现连接错误时,MySqlConnection类将返回 1 个MySqlException 对象。该对象有两个在处理错误时十分有用的属性:

·         Message:描述当前异常的消息。

·         Number:MySQL 错误编号。

处理错误时,可根据错误编号了解应用程序的响应。进行连接时最常见的两个错误编号如下:

·         0: 无法连接到服务器。

·         1045: 无效的用户名和/或密码。

在下面的代码中,介绍了根据实际错误改编应用程序的方法:

[VB]

Dim myConnectionString as String

myConnectionString = "server=127.0.0.1;" _
          & "uid=root;" _
          & "pwd=12345;" _
          & "database=test;"

Try
    Dim conn As New MySql.Data.MySqlClient.MySqlConnection(myConnectionString)
    conn.Open()
Catch ex As MySql.Data.MySqlClient.MySqlException
    Select Case ex.Number
        Case 0
            MessageBox.Show("Cannot connect to server. Contact administrator")
        Case 1045
            MessageBox.Show("Invalid username/password, please try again")
    End Select
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;

myConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString);
    conn.Open();
}
    catch (MySql.Data.MySqlClient.MySqlException ex)
{
    switch (ex.Number)
    {
        case 0:
            MessageBox.Show("Cannot connect to server.  Contact administrator");
        case 1045:
            MessageBox.Show("Invalid username/password, please try again");
    }
}
  

26.2.4.3. ;与预处理语句一起使用 MySQL Connector/NET

26.2.4.3.1. ;前言
从 MySQL 4.1 开始,能够与 MySQL Connector/NET 一起使用预处理语句。使用预处理语句能够现住改善多次执行的查询的性能。

对于多次执行的语句,预处理执行的速度快于直接执行,这是因为只需进行 1 次解析操作。在直接执行的情况下,每次执行时均将进行解析操作。预处理执行还能降低网络通信量,这是因为对于预处理语句的每次执行,仅需发送用于参数的数据。

预处理语句的另一优点是,它能使用二进制协议,这使得客户端和服务器间的数据传输更有效率。

26.2.4.3.2. ;在 MySQL Connector/NET 中准备语句
为了准备好语句,需创建 1 个命令对象,并为查询设置.CommandText 属性。

输入语句后,调用MySqlCommand 对象的。Prepare 方法。完成语句的准备后,为查询中的每个元素添加参数。

输入查询并输入参数后,使用.ExecuteNonQuery().ExecuteScalar()、或.ExecuteReader 方法执行语句。

对于后续的执行操作,仅需更改参数值并再次调用执行方法,无需设置.CommandText 属性或重新定义参数。

[VB]

Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
  
conn.ConnectionString = strConnection
 
Try
   conn.Open()
   cmd.Connection = conn
 
   cmd.CommandText = "INSERT INTO myTable VALUES(NULL, ?number, ?text)"
   cmd.Prepare()
 
   cmd.Parameters.Add("?number", 1)
   cmd.Parameters.Add("?text", "One")
 
   For i = 1 To 1000
       cmd.Parameters("?number").Value = i
       cmd.Parameters("?text").Value = "A string value"
 
       cmd.ExecuteNonQuery()
     Next 
Catch ex As MySqlException
    MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
  
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
 
conn.ConnectionString = strConnection;
 
try
{
    conn.Open();
    cmd.Connection = conn;
 
    cmd.CommandText = "INSERT INTO myTable VALUES(NULL, ?number, ?text)";
    cmd.Prepare();
 
    cmd.Parameters.Add("?number", 1);
    cmd.Parameters.Add("?text", "One");
 
    for (int i=1; i <= 1000; i++)
    {
        cmd.Parameters["?number"].Value = i;
        cmd.Parameters["?text"].Value = "A string value";
 
        cmd.ExecuteNonQuery();
    }
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
        "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

26.2.4.4. ;用 MySQL Connector/NET 访问存储程序

26.2.4.4.1. ;前言

随着 MySQL 版本 5 的发布,MySQL 服务器目前支持存储程序,它采用了 SQL 2003 存储程序的语法。

 

存储程序指的是能够保存在服务器上的一组 SQL 语句。 一旦完成了该操作,客户端无需再次发出单独语句,而仅需引用存储程序取而代之。

在下述情况下,存储程序尤其有用:

·         多个客户端应用程序是采用不同语言编写的或工作在不同平台上,但需执行相同的数据库操作。

·         安全性极其重要时。例如,对于所有共同操作,银行采用了存储程序。这样,就能提供一致且安全的环境,而且这类存储程序能够保证每次操作均具有恰当登录。在这类设置下,应用程序和用户无法直接访问数据库表,但能执行特定的存储程序。

MySQL Connector/NET 支持通过MySqlCommand 对象的存储程序调用。使用MySqlCommand.Parameters 集,能够将数据传入和传出MySQL 存储程序。

在本节中,未深度介绍创建存储程序方面的信息,要想了解这类信息,请参见 MySQL 参考手册的存储程序

在 MySQL Connector/NET 安装的Samples 目录下,可找到 1 个相应的示例,该示例演示了与MySQL Connector/NET 一起使用存储程序的方法。

26.2.4.4.2. ;从 MySQL Connector/NET 创建存储程序

可使用多种工具创建 MySQL 中的存储程序。首先,可使用mysql命令行客户端创建存储程序。其次,可使用MySQL Query Browser GUI 客户端创建存储程序。最后,可使用MySqlCommand 对象的。ExecuteNonQuery 方法创建存储程序。

[VB]

Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=test"

Try
    conn.Open()
    cmd.Connection = conn

    cmd.CommandText = "CREATE PROCEDURE add_emp(" _
        & "IN fname VARCHAR(20), IN lname VARCHAR(20), IN bday DATETIME, OUT empno INT) " _
        & "BEGIN INSERT INTO emp(first_name, last_name, birthdate) " _
        & "VALUES(fname, lname, DATE(bday)); SET empno = LAST_INSERT_ID(); END"

    cmd.ExecuteNonQuery()
Catch ex As MySqlException
    MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn.Open();
    cmd.Connection = conn;

    cmd.CommandText = "CREATE PROCEDURE add_emp(" +
        "IN fname VARCHAR(20), IN lname VARCHAR(20), IN bday DATETIME, OUT empno INT) " +
        "BEGIN INSERT INTO emp(first_name, last_name, birthdate) " +
        "VALUES(fname, lname, DATE(bday)); SET empno = LAST_INSERT_ID(); END";

    cmd.ExecuteNonQuery();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
请注意,不同于命令行和 GUI 客户端,在 MySQL Connector/NET 中创建存储程序时不需要指定特殊的定界符。
26.2.4.4.3. ;从 MySQL Connector/NET 调用存储程序

要想使用 MySQL Connector/NET 来调用存储程序,应创建 1 个MySqlCommand 对象,并将存储程序名作为。CommandText 属性传递。.CommandType属性设置为CommandType.StoredProcedure。

命名了存储程序后,为存储程序中的每个参数创建 1 个 MySqlCommand 参数。用参数名和包含值的对象定义 IN 参数,用参数名和预计将返回的数据类型定义 OUT 参数。对于所有参数,均需定义参数方向。

定义完参数后,使用MySqlCommand.ExecuteNonQuery() 方法调用存储程序。

[VB]

Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=test"

Try
    conn.Open()
    cmd.Connection = conn

    cmd.CommandText = "add_emp"
    cmd.CommandType = CommandType.StoredProcedure

    cmd.Parameters.Add("?lname", 'Jones')
    cmd.Parameters("?lname").Direction = ParameterDirection.Input

    cmd.Parameters.Add("?fname", 'Tom')
    cmd.Parameters("?fname").Direction = ParameterDirection.Input

    cmd.Parameters.Add("?bday", #12/13/1977 2:17:36 PM#)
    cmd.Parameters("?bday").Direction = ParameterDirection.Input

    cmd.Parameters.Add("?empno", MySqlDbType.Int32)
    cmd.Parameters("?empno").Direction = ParameterDirection.Output

    cmd.ExecuteNonQuery()

    MessageBox.Show(cmd.Parameters("?empno").Value)
Catch ex As MySqlException
    MessageBox.Show("Error " & ex.Number & " has occurred: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn.Open();
    cmd.Connection = conn;

    cmd.CommandText = "add_emp";
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Add("?lname", "Jones");
    cmd.Parameters("?lname").Direction = ParameterDirection.Input;

    cmd.Parameters.Add("?fname", "Tom");
    cmd.Parameters("?fname").Direction = ParameterDirection.Input;

    cmd.Parameters.Add("?bday", DateTime.Parse("12/13/1977 2:17:36 PM"));
    cmd.Parameters("?bday").Direction = ParameterDirection.Input;

    cmd.Parameters.Add("?empno", MySqlDbType.Int32);
    cmd.Parameters("?empno").Direction = ParameterDirection.Output;

    cmd.ExecuteNonQuery();

    MessageBox.Show(cmd.Parameters("?empno").Value);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
      "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
一旦调用了存储程序,可使用MySqlConnector.Parameters 集的。Value 属性检索输出参数的值。

26.2.4.5. ;用 Connector/NET 处理 BLOB 数据

26.2.4.5.1. ;前言
MySQL 的 1 种用途是在 BLOB 列中保存二进制数据。MySQL 支持 4 种不同的 BLOB 数据类型:TINYBLOB, BLOB, MEDIUMBLOBLONGBLOB

可使用 Connector/NET 访问保存在 BLOB 列中的数据,并能使用客户端代码对这类数据进行操作。使用 Connector/NET 和 BLOB 数据时,无特殊要求。

在本节中,给出了数个简单的代码示例,在 MySQL Connector/NET 安装的Samples 目录下,可找到 1 个完整的示例应用程序。

26.2.4.5.2. ;准备 MySQL 服务器
与 BLOB 数据一起使用 MySQL 的第 1 步是配置服务器。首先,让我们从创建要访问的表开始。在我的文件表中,通常有 4 列:1 个具有恰当大小的 AUTO_INCREMENT 列 (UNSIGNED SMALLINT),用于保存识别文件的主键;1 个 VARCHAR 列,用于保存文件名;1 个 UNSIGNED MEDIUMINT 列,用于保存文件的大小;以及 1 个用于保存文件本身的 MEDIUMBLOB 列。对于本例,我将使用下述表定义:
CREATE TABLE file(
file_id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
file_name VARCHAR(64) NOT NULL,
file_size MEDIUMINT UNSIGNED NOT NULL,
file MEDIUMBLOB NOT NULL);

完成表的创建后,或许需要更改 max_allowed_packet 系统变量。该变量决定了能够发送给 MySQL 服务器的信息包 (即单个行) 大小。默认情况下,服务器能够接受来自客户端应用程序的信息包最大为 1MB。如果不打算超过 1MB,情况良好。如果打算在文件传输中超出 1MB,必须增加该数值。

可以使用“MySQL 系统管理员的启动变量”屏幕更改 max_allowed_packet 选项。在“联网”选项卡的“内存”部分,恰当调整“允许的最大值”选项。完成值的调整后,点击“应用更改”按钮,并使用“MySQL 管理员”的“服务控制”屏幕重新启动服务器。也可以在 my.cnf 文件中直接调整该值 (添加 1 行,max_allowed_packet=xxM),或在 MySQL 中使用 SET max_allowed_packet=xxM。

设置 max_allowed_packet 时应保守些,这是因为传输 BLOB 数据需要一段时间。恰当地设置该值,使之与预期使用相符,并在必要时增大该值。

26.2.4.5.3. ;将文件写入数据库

要想将文件写入数据库,需要将文件转换为字节数组,然后将字节数组用作 INSERT 查询的参数。

在下述代码中,使用 FileStream 对象打开了 1 个文件,将其读入至字节数组,然后将其插入到文件表中:

[VB]

Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand

Dim SQL As String

Dim FileSize As UInt32
Dim rawData() As Byte
Dim fs As FileStream

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=test"

Try
    fs = New FileStream("c:\image.png", FileMode.Open, FileAccess.Read)
    FileSize = fs.Length

    rawData = New Byte(FileSize) {}
    fs.Read(rawData, 0, FileSize)
    fs.Close()

    conn.Open()

    SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)"

    cmd.Connection = conn
    cmd.CommandText = SQL
    cmd.Parameters.Add("?FileName", strFileName)
    cmd.Parameters.Add("?FileSize", FileSize)
    cmd.Parameters.Add("?File", rawData)

    cmd.ExecuteNonQuery()

    MessageBox.Show("File Inserted into database successfully!", _
    "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)

    conn.Close()
Catch ex As Exception
    MessageBox.Show("There was an error: " & ex.Message, "Error", _
        MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();

string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    fs = new FileStream(@"c:\image.png", FileMode.Open, FileAccess.Read);
    FileSize = fs.Length;

    rawData = new byte[FileSize];
    fs.Read(rawData, 0, FileSize);
    fs.Close();

    conn.Open();

    SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)";

    cmd.Connection = conn;
    cmd.CommandText = SQL;
    cmd.Parameters.Add("?FileName", strFileName);
    cmd.Parameters.Add("?FileSize", FileSize);
    cmd.Parameters.Add("?File", rawData);

    cmd.ExecuteNonQuery();

    MessageBox.Show("File Inserted into database successfully!",
        "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);

    conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
        "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
 
FileStream 对象的Read方法可用于将文件加载到字节数组中,该字节数组的大小是根据 FileStream 对象的Length属性确定的。

将字节数组指定为MySqlCommand 对象的参数后,调用 ExecuteNonQuery 方法,并将 BLOB 插入到文件表中。

26.2.4.5.4. ;将 BLOB 从数据库读取到磁盘上的文件

一旦将文件加载到了文件表中,就能使用MySqlDataReader 类来检索它。

在下述代码中,从文件表提取了 1 行,然后将数据装载到要写入至磁盘的FileStream 对象。

[VB]

Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim myData As MySqlDataReader
Dim SQL As String
Dim rawData() As Byte
Dim FileSize As UInt32
Dim fs As FileStream

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=test"

SQL = "SELECT file_name, file_size, file FROM file"

Try
    conn.Open()

    cmd.Connection = conn
    cmd.CommandText = SQL

    myData = cmd.ExecuteReader

    If Not myData.HasRows Then Throw New Exception("There are no BLOBs to save")

    myData.Read()

    FileSize = myData.GetUInt32(myData.GetOrdinal("file_size"))
    rawData = New Byte(FileSize) {}

    myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize)

    fs = New FileStream("C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write)
    fs.Write(rawData, 0, FileSize)
    fs.Close()

    MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)

    myData.Close()
    conn.Close()
Catch ex As Exception
    MessageBox.Show("There was an error: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
  

[C#]

MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader myData;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();

string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

SQL = "SELECT file_name, file_size, file FROM file";

try
{
    conn.Open();

    cmd.Connection = conn;
    cmd.CommandText = SQL;

    myData = cmd.ExecuteReader();

    if (! myData.HasRows)
        throw new Exception("There are no BLOBs to save");

    myData.Read();

    FileSize = myData.GetUInt32(myData.GetOrdinal("file_size"));
    rawData = new byte[FileSize];

    myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize);

    fs = new FileStream(@"C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write);
    fs.Write(rawData, 0, FileSize);
    fs.Close();

    MessageBox.Show("File successfully written to disk!",
        "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);

    myData.Close();
    conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
        "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
 
连接后,文件表的内容将被加载到MySqlDataReader 对象中。使用 MySqlDataReader 的GetBytes 方法将 BLOB 加载到字节数组,然后使用FileStream 对象将字节数据写入磁盘。

MySqlDataReader 的GetOrdinal 方法可用于确定命名列的整数索引。如果 SELECT 查询的列顺序发生变化,使用GetOrdinal 方法能够防止错误。

26.2.4.6. ;与 Crystal Reports 一起使用 MySQL Connector/NET

26.2.4.6.1. ;前言
Crystal Reports 是 Windows 应用程序开发人员用于通报文档生成的常用工具。在本节中,介绍了 Crystal Reports XI 与 MySQL 和 Connector/NET 一起使用的方法。

在 MySQL Connector/NET 安装的 Samples 目录的 CrystalDemo 子目录下,可找到完整的示例应用程序。

26.2.4.6.2. ;创建数据源

在 Crystal Reports 中创建报告时,在设计报告时,有两个用于访问 MySQL 数据的选项。

第 1 个选项是,设计报告时,使用 Connector/ODBC 作为 ADO 数据源。你能够浏览数据库,并使用拖放式操作选择表和字段以创建报告。该方法的缺点是,必须在应用程序中执行额外操作以生成与报告预期的数据集匹配的数据集。

第 2 个选项是在 VB.NET 中创建数据集,并将其保存为 XML 格式。随后,该 XML 文件可被用于设计报告。在应用程序中显示报告时,它的表现相当良好,但设计时的通用性较差,这是因为在创建数据集时,必须选择所有的相关列。如果忘记选择了某一列,在能够将列添加到报告前,必须重新创建数据集。

使用下述代码,可根据查询操作创建数据集,并将其写入磁盘。

[VB]

Dim myData As New DataSet
Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim myAdapter As New MySqlDataAdapter

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=world"

Try
    conn.Open()
    cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " _
        & "country.name, country.population, country.continent " _
        & "FROM country, city ORDER BY country.continent, country.name"
    cmd.Connection = conn

    myAdapter.SelectCommand = cmd
    myAdapter.Fill(myData)

    myData.WriteXml("C:\dataset.xml", XmlWriteMode.WriteSchema)
Catch ex As Exception
    MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
 

[C#]

DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
  "pwd=12345;database=test;";

try
{
  cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " +
  "country.name, country.population, country.continent " +
  "FROM country, city ORDER BY country.continent, country.name";
  cmd.Connection = conn;

  myAdapter.SelectCommand = cmd;
  myAdapter.Fill(myData);

  myData.WriteXml(@"C:\dataset.xml", XmlWriteMode.WriteSchema);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
  MessageBox.Show(ex.Message, "Report could not be created",
  MessageBoxButtons.OK, MessageBoxIcon.Error);
}
设计报告时,可将该代码生成的 XML 文件用作 ADO.NET XML 数据源。

如果你选择使用 Connector/ODBC 来设计报告,可从dev.mysql.com下载它。

26.2.4.6.3. ;创建报告
对于大多数应用目的,标准的报告向导应能帮助你完成报告的最初创建。要想启动向导,打开 Crystal Reports 并从“文件”菜单选择“New > Standard Report”选项。

向导首先要求你提供数据源。如果你正使用 Connector/ODBC 作为数据源,选择数据源时,请使用 OLE DB (ADO) 树的“用于 ODBC 的 OLEDB provider”选项,,而不是来自 ODBC (RDO) 的对应选项。如果你使用的是已保存的数据集,请选择 ADO.NET (XML) 选项,并浏览你保存的数据集。

在报告的创建过程中,剩余部分将由向导自动完成。

创建完报告后,选择“文件”菜单中的“Report Options...”菜单项。取消对“Save Data With Report”(与报告一起保存数据) 选项的选择。这样,就能防止保存的数据干扰应用程序中的数据加载操作。

26.2.4.6.4. ;显示报告

要想显示报告,首先用报告所需的数据填充数据集,然后加载报告,并将其与绑定到数据集。最后,将报告传递给 crViewer 控制,以便向用户显示它。

在显示报告的项目中,需要下述引用:

·         CrytalDecisions.CrystalReports.Engine

·         CrystalDecisions.ReportSource

·         CrystalDecisions.Shared

·         CrystalDecisions.Windows.Forms

在下述代码中,假定你使用数据集 (用创建数据源中给出的代码保存的数据集) 创建了报告,并在名为“myViewer”的表单上有 1 个 crViewer 控件。

[VB]

Imports CrystalDecisions.CrystalReports.Engine
Imports System.Data
Imports MySql.Data.MySqlClient

Dim myReport As New ReportDocument
Dim myData As New DataSet
Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim myAdapter As New MySqlDataAdapter

conn.ConnectionString = _
    "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=test"

Try
    conn.Open()

    cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " _
        & "country.name, country.population, country.continent " _
        & "FROM country, city ORDER BY country.continent, country.name"
    cmd.Connection = conn

    myAdapter.SelectCommand = cmd
    myAdapter.Fill(myData)

    myReport.Load(".\world_report.rpt")
    myReport.SetDataSource(myData)
    myViewer.ReportSource = myReport
Catch ex As Exception
    MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

[C#]

using CrystalDecisions.CrystalReports.Engine;
using System.Data;
using MySql.Data.MySqlClient;

ReportDocument myReport = new ReportDocument();
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    cmd.CommandText = "SELECT city.name AS cityName, city.population AS CityPopulation, " +
        "country.name, country.population, country.continent " +
        "FROM country, city ORDER BY country.continent, country.name";
    cmd.Connection = conn;

    myAdapter.SelectCommand = cmd;
    myAdapter.Fill(myData);

    myReport.Load(@".\world_report.rpt");
    myReport.SetDataSource(myData);
    myViewer.ReportSource = myReport;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message, "Report could not be created",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
}

使用相同的查询 (用于生成前面保存的数据集),可生成新的数据集。一旦填充了数据集,可使用 ReportDocument 加载报告文件,并将其与数据集绑定在一起。ReportDocument 是作为 crViewer 的 ReportSource 而传递的。

使用 Connector/ODBC 从单个表创建报告时,采用了相同的方法。数据集替换报告中使用的表,并恰当显示报告。

如果报告是使用 Connector/ODBC 从多个表创建的,在我们的应用程序中必须创建具有多个表的数据集。这样,就能用数据集中的报告替换报告数据源中的各个表。

在我们的 MySqlCommand 对象中提供多条 SELECT 语句,通过该方式,用多个表填充数据集。这些 SELECT 语句基于 SQL 查询,如数据库菜单“Show SQL Query”选项中的“Crystal Reports”中显示的那样。假定有下述查询:

SELECT `country`.`Name`, `country`.`Continent`, `country`.`Population`, `city`.`Name`, `city`.`Population`
FROM `world`.`country` `country` LEFT OUTER JOIN `world`.`city` `city` ON `country`.`Code`=`city`.`CountryCode`
ORDER BY `country`.`Continent`, `country`.`Name`, `city`.`Name`

该查询将被转换为两条 SELECT 查询,并以下述代码显示:

[VB]

Imports CrystalDecisions.CrystalReports.Engine
Imports System.Data
Imports MySql.Data.MySqlClient

Dim myReport As New ReportDocument
Dim myData As New DataSet
Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim myAdapter As New MySqlDataAdapter

conn.ConnectionString = "server=127.0.0.1;" _
    & "uid=root;" _
    & "pwd=12345;" _
    & "database=world"

Try
    conn.Open()
    cmd.CommandText = "SELECT name, population, countrycode FROM city ORDER BY countrycode, name; " _
        & "SELECT name, population, code, continent FROM country ORDER BY continent, name"
    cmd.Connection = conn

    myAdapter.SelectCommand = cmd
    myAdapter.Fill(myData)

    myReport.Load(".\world_report.rpt")
    myReport.Database.Tables(0).SetDataSource(myData.Tables(0))
    myReport.Database.Tables(1).SetDataSource(myData.Tables(1))
    myViewer.ReportSource = myReport
Catch ex As Exception
    MessageBox.Show(ex.Message, "Report could not be created", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

[C#]

using CrystalDecisions.CrystalReports.Engine;
using System.Data;
using MySql.Data.MySqlClient;

ReportDocument myReport = new ReportDocument();
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;

conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();

conn.ConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    cmd.CommandText = "SELECT name, population, countrycode FROM city ORDER " +
        "BY countrycode, name; SELECT name, population, code, continent FROM " +
        "country ORDER BY continent, name";
    cmd.Connection = conn;

    myAdapter.SelectCommand = cmd;
    myAdapter.Fill(myData);

    myReport.Load(@".\world_report.rpt");
    myReport.Database.Tables(0).SetDataSource(myData.Tables(0));
    myReport.Database.Tables(1).SetDataSource(myData.Tables(1));
    myViewer.ReportSource = myReport;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message, "Report could not be created",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
}
 
应将 SELECT 语句按字母顺序排列,这点很重要,原因在于,这是报告希望其源表所具有的顺序。对于报告中的每个表,均需要一条 SetDataSource 语句。

该方法会导致性能问题,这是因为 Crystal Reports 必须在客户端一侧将表绑定在一起,与使用以前保存的数据集相比,速度较慢。

26.2.4.7. ;在 MySQL Connector/NET 中处理日期和时间信息

26.2.4.7.1. ;前言
MySQL 和。NET 语言处理日期和时间信息的方式是不同的,MySQL 允许使用无法由。NET 数据类型表示的日期,如“0000-00-00 00:00:00如果处理步当,该差异会导致问题。

在本节中,介绍了使用 MySQL Connector/NET 时恰当处理日期和时间信息的方法。

26.2.4.7.2. ;使用无效日期时的问题
对于使用无效日期的开发人员来说,数据处理方面的差异会导致问题。无效的 MySQL 日期无法被加载到。NET DateTime对象中,包括NULL 日期。

由于该原因,不能用MySqlDataAdapter 类的 Fill 方法填充.NET DataSet 对象,这是因为无效日期会导致 System.ArgumentOutOfRangeException 异常。

26.2.4.7.3. ;限制无效日期
对日期问题的最佳解决方案是,限制用户输入无效日期。这即可在客户端上进行,也可在服务器端进行。

在客户端上限制无效日期十分简单,即总使用。NET DateTime 类来处理日期。DateTime 类仅允许有效日期,从而确保了数据库中的值也是有效的。该方法的缺点是,在使用。NET 和非。NET 代码操作数据库的混合环境下不能使用它,这是因为各应用程序必须执行自己的日期验证。

MySQL 5.0.2 和更高版本的用户可使用新的传统 SQL 模式来限制无效日期值。关于使用传统 SQL 模式的更多信息,请参见http://dev.mysql.com/doc/mysql/en/server-sql-mode.html

26.2.4.7.4. ;处理无效日期
强烈建议在你的。NET 应用程序中应避免使用无效日期,尽管如此,也能 tongguo MySqlDateTime 数据类型使用无效日期。

MySqlDateTime数据类型支持 MySQL 服务器支持的相同日期值。MySQL Connector/NET 的默认行为是,对有效的日期值返回 1 个。NET DateTime 对象,对无效日期值返回错误。可以更改该默认方式,使 MySQL Connector/NET 为无效日期返回MySqlDateTime 对象。

要想使 MySQL Connector/NET 为无效日期返回MySqlDateTime 对象,可在连接字符串中添加下行:

  Allow Zero Datetime=True
  

请注意,使用MySqlDateTime 类仍会产生问题。下面介绍了一些已知问题:

1.    无效日期的数据绑定仍会导致错误 (零日期 0000-00-00 看上去不存在该问题)。

2.    ToString方法返回按标准 MySQL 格式进行格式处理的日期 (例如,2005-02-23 08:50:25)。这与。NET DateTime 类的ToString 行为不同。

3.    MySqlDateTime类支持 NULL 日期,但。NET DateTime 类不支持 NULL 日期。如果未首先检查 NULL,在试图将 MySQLDateTime 转换为 DateTime 时,会导致错误。

由于存在上述已知事宜,最佳建议仍是,在你的应用程序中仅使用有效日期。

26.2.4.7.5. ;处理 NULL 日期

.NET DateTime数据类型不能处理NULL 值。同样,在查询中为DateTime 变量赋值时,必须首先检查值是否是 NULL。

使用MySqlDataReader 时,在赋值前,应使用。IsDBNull方法检查值是否为NULL:

[VB]

If Not myReader.IsDBNull(myReader.GetOrdinal("mytime")) Then
    myTime = myReader.GetDateTime(myReader.GetOrdinal("mytime"))
Else
    myTime = DateTime.MinValue
End If
  

[C#]

if (! myReader.IsDBNull(myReader.GetOrdinal("mytime")))
    myTime = myReader.GetDateTime(myReader.GetOrdinal("mytime"));
else
    myTime = DateTime.MinValue;
  
NULL值能够在数据集中使用,也能将其绑定以构成控件,无需特殊处理。

26.2.5. MySQL Connector/NET 变更史

26.2.5.1. 版本 2.0.0

·         更正了在未填充 Connection.Database 的情况下使用存储程序时出现的异常 (Bug #11450) 。

·         特定的残缺查询将触发“连接必须是有效和打开的”错误消息 (Bug #11490) 。

26.2.5.2. 版本 1.0.7

·         调用其某一参数含有特殊字符 (如“@”) 的存储程序将产生异常。注意,必须启用ANSI_QUOTES 才会使之成为可能 (Bug #13753) 。

·         如果语句包含对相同参数的多个引用,无法对其进行预处理 (Bug #13541) 。

·         Ping() 方法不更新 Connection 对象的 State 属性 (Bug #13658) 。

26.2.5.3. 版本 1.0.6

·         Nant 构建序列有问题(Bug #12978)

·         如果传递的第 1 个值是 NULL,参数的串行化操作失败 (Bug #13276) 。

·         含下述字符的字段名将导致错误:()%<>/ (Bug #13036) 。

·         MySQL Connector/NET 1.0.5 安装程序不能同时安装 MySQL Connector/NET 1.0.4. (Bug #12835)。

·         在 Mono 上 MySQL Connector/NET 1.0.5 不能连接 (Bug #13345) 。

26.2.5.4. 版本 1.0.5

·         连接字符串中有多个主机时,MySQL Connector/NET 无法与列表中的 1 个主机相连 (Bug #12628) 。

·         MySQL Connector/NET 将新的十进制数据类型解释为字节数组 (Bug #11294) 。

·         不支持cp1250 字符集 (Bug #11621) 。

·         当。NET 线程池无可用的工作线程时,连接可能失败 (Bug #10637) 。

·         十进制参数导致语法错误 (Bug #11550, Bug #10486, Bug #10152)。

·         如果存储程序不含参数,调用存储程序将导致异常 (Bug #11542) 。

·         特定的残缺查询将触发“连接必须是有效和打开的”错误消息 (Bug #11490) 。

·         除了默认数据库外,MySqlCommandBuilder 类不能处理引用了其他数据库中表的查询 (Bug #8382) 。

·         MySQL Connector/NET 无法特定的局部设置一起正常工作 (WL#8228)。

·         未填充Connection.Database 时使用存储程序导致异常 (Bug #11450) 。

·         读取TIMESTAMP 列时产生异常 (Bug #7951) 。

·         用换行符隔开参数时,无法识别参数 (Bug #9722) 。

·         在初始连接上未设置连接字符串时,调用MySqlConnection.clone 将导致错误 (Bug #10281) 。

·         增加了对从 MySQL Connector/NET 调用存储函数的支持 (Bug #10644) 。

·         MySQL Connector/NET 不能连接到 MySQL 4.1.14. (Bug #12771)。

·         用设计器添加了MySqlConnection 对象时,无法设置 ConnectionString 属性 (Bug #12551, Bug #8724)。

26.2.5.5. 版本 1.0.4 1-20-05

·         Bug #7243:调用准备导致异常 [已更正]。

·         更正了与预处理语句有关的另一个小问题。

·         Bug #7258:MySqlCommand.Connection 返回 IDbConnection [已更正]。

·         Bug #7345:MySqlAdapter.Fill 方法抛出错误消息:需要非负数值 [已更正]。

·         Bug #7478:MySqlCommand 中的克隆方法缺陷 [已更正]。

·         Bug #7612:当字段为 NULL 时,MySqlDataReader.GetString(index) 返回了非 Null 值 [已更正]。

·         Bug #7755:如果列是无符号类型,MySqlReader.GetInt32 抛出异常 [已更正]。

·         Bug #7704:GetBytes 不再工作 [已更正]。

·         Bug #7724:引用字符“\222”在 EscapeString 中未被引用 [已更正]。

·         更正了命名管道不能与某些 Blob 功能一起工作的问题。

·         更正了与共享内存连接有关的问题。

·         Bug #7436:与多个结果集有关的问题 [已更正]。

·         在 API 参考文档中增加了多个主题。

26.2.5.6. 版本 1.0.3-gamma 12-10-04

·         使 MySQL 成为默认的命名管道名称。

·         现在,连接时 SHOW COLLATION 可用于检索完整的字符集 ID 列表。

·         更正了无效字符集索引:200 (Bug #6547) 。

·         安装器现在包含了多个选项,可安装至 GAC 中,并创建“开始”菜单项。

·         Bug #6863:MySqlCommand 参数中的 Int64 支持 [已更正]。

·         对于连接,现在无需在连接字符串上给出数据库。

·         Bug #6770:MySqlDataReader.GetChar(int i) 抛出 IndexOutOfRange 异常 [已更正]。

·         更正了因具有不同行数的多个结果集而导致的问题。

·         Bug #6983:再次抛出异常时异常堆栈跟踪丢失 [已更正]。

·         更正了与使用预处理语句检测 Null 值有关的主要问题。

·         Bug #6902:解析存储程序参数时的错误 [已更正]。

·         Bug #6668:存储程序的整数输出参数返回为字符串 [已更正]。

·         Bug #7032:按文本分类的数据表中的 MySqlDateTime,无数据 [已更正]。

·         Bug #7133:使用 inout 参数时的无效查询字符串 [已更正]。

·         Bug #6831:与 MySQL 4.0 一起时,测试失败,原因在于表名的大小写敏感性 [已更正]。

·         Bug #7132:插入 DateTime 导致 System.InvalidCastException 的抛出 [已更正]。

·         Bug #6879:使用 DATE_ADD-function 时的 InvalidCast[已更正]。

·         Bug #6634:1 个打开的连接被主机系统关闭 [已更正]。

·         为 MySqlConnection 添加了 ServerThread 属性以显示服务器线程 ID。

·         为 MySqlConnection 增加了 Ping 方法。

·         将测试包的名称更改为 MySql.Data.Tests.dll。

26.2.5.7. 版本 1.0.2-gamma 04-11-15

·         更正了与 MySqlBinary 有关的问题,其中,无法使用字符串值更新扩展的文本列。

·         更正了使用定制安装时忽略的安装目录问题 (Bug #6329)。

·         更正了设置命令文本将命令留在预处理状态的问题。

·         更正了 MySqlParameter 双类型处理问题 (字符串 parameterName,对象值)(Bug #6428)。

·         更正了填充数据集时返回零日期“0000-00-00”错误 (Bug #6429)。

·         更正了调用存储程序可能会导致“Illegal mix of collations”(非法校对组合) 的问题。

·         增加了 charset 连接字符串选项。

·         更正了#HY000“Illegal mix of collations”(非法校对组合)(latin1_swedish_ci,IMPLICIT) 和 (utf8_general_ (Bug #6322) 问题。

·         增加了 TableEditor CS 和 VB 示例。

·         更正了关于 UCS-2 的 Charset-map 问题 (Bug #6541)。

·         更新了安装器,包含了新的示例。

·         更正规了 Long 插入耗时很长的问题 (Bug #5453)。

·         更正了对象无法被处理的问题 (Bug #6649)。

·         提供方正将服务器指定的字符集用作默认字符集。

26.2.5.8. 版本 1.0.1-beta2 04-10-27

·         更正了 MySqlParameter(string, object) 构造函数中的可能缺陷BUG #5602

·         更正了BUG #5458,在 longtext 列上调用 GetChars 将抛出异常。

·         更正了BUG #5474,无法运行存储程序来填充 mysqlcommand.parameters。

·         更正了BUG #5469,设置 DbType 时抛出 NullReferenceException。

·         更正了在关闭套接字之前连接器无法发出 CMD_QUIT 的问题。

·         更正了BUG #5392,MySqlCommand 在字符串文本内容中发现作为参数的“?”。

·         更正了与 ConnectionInternal 有关的问题,其中,1 个键可能会被添加多次。

·         当服务器版本为 4.1.2 或更高时,CP1252 仅用于 Latin1。

·         更正了BUG #5388,如果 1 行为 NULL,DataReader 通报所有行均为 NULL。

·         虚拟化了驱动子系统,以便未来版本能轻易地支持客户端或嵌入式服务器。

·         再次使用字段缓冲,以减少内存分配并增加速度。

·         更正了相应的问题,使用接口时使用旧语法将导致问题。

·         对于写入流操作,使用 PacketWriter 取代 Packet。

·         在 CompressedStream 中再分解压缩代码,以清理 NativeDriver。

·         增加了用于在预处理命令上重置命令文本的测试范例。

·         更正了给定 Null 值时 MySqlParameterCollection.Add() 将抛出不明异常的问题 (Bug #5621)。

·         更正了 MySqlCommand() 中的构造函数初始化问题 (Bug #5613)。

·         更正了解析“;”字符的问题 (Bug #5876)。

·         更正了在 DbType 设置器中丢失引用的问题 (Bug #5897)。

·         更正了使用 YEAR 数据类型时的 System.OverflowException 问题 (Bug #6036)。

·         增加了聚合函数测试 (实际上不是缺陷)。

·         更正了浮点参数 (double, numeric, single, decimal) 的序列化问题 (Bug #5900)。

·         IsNullable 错误 (Bug #5796)。

·         更正了不遵守连接字符串上给出的连接寿命的问题。

·         更正了不遵守 Min Pool Size(最小池大小) 的问题。

·         更正了 MySqlDataReader 和“show tables from ...”(从显示表) 行为 (Bug #5256)。

·         实施了 SequentialAccess。

·         更正了发现第 1 个 0 后 MySqlDateTime 在所有 subseq.records 上设置 IsZero 属性的问题 (Bug #6006)。

·         更正了无法正确显示中文字的问题 (Bug #5288)。

·         还更正了俄文字符支持。

·         更正了 Method TokenizeSql() 仅将有限的有效字符用于参数的问题 (Bug #6217)。

·         更正了丢失 resx 文件的 NET Connector 源 (Bug #6216)。

·         更正了与检索/更新查询一起使用是会导致问题的 DBNull 值 (Bug #5798) 。

·         更正了仍有另一个“未设置给对象实例的对象引用”(Bug #5496)。

·         更正了 PacketReader 中的问题,其中,会试图在 EnsureCapacity 中分配错误的缓冲大小。

·         更正了 GetBoolean 返回错误值的问题 (Bug #6227)。

·         更正了带有 GetString(index) 的 DataReader 一起读取 BLOB 时的 IndexOutOfBounds 问题 (Bug #6230)。

26.2.5.9. 版本 1.0.0 04-09-01

·         更正了 BUG# 3889,不能正确支持 Thai 编码。

·         更新了很多测试范例。

·         更正了与使用压缩有关的问题。

·         将贝塔 1 版本的版本号扩充为 1.0.0。

·         增加了用于安装器的 COPYING.rtf 文件。

·         删除了所有的 XML 注释警告 (以后将更好地清理它们)。

·         删除了一些对 ByteFX 的最近引用。

26.2.5.10. 版本 0.9.0 04-08-30

·         为预处理语句增加了测试定位器。

·         目前,所有类型的类均实施了 SerializeBinary 方法,用于将其数据发送给 PacketWriter。

·         增加了 PacketWriter 类,允许将来的低内存大对象处理。

·         更正了运行预处理语句和存储程序中存在的很多小缺陷。

·         更改了多条命令,使得在执行带有特定参数 (采用旧语法模式) 的存储程序时不再抛出异常。

·         SingleRow 现在工作正常,即使在存在限制的情况下也同样。

·         GetBytes 目前仅作用在二进制列上。

·         Logger 现在能够截短长的 SQL 命令,从而使得 blob 列不会“撑爆”日志。

·         主机和数据库目前的默认值为“”,除非作了其他设置。

·         更正了 BUG# 5214,忽略了连接超时。

·         增加了测试范例,针对 bug# 5051:GetSchema 不能正确工作。

·         更正了当列为关键字时 GetSchema 为 IsUnique 返回“假”的问题。

·         MySqlDataReader GetXXX 方法目前采用了字段级 MySqlValue 对象,不执行转换。

·         更正了 BUG# 5097:DataReader 为时间列返回 NULL。

·         A 增减了针对 LOAD DATA LOCAL INFILE 的测试范例。

·         增加了 replacetext custom nant 任务。

·         增加了 CommandBuilderTest 定位器。

·         为 CommandBuilder 增加了 Last One Wins(最后一个胜出) 特性。

·         更正了持续性安全信息问题。

·         更正了 GetBool,使得 1, true, "true";和"yes";均可表示 trueWL# 2024,从而使得参数标志成为可配置的。

·         增加了"old syntax";连接字符串参数,允许使用“@”参数标记符。

·         更正了Bug #4658,MySqlCommandBuilder。

·         更正了Bug #4864,如果“Persist Security Info”(持续性安全信息) 为假,ByteFX.MySqlClient 将对密码进行缓冲处理。

·         在所有的源文件中更新了许可标志,以包含 FLOSS 异常。

·         针对目前所有的 MySql 类型,增加了新的。Types 名称空间和具体实施。

·         增加了作为 MySqlField 子类的 MySqlField41。

·         更改了很多类,使之能够使用新的。Types 类型。

·         将 enum int 类型更改为 Int32,将 short 类型更改为 Int16,并将 bigint 类型更改为 Int64。

·         增加了伪类型 UInt16、UInt32 和 UInt64,允许创建无符号参数。

·         现在,从连接池拉出连接时,连接将被复位。

·         在驱动程序中再次分解了 auth 代码,使得其即能用于 auth,也能用于 reset。

·         在 PoolingTests.cs 中增加了 UserReset 测试。

·         现在,使用 COM_CHANGE_USER 从池中拉出连接时,连接将被复位。

·         实现了 SingleResultSet 行为。

·         实现了对 unicode 的支持。

·         为 utf-8 和 ucs-2 增加了字符集映射。

·         更正了Bug #4520,使用 bytefx .net mysql 驱动时,时间字段溢出。

·         在数据类型测试定位器中修改了时间测试,以便能够检查“hours > 24”的时间跨度。

·         更正了Bug #4505,在 ByteFx.Data.MySqlClient.MySqlParameter 中带有反斜杠转义的错误字符串。

·         为参数测试范例 TestQuoting 增加了代码,以测试反斜线符号。

·         更正了Bug #4486,与 multi-word 列名一起工作时,mysqlcommandbuilder 失败。

·         更正了 TokenizeSql 中的缺陷,其中,下划线将中止获取参数名中的字符。

·         为列名空间增加了测试范例。

·         更正了 bug# 4324,MySqlDataReader.GetBytes 不能正确工作。

·         为 DataReader 测试定位器增加了 GetBytes() 测试范例。

·         现在,能够将 InternalConnection.Configure 中的所有服务器变量读入到 Hashtable。

·         目前使用字符串 [],用于 CharSetMap 中的索引映射。

·         为 SQL 中的 carriage 返回增加了 CRInSQL 测试范例。

·         在 Driver.ctor 中,将 maxPacketSize 设为默认值。

·         更正了bug #4442,在参数上设置 MySqlDbType 的操作不设置一般类型。

·         删除了过时的列类型 Long 和 LongLong。

·         更正了 bug# 4071,在连接字符串上使用“use pipe”时,抛出溢出异常。

·         将关键字“use pipe”更改为“pipe name”或“pipe”。

·         允许从单个查询读取多个结果集。

·         为 ServerStatusFlags enum 增加了标志属性。

·         将 ServerStatus enum 的名称更改为 ServerStatusFlags。

·         更正了BUG #4386,插入的数据行未正确更新。

·         更正了bug #4074,错误处理表明创建了表。

·         将 Packet.ReadLenInteger 更改为 ReadPackedLong,并增加了 packet.ReadPackedInteger,它总读取用 2、3、4 组装的整数。

·         增加了 syntax.cs 测试定位器,以测试各种 SQL 语法缺陷。

·         更正了 bug# 4149,对时间值的不当处理。现在,值“00:00:00”不再被当作 Null。

·         将所有的测试包文件移到了 TestSuite 文件夹。

·         更正了空列会将结果信息包指针向后移的问题。

·         增加了新的 nant 创建脚本。

·         更正了BUG #3917,清除表名,以便能在下一 GenerateSchema 执行期间恰当地重新生成它。

·         更正了bug #3915,GetValues 总返回 0,而且总是试图复制所有字段,而不是根据所传入数组的大小。

·         实施了共享内存访问协议。

·         实施了针对的 MySQL 4.1 的预处理语句。

·         实施了针对 MySQL 5.0 的存储程序。

·         将 MySqlInternalConnection 重新命名为 InternalConnection。

·         SQL 现在被解释为字符,更正了与其他语言有关的问题。

·         增加了日志功能,并允许批连接字符串选项。

·         更正了bug #3888,设置 DataAdapter 属性时未设置 RowUpdating 事件。

·         更正了字符集映射中存在的缺陷。

·         实施了 4.1 鉴定。

·         改善了驱动中的 open/auth 代码。

·         改善了在连接过程中连接位的设置方式。

·         现在,在初始的握手阶段,将数据库名传递给了服务器。

·         将客户端的名称空间更改为 MySql.Data.MySqlClient。

·         将客户端的装配名称更改为 MySql.Data.dll。

·         将所有源文件中的许可文本更改为了 GPL。

·         增加了 MySqlClient.build Nant 文件。

·         删除了 mono 批处理文件。

·         将一些未使用的文件移到了 notused 文件夹,从而使得 nant 创建文件能够使用通配符。

·         实施了共享内存访问。

·         对代码结构进行了较大修补。

·         现在,预处理语句能够在 MySql 4.1.1 和更高版本中使用。

·         对 4.0、4.1.0 和 4.1.1 完成了 auth 实施。

·         将名称空间从 MySQL.Data.MySQLClient 更改为 MySql.Data.MySqlClient。

·         更正了 CharSetMapping 中存在的缺陷,其中,它试图将文本名称用作 ints。

·         将名称空间更改为 MySQL.Data.MySQLClient。

·         集成了来自 UC2004 的 auth 变动。

·         更正了在读取数据之前和值后、在 datareader 上调用任何 GetXXX 方法时不能抛出恰当异常的缺陷 (感谢 Luca Morelli morelli.luca@iol.it)。

·         在 parameter.cs 中增加了 TimeSpan 代码,以便能恰当地将 timespan 对象处理为 mysql 时间格式 (感谢 Gianluca Colombo g.colombo@alfi.it)。

·         为参数序列化代码增加了 TimeStamp。防止 DataAdatper 不正常的更新 (感谢 MIchael King)。

·         更正了 MySqlHelper.cs 中的拼写错误 (感谢 Patrick Kristiansen)。

26.2.5.11. 版本 0.76

·         驱动程序现在能使用握手协议中给定的字符集编号创建编码。

·         更改了命令编辑器,使之指向 MySqlClient.Design。

·         更正了 Version.isAtLeast 中的缺陷。

·         更改了 DBConnectionString,使之能够支持对 MySqlConnectionString 所作的更改。

·         删除了 SqlCommandEditor 和 DataAdapterPreviewDialog。

·         在很多地方采用了新的 Long 返回值。

·         集成了新的 CompressedStream 类。

·         更改了 ConnectionString 并增加了多项属性,从而使之能够在 MySqlClient.Design 中使用。

·         更改了 packet.cs,以支持 ReadLenInteger 中的较新长度。

·         更改了其他类,以使用 MySqlConnectionString 的新属性和字段。

·         现在,ConnectionInternal 能够使用 PING 命令查看服务器是否可用。

·         将工具箱位图移到了 resource/下。

·         更改 field.cs,允许值直接来自行缓冲器。

·         进行了相应的更改,以使用新的 driver.Send 语法。

·         使用了新的信息包排队系统。

·         开始着手进行“损坏的”压缩信息包处理。

·         更正了 StreamCreator 中的缺陷,无法连接到主机将导致无限循环 (感谢 Kevin Casella)。

·         改善了 connectstring 处理。

·         将设计器移到了 Pro 产品中。

·         从 command.cs 删除了一些旧的、被注释掉的代码。

·         更正了与压缩有关的 1 个问题。

·         更正了连接对象,打开连接前抛出的异常不会使连接保持在连接状态 (感谢 Chris Cline)。

·         增加了 GUID 支持。

·         更正了序列混乱缺陷 (感谢 Mark Reay)。

26.2.5.12. 版本 0.75

·         现在,可将 Enum 值作为参数值加以支持 (感谢 Philipp Sumi)。

·         支持 Year 数据类型。

·         更正了压缩问题。

·         更正了以 TimeSpan 作为值的参数无法恰当序列化的缺陷。

·         更正了默认 ctor 不能设置默认连接字符串值的缺陷。

·         为一些新成员增加了一些 XML 注释。

·         着手更正/改善压缩处理事宜。

·         改善了 ConnectionString 处理功能,使之能够与 SqlClient 设定的标准更好地匹配。

·         如果用户名未包含在连接字符串中,将抛出 MySqlException。

·         如果在连接字符串中未指定,本地主机将用作默认主机。

·         如果在连接打开的同时试图设置连接字符串,将抛出异常。

·         对 ConnectionString 文档进行了小的修改。

·         删除了 MultiHostStream 和 MySqlStream。采用 Common/StreamCreator 取而代之。

·         增加了对“Use Pipe”连接字符串值的支持。

·         增加了 Platform 类,以便能更容易地访问平台的实用工具功能。

·         更正了小的连接池缺陷,即,在 IsAlive 失败后,不能创建新的连接。

·         增加了 Platform.cs 和 StreamCreator.cs。

·         更正了 Field.cs,以便能恰当处理 4.1 版分格的时间戳。

·         将 Common.Version 更改为 Common.DBVersion,以避免名称冲突。

·         更正了 field.cs,从而使得文本列能返回正确的字段类型 (感谢 beni27@gmx.net)。

·         增加了 MySqlError 类,以提供对错误代码的一些引用 (感谢 Geert Veenstra)。

26.2.5.13. 版本 0.74

·         增加了 Unix 套接字支持 (感谢 Mohammad DAMT [md@mt.web.id])。

·         没有可用数据时,仅调用 Thread.Sleep。

·         该井了参数数据中引用字符的转义特性。

·         删除了 parameter.cs 中易造成误解的注释。

·         更正了连接池缺陷。

·         再次更正了相同的连接池缺陷!! ;-)

·         更正了 ConnectionSTring 编辑器对话框 (感谢 marco p (pomarc))。

·         现在,在连接字符串中支持 UserId(感谢 Jeff Neeley)。

·         创建非输入参数时抛出异常 (感谢 Ryan Gregg)。

·         增加了更多文档。

·         提供了新的 MultiHostStream 能力。诚挚感谢 Dan Guisinger 对此的贡献。是他首次提供了在连接字符串上支持多台机器的代码和观念。

·         增加了大量文档。仍有很多文档需要增加。

·         更正了与 0.73 有关的速度事宜。

·         更改了 MySqlDataStream 中的 Thread.Sleep(0),以便在不需要等待时优化性能 (感谢 Todd German)。

·         预先将 idlepools 填充到了 MinPoolSize。

·         个高质量 MySqlPool 死锁条件以及愚蠢的缺陷,其中,CreateNewPooledConnection 从不为连接池添加新连接。此外,还更正了 MySqlStream.ReadBytes 和 ReadByte,从而不再使用并非始终正确的 TicksPerSecond。(感谢 Matthew J. Peddlesden)。

·         修正了精度和标度 (感谢 Matthew J. Peddlesden)。

·         为流读取方法增加了 Thread.Sleep(1),使之对 CPU 更友好 (感谢 Sean McGinnis)。

·         更正了 ExecuteReader 有时会返回 Null 的问题 (感谢 Lloyd Dupont)。

·         更正了与 Null 字段处理有关的主要缺陷 (感谢 Naucki)。

·         封装了针对 max_allowed_packet 的查询,以及 Try Catch 中的字符集 (并设置为默认)。

·         更正了套接字未能恰当关闭的问题 (感谢 Steve)。

·         更正了 ExecuteNonQuery 不能始终返回正确值的问题。

·         更正了 InternalConnection,不使用@@session.max_allowed_packet,而是使用@@max_allowed_packet。(感谢 Miguel)。

·         增加了很多新 XML 文档行。

·         更正了 SQL 解析功能,不发送控查询 (感谢 Rory)。

·         更正了阅读器在关闭时不能 unpeeking 信息包的问题。

·         更正了不能处理用户变量的问题 (感谢 Sami Vaaraniemi)。

·         更正了 MySqlPool 中的循环检查功能 (感谢 Steve M. Brown)。

·         更正了 ParameterCollection.Add 方法,以与 SqlClient 匹配 (感谢 Joshua Mouch)。

·         更正了 ConnectionSTring 解析功能,以处理布尔类型的 NO 和 YES,以及非小写值 (感谢 Naucki)。

·         增加了 InternalConnection 类,修改了连接池功能。

·         实现了 Persist Security Info(持续性安全信息)。

·         为项目增加了 security.cs 和 version.cs。

·         更正了 Parameter.cs 中的 DateTime 处理功能 (感谢 Burkhard Perkens-Golomb)。

·         更正了某些类型抛出 cast 异常的参数序列化问题。

·         更正了 DataReader,转换所有的返回值以防止抛弃错误 (感谢 Keith Murray)。

·         为 Command.ExecuteReader 增加了代码,如果初始 SQL 命令抛出异常,将返回 Null(感谢 Burkhard Perkens-Golomb)。

·         构造了与重组一起引入 ExecuteScalar 缺陷。

·         进行了重新构造,允许 LOCAL DATA INFILE,以及更好的信息包排序。

·         更正了与重组有关的数个缺陷。

·         完成了前期工作,支持 Mysql 4.1 中更安全的密码。不再支持 4.1 版中的旧密码。

·         正确处理系统参数后显示参数 (Adam M. (adammil))。

·         现在,可将字符串直接赋给 blob 字段 (Adam M.)。

·         更正了浮点参数 (感谢 Pent)。

·         改善了参数 ctor 和 ParameterCollection.Add 方法,以更好地匹配 SqlClient(感谢 Joshua Mouch)。

·         更正了 Connection.CreateCommand 以返回 MySqlCommand 类型。

·         更正了连接字符串设计器的对话框问题 (感谢 Abraham Guyt)。

·         更正了与发送命令无法总是读取响应信息包有关的问题 (感谢 Joshua Mouch)。

·         更正了某些 Blob 类型无法被处理的参数序列化问题 (感谢 Sean McGinnis)。

·         从 DataReader 代码中删除了伪 MessageBox.show(感谢 Joshua Mouch)。

·         更正了 split sql 代码中的丑陋缺陷 (感谢所有人! :-) )

26.2.5.14. 版本 0.71

·         更正了 MySqlStream 中的缺陷,即可能会读取过多数据 (感谢 Peter Belbin)。

·         实现了 HasRows(感谢 Nash Pherson)。

·         更正了大于 256 列的表会导致异常的问题 (感谢 Joshua Kessler)。

·         更正了以“;”结束的 SQL 语句会导致问题的缺陷 (感谢 Shane Krueger)。

·         更正了驱动中的缺陷,即,错误消息被截去 1 个字符 (感谢 Shane Krueger)。

·         使得 MySqlException 成为可序列化的 (感谢 Mathias Hasselmann)。

26.2.5.15. 版本 0.70

·         更新了一些字符代码页,使之更加准确。

·         更正了阅读器能够在已有打开阅读器的连接上打开的问题。

·         发布了 0.70。

·         将测试移至单独的 MySqlClientTests 下。

·         更正了驱动程序序列混乱的愚蠢问题 (感谢 Peter Belbin)。

·         增加了一些管道测试。

·         将默认最大池大小增加到 50。

·         与 Mono 0-24 一起进行了编译。

·         更正了连接和数据阅读器处理问题。

·         为参数序列化增加了字符串数据类型处理功能。

·         更正了抛出异常后在驱动程序中出现的顺序问题 (感谢 Burkhard Perkens-Golomb)。

·         增加了对 CommandBehavior.SingleRow 到 DataReader 的支持。

·         更正了命令 sql 的处理功能,以便能更好地处理引用 (感谢 Theo Spears)。

·         更正了 double、single 和 decimal 值的解析问题,以解释非英文分隔符。如果你正使用硬编码 sql,仍须使用正确的语法,但是,如果你使用参数,代码将转换浮点类型,以便在进出服务器的过程中恰当地在内部使用“.”。[感谢匿名人]。

·         增加了 MySqlStream 类,以简化超时和驱动编码。

·         更正了 DataReader,以便在相关连接关闭时恰当地关闭它。[感谢 smishra]。

·         使得客户端更兼容 SqlClient,在连接能够用于运行另一命令前关闭 DataReaders。

·         改进了字段中的 DBNull.Value 处理功能。

·         增加了数个单元测试。

·         更正了 MySqlException,以便能调用基本类:-o

·         改进了驱动编码。

·         更正了 NextResult 在最后 1 个结果集上返回“假”的缺陷。

·         为 MySQL 增加了多个测试。

·         通过等化无符号 32bit 值和 Int64,以及无符号 16bit 值和 Int32 等,改进了抛弃问题。

·         为 MySqlParameter 增加了新的 ctor(名称、类型、大小、srccol)。

·         更正了 MySqlDataReader 中存在的问题,即,在返回字段计数前,不能检查空的字段列表。

·         开始增加了 MySqlClient 单元测试 (增加了 MySqlClient/Tests 文件夹以及一些测试范例)。

·         更正了连接字符串处理中的一些问题。

·         将 INIT_DB 移到 MySqlPool。可或许会在此移动它,这是在协商的准备过程中。

·         更正了 CommandBuilder 中存在的缺陷,该缺陷会阻止插入正确出现。

·         改写了一些内部构件,从而使得 Command 的所有三种执行方法均能正确工作。

·         更正了在基准测试过程中发现的一些小问题。

·         CoonectionPooling 的首次截除工作恰当。保留了“min pool size”和“max pool size”。

·         进行处理,允许返回多个结果集。

·         现在,字符集的处理更为智能化。启动时,驱动程序查询 MySQL,寻找默认的字符集。随后,如果能够加载代码页,该字符集将用于转换。如不然,将使用当前操作系统的默认代码页。

·         增加了代码,以便将推断的类型保存在名称,以及参数的值 ctor 中。

·         此外,如果使用 Value 属性更改了空参数的值,还能推断类型。

·         转换了所有的文件以使用恰当的 Camel 范例。现在,在所有文件中,MySQL 是 MySql。PgSQL 现在是 PgSql。

·         为 PgSql 代码增加了属性,以防止设计器显示它。

·         为参数对象增加了 MySQLDbType 属性,并为从 DbType 到 MySQLDbType 的转换增加了恰当的转换代码。

·         从 MySQLParameter.cs 中删除了从未使用的 ObjectToString 方法。

·         更正了 ParameterCollection 中的 Add(..) 方法,不必使用 Add(name, value) 取而代之。

·         更正了 ParameterCollection 中的 IndexOf 和 Contains,使之清楚保存参数名时不需要@。

·         更正了 Command.ConvertSQLToBytes,仅允许能够构出现在 MySQL 变量名中的字符。

·         更正了 DataReader 和字段,从而使得 Blob 字段能够从 Field.cs 读取其数据,而且 GetBytes 工作正确。

·         为 MySQLCommand 的 CommandText 属性增加了简单的构造器编辑器。

·         更正了 CommandBuilder 和 Parameter 序列化,指明在参数名称中不保存@。

·         从 Field.cs 删除了 MySQLFieldType enum,现使用 MySQLDbType enum。

·         为数个类增加了 Designer 属性,防止了使用 VS.Net 时的设计器视图。

·         更正了 ConnectionString 设计器中的初始目录类型。

·         删除了与 (名称、类型、值) 冲突的 3 种 MySQLParameter 参数 ctor。

·         更改了 MySQLParameter,现在能够保存 paramName 而无需前导@(这修正了使用设计器是的 Null 插入问题)。

·         更改了用于 MySQLParameter 的 TypeConverter,以便能够与所有属性一起使用 ctor。

26.2.5.16. 版本 0.68

·         更正了驱动程序中的顺序问题。

·         增加了 DbParametersEditor,使得参数编辑更像 SqlClient。

·         更正了 Command 类,以便能够使用设计器编辑参数。

·         更新了连接字符串设计器,支持使用压缩标志。

·         更正了字符串编码功能,从而使得欧洲字符 (如ä) 能够正确工作。

·         创建了基本类,以帮助创建新的数据 Provider。

·         在连接字符串中增加了对 UID 关键字的支持。

·         字段、参数和命令现在都能使用 DBNull.Value,而不是 null。

·         使用 DBNull.Value 的 CommandBuilder。

·         未出现 auto_insert 字段时,CommandBuilder 现在能正确创建插入命令。

·         现在,字段使用 typeof 关键字来返回 System.Types(性能)。

26.2.5.17. 版本 0.65

·         目前实现了 MySQLCommandBuilder。

·         目前实现了事务支持 (并非所有的表类型均支持它)。

·         更正了 GetSchemaTable,不再使用 xsd(对于 Mono)。

·         驱动程序先能兼容 Mono!!

·         现在支持 TIME 数据类型。

·         需要更多工作以改善 Timestamp 数据类型处理。

·         更改了所有类的特征以匹配对应的 SqlClient 类。

26.2.5.18. 版本 0.60

·         采用 SharpZipLib 的协议压缩 (www.icsharpcode.net)。

·         Windows 平台上的命名管道现工作正常。

·         完成了更多工作,改善了 Timestamp 数据类型处理。

·         在 DataReader 上实现了 Ienumerable,以使 DataGrid 能恰当工作。

26.2.5.19. 版本 0.50

·         通过删除网络同步代码中的缺陷,大幅度提高了速度。

·         驱动程序不再对数据行进行缓冲处理 (更兼容 ADO.Net)。

·         更正了与 TIMESTAMP 和 DATETIME 字段有关的转换缺陷。

26.3. MySQL Connector/J

通过 JDBC 驱动,MySQL 提供了与使用 Java 编程语言开发的客户端应用程序的连通性,该驱动称为 MySQL Connector/J。

MySQL Connector/J 是一种 JDBC-3.0“类型 4”驱动,这意味着它是一种纯 Java 程序,实施了 3.0 版 JDBC 规范,并能使用 MySQL 协议与 MySQL 服务器直接通信。

本文档是为初级 JDBC 开发人员准备和安排的。如果你已有了使用 JDBC 方面的经验,可直接从安装 Connector/J开始。

尽管 JDBC 本身很有用,但我们希望,如果你在阅读完本手册的前几节后尚未熟悉 JDBC,除了最平常的问题外应避免全面使用“裸”JDBC,应考虑使用流行的架构,如HibernateSpringJDBC模板Ibatis SQL Maps等,使用它们来完成大多数重复性工作,以及在某些时侯需要用到 JDBC 的繁重任务。

本节不是作为完整的 JDBC 教程而设计的。如果需要了解使用 JDBC 方面的更多信息,或许会对下述在线教程感兴趣,与这里提供的信息相比,它们介绍的更为详细和更具深度。

·         JDBC基础,Sun 公司提供的教程,涵盖了 JDBC 的基本主题。。

·         JDBC简明课程,Sun 和 JGuru 提供了更深的教程。

26.3.1. ;基本的 JDBC 概念

在本节中,介绍一些一般性的 JDBC 背景知识。

26.3.1.1. ;使用 DriverManager 接口连接到 MySQL

在应用服务器外使用 JDBC 时,DriverManager 类将用于管理连接的建立。

需要告诉 DriverManager 应与哪个 JDBC 驱动建立连接。完成该任务的最简单方法是:在实施了 java.sql.Driver 接口的类上使用 Class.forName()。对于 MySQL Connector/J,该类的名称是 com.mysql.jdbc.Driver。采用该方法,可使用外部配置文件来提供连接到数据库时将使用的驱动类名和驱动参数。

在下面的 Java 代码中,介绍了在应用程序的 main() 方法中注册 MySQL Connector/J 的方式:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
// Notice, do not import com.mysql.jdbc.*
// or you will have problems!(注意,不要导入com.mysql.jdbc.*,否则// 将出现问题!)
 
public class LoadDriver {
    public static void main(String[] args) {
        try {
            // The newInstance() call is a work around for some
            // broken Java implementations
 
            Class.forName("com.mysql.jdbc.Driver").newInstance();
        } catch (Exception ex) {
            // handle the error
        }
}

在 DriverManager 中注册了驱动后,通过调用 DriverManager.getConnection(),能够获得与特殊数据库相连的连接实例。

示例 26.1:从 DriverManager 获得连接

在本示例中,介绍了从 DriverManager 获得连接实例的方法。对于 getConnection() 方法,有一些不同的特性。关于如何使用它们的更多信息,请参阅与 JDK 一起提供的 API 文档。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
 
    ... try {
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
 
            // Do something with the Connection
 
           ....
        } catch (SQLException ex) {
            // handle any errors
            System.out.println("SQLException: " + ex.getMessage());
            System.out.println("SQLState: " + ex.getSQLState());
            System.out.println("VendorError: " + ex.getErrorCode());
        }

一旦建立了连接,它可被用于创建语句和 PreparedStatements,并检索关于数据库的元数据。在下面数节内,给出了进一步的解释。

26.3.1.2. ;使用语句以执行 SQL

使用语句,可执行基本的 SQL 查询,并通过下面介绍的 ResultSet 类检索结果。

要想创建语句实例,应通过前面介绍的 DriverManager.getConnection() 或 DataSource.getConnection() 方法之一,在检索的连接对象上调用 createStatement() 方法。

一旦拥有了语句实例,可以与希望使用的 SQL 一起通过调用 executeQuery(String) 方法执行 SELECT 查询。

要想更新数据库中的数据,可使用 executeUpdate(String SQL) 方法。该方法将返回受更新语句影响的行数。

如果你事先不清楚 SQL 语句是 SELECT 或 UPDATE/INSERT,应使用 execute(String SQL) 方法。如果 SQL 查询是 SELECT,本方法将返回“真”,如果 SQL 查询是 UPDATE/INSERT/DELETE,本方法将返回“假”。如果是 SELECT 查询,能够通过调用 getResultSet() 方法检索结果。如果是 UPDATE/INSERT/DELETE 查询,能够通过在语句实例上调用 getUpdateCount() 检索受影响的行计数。

示例 26.2:使用 java.sql.Statement 执行 SELECT 查询

// assume conn is an already created JDBC connection
Statement stmt = null;
ResultSet rs = null;

try {
    stmt = conn.createStatement();
    rs = stmt.executeQuery("SELECT foo FROM bar");

    // or alternatively, if you don't know ahead of time that
    // the query will be a SELECT...

    if (stmt.execute("SELECT foo FROM bar")) {
        rs = stmt.getResultSet();
    }

    // Now do something with the ResultSet ....
} finally {
    // it is a good idea to release
    // resources in a finally{} block
    // in reverse-order of their creation
    // if they are no-longer needed

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException sqlEx) { // ignore }

        rs = null;
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException sqlEx) { // ignore }

        stmt = null;
    }
}

26.3.1.3. ;使用 CallableStatements 以执行存储程序

从 MySQL 服务器 5.0 版开始,与 Connector/J 3.1.1 或更新版本一起使用时,可完全实现java.sql.CallableStatement 接口,getParameterMetaData() 方法例外。

在 MySQL 参考手册的“http://www.mysql.com/doc/en/Stored_Procedures.html”一节中,介绍了 MySQL 存储程序的语法。

通过 JDBC 的CallableStatement 接口,Connector/J 指明了存储程序的功能。

在下面的示例中,给出了 1 个存储程序,它返回增量为 1 的inOutParam 的值,并通过 inputParam 传递了作为 ResultSet 的字符串。

示例 26.3. ;存储程序示例

CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam INT)
BEGIN
    DECLARE z INT;
    SET z = inOutParam + 1;
    SET inOutParam = z;
 
    SELECT inputParam;
 
    SELECT CONCAT('zyxw', inputParam);
END

要想与 Connector/J 一起使用demoSp,可采取下述步骤:

1.    使用Connection.prepareCall() 准备可调用语句。

注意,必须使用 JDBC 转义语法,而且必须使用包含占位符的圆括号:

示例26.4. 使用Connection.prepareCall()

导入java.sql.CallableStatement
 
...
 
    //
    // Prepare a call to the stored procedure 'demoSp'
    // with two parameters
    //
    // Notice the use of JDBC-escape syntax ({call ...})
    //
 
    CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");
 
 
 
    cStmt.setString(1, "abcdefg");

注释:

Connection.prepareCall()是一种开销很大的方法,原因在于驱动程序执行的支持输出参数的元数据检索。出于性能方面的原因,应在你的代码中再次使用CallableStatement 实例,通过该方式,使对 Connection.prepareCall() 的不必要调用降至最低。

2.      注册输出参数 (如果有的话)

为了检索输出参数的值 (创建存储程序时指定为OUT 或 INOUT 的参数),JDBC 要求在CallableStatement 接口中使用各种 registerOutputParameter() 方法来执行语句之前指定它们:

示例26.5. 注册输出参数

导入java.sql.Types
 
...
    //
    // Connector/J supports both named and indexed
    // output parameters. You can register output
    // parameters using either method, as well
    // as retrieve output parameters using either
    // method, regardless of what method was
    // used to register them.
    //
    // The following examples show how to use
    // the various methods of registering
    // output parameters (you should of course
    // use only one registration per parameter).
    //
 
    //
    // Registers the second parameter as output
    //
 
    cStmt.registerOutParameter(2);
 
    //
    // Registers the second parameter as output, and
    // uses the type 'INTEGER' for values returned from
    // getObject()
    //
 
    cStmt.registerOutParameter(2, Types.INTEGER);
 
    //
    // Registers the named parameter 'inOutParam'
    //
 
    cStmt.registerOutParameter("inOutParam");
 
    //
    // Registers the named parameter 'inOutParam', and
    // uses the type 'INTEGER' for values returned from
    // getObject()
    //
 
    cStmt.registerOutParameter("inOutParam", Types.INTEGER);
 
...

3.      设置输入参数 (如果有的话)

输入以及输入/输出参数是作为PreparedStatement 对象而设置的。但是,CallableStatement 也支持按名称设置参数:

示例26.6. 设置CallableStatement输入参数

...
 
    //
    // Set a parameter by index
    //
 
    cStmt.setString(1, "abcdefg");
 
    //
    // Alternatively, set a parameter using
    // the parameter name
    //
 
    cStmt.setString("inputParameter", "abcdefg");
 
    //
    // Set the 'in/out' parameter using an index
    //
 
    cStmt.setInt(2, 1);
 
    //
    // Alternatively, set the 'in/out' parameter
    // by name
    //
 
    cStmt.setInt("inOutParam", 1);
 
...

4.    执行CallableStatement,并检索任何结果集或输出参数。

尽管CallableStatement支持调用任何语句执行方法 (executeUpdate()executeQuery()execute()),最灵活的方法是调用execute(),这是因为,采用该方法,你无需事先知道存储程序是否将返回结果集:

示例26.7. 检索结果和输出参数值

...
 
    boolean hadResults = cStmt.execute();
 
    //
    // Process all returned result sets
    //
 
    while (hadResults) {
        ResultSet rs = cStmt.getResultSet();
 
        // process result set
        ...
 
        hadResults = cStmt.getMoreResults();
    }
 
    //
    // Retrieve output parameters
    //
    // Connector/J supports both index-based and
    // name-based retrieval
    //
 
    int outputValue = cStmt.getInt(1); // index-based
 
    outputValue = cStmt.getInt("inOutParam"); // name-based
 
...

26.3.1.4. ;检索 AUTO_INCREMENT 列的值

在 JDBC API 3.0 版之前,没有从支持“自动增量”或 ID 列的数据库中检索关键值的标准方法。对于针对 MySQL 的早期 JDBC 驱动,总是不得不在语句接口上使用特定的 MySQL 方法,或在向拥有 AUTO_INCREMENT 关键字的表发出“INSERT 后”发出“SELECT LAST_INSERT_ID()”。特殊的 MySQL 方法调用是不可移植的,而且对于发出“SELECT”以获取 AUTO_INCREMENT 关键字的值来说,需要对数据库执行另一往返操作,其效率不高。在下面的代码片段中,介绍了检索 AUTO_INCREMENT 值的三种不同方式。首先,介绍了 JDBC-3.0 新方法“getGeneratedKeys()”的使用方式,当你需要检索 AUTO_INCREMENT 关键字并访问 JDBC-3.0,它是目前的首选方法。在第 2 个示例中,介绍了使用标准“SELECT LAST_INSERT_ID()”查询检索相同值的方法。在最后一个示例中,介绍了使用“insertRow()”方法时,用可更新结果集检索 AUTO_INCREMENT 值的方式。

示例 26.8. ;使用 Statement.getGeneratedKeys() 检索 AUTO_INCREMENT 列的值

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets assuming you have a
    // Connection 'conn' to a MySQL database already
    // available

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                                java.sql.ResultSet.CONCUR_UPDATABLE);

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Insert one row that will generate an AUTO INCREMENT
    // key in the 'priKey' field
    //

    stmt.executeUpdate(
            "INSERT INTO autoIncTutorial (dataField) "
            + "values ('Can I Get the Auto Increment Field?')",
            Statement.RETURN_GENERATED_KEYS);

    //
    // Example of using Statement.getGeneratedKeys()
    // to retrieve the value of an auto-increment
    // value
    //

    int autoIncKeyFromApi = -1;

    rs = stmt.getGeneratedKeys();

    if (rs.next()) {
        autoIncKeyFromApi = rs.getInt(1);
    } else {

        // throw an exception from here
    }

    rs.close();

    rs = null;

    System.out.println("Key returned from getGeneratedKeys():"
        + autoIncKeyFromApi);
} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}

示例 26.9. ;使用 SELECT LAST_INSERT_ID() 检索 AUTO_INCREMENT 列的值

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets.

    stmt = conn.createStatement();

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Insert one row that will generate an AUTO INCREMENT
    // key in the 'priKey' field
    //

    stmt.executeUpdate(
            "INSERT INTO autoIncTutorial (dataField) "
            + "values ('Can I Get the Auto Increment Field?')");

    //
    // Use the MySQL LAST_INSERT_ID()
    // function to do the same thing as getGeneratedKeys()
    //

    int autoIncKeyFromFunc = -1;
    rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");

    if (rs.next()) {
        autoIncKeyFromFunc = rs.getInt(1);
    } else {
        // throw an exception from here
    }

    rs.close();

    System.out.println("Key returned from " + "'SELECT LAST_INSERT_ID()': "
        + autoIncKeyFromFunc);

} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}
   

示例 26.10. ;在可更新的 ResultSets 中检索 AUTO_INCREMENT 列的值

   Statement stmt = null;
   ResultSet rs = null;

   try {

    //
    // Create a Statement instance that we can use for
    // 'normal' result sets as well as an 'updatable'
    // one, assuming you have a Connection 'conn' to
    // a MySQL database already available
    //

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                                java.sql.ResultSet.CONCUR_UPDATABLE);

    //
    // Issue the DDL queries for the table for this example
    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
    stmt.executeUpdate(
            "CREATE TABLE autoIncTutorial ("
            + "priKey INT NOT NULL AUTO_INCREMENT, "
            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //
    // Example of retrieving an AUTO INCREMENT key
    // from an updatable result set
    //

    rs = stmt.executeQuery("SELECT priKey, dataField "
       + "FROM autoIncTutorial");

    rs.moveToInsertRow();

    rs.updateString("dataField", "AUTO INCREMENT here?");
    rs.insertRow();

    //
    // the driver adds rows at the end
    //

    rs.last();

    //
    // We should now be on the row we just inserted
    //

    int autoIncKeyFromRS = rs.getInt("priKey");

    rs.close();

    rs = null;

    System.out.println("Key returned for inserted row: "
        + autoIncKeyFromRS);

} finally {

    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            // ignore
        }
    }

    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException ex) {
            // ignore
        }
    }
}


   
运行上面的示例代码时,将获得下述输出:从 getGeneratedKeys():返回的键, 从“SELECT LAST_INSERT_ID():”返回 1 个键, 从插入的行返回 1 个键。请注意,有些时候,使用“SELECT LAST_INSERT_ID()”查询十分复杂,原因在于函数值与连接相关。因此,如果在相同连接上存在其他查询,函数值将被覆盖。另一方面,“getGeneratedKeys()”方法是由语句实例确定的,因此,即使在相同连接上存在其他查询也能使用它,但在相同语句实例上存在其他查询时则不能使用。

26.3.2. ;安装 Connector/J

请按照下述说明安装 Connector/J。

26.3.2.1. ;所需的软件版本

26.3.2.1.1. ;支持的 Java 版本
MySQL Connector/J 支持 Java-2 JVMs,包括 JDK-1.2.x、JDK-1.3.x、JDK-1.4.x 和 JDK-1.5.x,并需要 JDK-1.4.x 或更新的版本进行编译 (而不是运行)。MySQL Connector/J 不支持 JDK-1.1.x 或 JDK-1.0.x。

由于实现了 java.sql.Savepoint,Connector/J 3.1.0 和更新版本不会运行在早于 1.4 版的 JDK 上,除非关闭了类验证器 (-Xverify:none),这是因为,类验证器将试图加载用于 java.sql.Savepoint 的类定义,除非使用了 savepoint 功能,否则驱动程序不会访问类验证器。

早于 1.4.x 版的 JVM 上,不能使用 Connector/J 3.1.0 或更高版本提供的新缓冲功能,这是因为该功能依赖JDK-1.4.0 中首次提供的java.util.LinkedHashMap。

26.3.2.1.2. MySQL 服务器版本指南
MySQL Connector/J 支持所有著名的 MySQL 服务器版本。某些特性 (外键,可更新结果集) 需要更新的 MySQL 版本才能工作。

与 MySQL 服务器 4.1 版或更高版本建立连接时,最好使用 MySQL Connector/J 3.1 版,这是因为它全面支持较新版本的服务器提供的特性,包括 Unicode 字符、视图、存储程序和服务器端预处理语句。

尽管 3.0 版 Connector/J 能够与 MySQL 服务器 4.1 或更高版本建立连接,但由于实现了 Unicode 字符和新的鉴定机制,将无法更新 Connector/J 3.0 以支持当前和未来服务器版本中提供的新特性。

26.3.2.1.3. ;安装驱动程序并配置 CLASSPATH
MySQL Connector/J 是以。zip 或。tar.gz 形式分发的,其中包含源码、类文件、以及仅为“二进制”.jar 的类文件 (名为mysql-connector-java-[version]-bin.jar),从Connector/J 3.1.8 开始,驱动程序的“调试版”位于名为“mysql-connector-java-[version]-bin-g.jar”的文件中。

从 Connector/J 3.1.9 开始,我们不再单独提供。class 文件,仅在与驱动程序一起提供的 JAR 文件中提供它们。

不应使用驱动程序的“调试版”,除非是在向 MySQL AB 通报问题或缺陷时需要用到它,这是因为“调试版”不是为生产环境下的运行而设计的,如果使用它,会对性能造成负面影响。二进制代码的调试取决于 Aspect/J 运行时库,该库位于与 Connector/J 分发版一起提供的src/lib/aspectjrt.jar文件中。

需要使用恰当的 GUI 或命令行使用工具来解开分发文件 (例如,用于。zip 文件的 WinZip,以及用于。tar.gz 文件的“tar”)。由于在分发版中可能存在长文件名,我们采用了 GNU tar 档案格式。需要使用 GNU tar(或能理解 GNU tar 档案格式的其他应用程序) 来解开分发版的。tar.gz 文件。

一旦解包了分发版档案文件,可以将 mysql-connector-java-[version]-bin.jar 放在你的类路径中,或是在你的 CLASSPATH 环境变量中添加它的完整路径,或是在启动 JVM(Java 虚拟机) 时用命令行开关“-cp”直接指定它,通过该方式安装驱动。

如果你打算用 JDBC DriverManager 来使用驱动,可使用“com.mysql.jdbc.Driver”,将其用作实施了“java.sql.Driver”类。

示例 26.11. ;设置 Unix 环境下的 CLASSPATH

在 Unix 环境下,下述命令用于“csh”:

$ setenv CLASSPATH /path/to/mysql-connector-java-[version]-bin.jar:$CLASSPATH

可以将上述命令添加到恰当的、用于登录 shell 的启动文件中,从而使得所有的 Java 应用程序均能使用 MySQL Connector/J。

如果希望与诸如 Tomcat 或 Jboss 等应用服务器一起使用 MySQL Connector/J,应仔细阅读供应商提供的文档,以了解如何配置第三方类库的更多信息,这是因为大多数应用服务器均会忽略 CLASSPATH 环境变量。在“与 J2EE 和其他 Java 框架一起使用 Connector/J”一节中,给出了针对一些 J2EE 应用服务器的配置示例,但是,对于特定的应用服务器,JDBC 连接池配置信息的权威信息源是该应用服务器的文档。

如果你准备开发小服务程序和/或 JSP,而且你的应用服务器是 J2EE 兼容的,可以将驱动的。jar 文件放到 webapp 的 WEB-INF/lib 子目录下,在 J2EE Web 应用程序中,这是第三方类库的标准位置。

如果你的 J2EE 应用服务器支持或要求,也可以使用 com.mysql.jdbc.jdbc2.optional 可选软件包中的 MysqlDataSource 或 MysqlConnectionPoolDataSource 类。多种 MysqlDataSource 类均支持下述参数 (通过标准的“Set”存取器):

·         user

·         password

·         serverName(参见前面关于故障切换主机的章节)

·         databaseName

·         port

26.3.2.2. ;升级旧版本

MySQL AB 试图使升级进程尽可能简单,但是,对于任何软件来说,某些时侯需要在新版本中进行一些更改才能支持新的特性,改进已有的功能,或与新标准相符。

在本节中,介绍了打算从 Connector/J 的一个版本升级到另一版本 (或考虑到 JDBC 的功能,升级到 MySQL 服务器的新版本) 的用户应了解的信息。

26.3.2.2.1. ;从 MySQL Connector/J 3.0 升级到 3.1

设计 Connector/J 3.1 时,尽量使它能向后兼容 Connector/J 3.0。大的变化被单独作为 MySQL-4.1 和更新版中的新功能,包括 Unicode 字符集、服务器端预处理语句、由服务器返回的错误信息中的 SQLState 代码、以及各种性能增强特性 (可通过配置属性启用或禁止)。

·         Unicode 字符集:关于 MySQL 新特性的更多信息,请参见下一节,以及服务器手册中的“字符集”一节。如果有些事项配置不当,通常会显示错误,同时给出错误消息,如“非法校对组合”。

·         服务器端预处理语句:Connector/J 3.1 将自动检测服务器端预处理语句,并在可用时自动使用它们 (MySQL 服务器 4.1.0 版或更新)。

从 3.1.7 版开始,驱动程序能通过各种Connection.prepareStatement() 变体扫描 SQL,以判断它是否是能够在服务器端支持的语句类型,如果不被服务器端支持,会将其作为客户端的模拟预处理语句进行处理。也可以通过在 JDBC URL 中传递“emulateUnsupportedPstmts=false”禁止该特性。

如果应用程序遇到与服务器端预处理语句有关的问题,可将其回复为旧的客户端模拟预处理语句代码,在早于 4.1.0 版的 MySQL 服务器中仍使用该代码,连接属性如下:

useServerPrepStmts=false

·         具有全 0 组分的 Datetimes(0000-00-00 ...):在 Java 中,无法可靠地表示这些值。从结果集读取它们时,Connector/J 3.0.x 总是会将其转换为 NULL。

默认情况下,遇到这类值时,Connector/J 3.1 将抛出异常,这是因为,根据 JDBC 和 SQL 标准,这是最正确的行为方式。可以使用“zeroDateTimeBehavior”配置属性改变该行为。允许的值包括:“exception”,(默认值),用代码为“S1009”的 SQLState 抛出 SQLException;“convertToNull”,返回 NULL 而不是数据;以及“round”,对日期进行舍入处理,使之成为最接近的值,即“0001-01-01”。

从 Connector/J 3.1.7 开始,能够使用“noDatetimeStringSync=true”(默认值为“假”),将 ResultSet.getString() 与该行为分离开,从而能够以字符串的形式提取未被改变的全 0 值。请注意,这也会阻止使用任何时区转换功能,因此,驱动程序将禁止同时启用noDatetimeStringSyncuseTimezone。

·         新 SQLState 代码:Connector/J 3.1 采用 MySQL 返回的 SQL:1999 SQLState 代码 (如果支持的话),它不同于 Connector/J 3.0 使用的“传统”X/Open 状态码。如果连接到了版本低于 MySQL-4.1.0(能够将 SQLStates 作为错误代码组成部分返回的最早版本) 的 MySQL 服务器,驱动程序将使用内置的映射功能。你也可以使用下述配置选项,采用旧的映射。

useSqlStateCodes=false

·         在 BLOB 列上调用 ResultSet.getString() 将返回代表它的字节 [] 数组的地址,而不是 BLOB 的字符串形式。BLOB 没有字符集,因此,在不造成数据丢失或损坏的情况下,不能将它们转换为 java.lang.Strings。

要想以 BLOB 方式将字符串保存在 MySQL 中,可使用一种 TEXT 类型,驱动程序会将其当作 java.sql.Clob 对待。

·         从 Connector/J 3.1.8 开始,驱动的“调试版”(在名为“mysql-connector-java-[version]-bin-g.jar的文件中与正常的二进制jar 文件名为 mysql-connector-java-[version]-bin.jar一起提供

从 Connector/J 3.1.9 开始,我们不再单独提供。class 文件,仅在与驱动程序一起提供的 JAR 文件中提供它们。

不应使用驱动程序的“调试版”,除非是在向 MySQL AB 通报问题或缺陷时需要用到它,这是因为“调试版”不是为生产环境下的运行而设计的,如果使用它,会对性能造成负面影响。二进制代码的调试取决于 Aspect/J 运行时库,该库位于与 Connector/J 分发版一起提供的src/lib/aspectjrt.jar文件中。

26.3.2.2.2. ;升级到 MySQL 服务器 4.1 版或更新版本时的 JDBC 事宜

·         使用UTF-8字符编码:在 4.1 版 MySQL 服务器之前,服务器不支持UTF-8字符编码,但 JDBC 驱动能使用它,从而允许在服务器上的 latin1 中保存多个字符集。

从 MySQL-4.1 版开始,该功能被放弃。如果你有依赖该功能的应用程序,而且无法升级它们以使用 MySQL 服务器 4.1 版或更高版本中支持的正是 Unicode 字符集,应在连接 URL 中增加下述属性:

useOldUTF8Behavior=true

·         服务器端预处理语句:Connector/J 3.1 将自动检测服务器端预处理语句,并在可用时自动使用它们 (MySQL 服务器 4.1.0 版或更新)。如果应用程序遇到与服务器端预处理语句有关的问题,可将其回复为旧的客户端模拟预处理语句代码,在早于 4.1.0 版的 MySQL 服务器中仍使用该代码,连接属性如下:

useServerPrepStmts=false

26.3.3. JDBC 引用

26.3.3.1. Driver/Datasource 类名,URL 语法,以及 Connector/J 的配置属性

在 MySQL Connector/J 中实现了 java.sql.Driver 的类名是“com.mysql.jdbc.Driver”。“org.gjt.mm.mysql.Driver”类名任是可用的,以保持与 MM.MySQL 的向后兼容性。注册驱动程序,或配置软件以使用 MySQL Connector/J 时,应使用该类名。

用于 MySQL Connector/J 的 JDBC URL 格式如下,方括号“[, ]”的项为可选项:

jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

如果未指定主机名,默认为“127.0.0.1”。如果未指定端口,默认为“3306”,它是 MySQL 服务器的默认端口号。

jdbc:mysql://[host:port],[host:port].../[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

如果未指定数据库,将使用无“当前”数据库进行连接。在这种情况下,需要在连接实例上调用“setCatalog()”方法,或在 SQL 中使用数据库名指定完整的表名 (即“SELECT dbname.tablename.colname FROM dbname.tablename...”)。不指定连接时使用的数据库,该选项通常仅在创建用于处理多个数据库的工具时才有用,例如 GUI 数据库管理器。

MySQL Connector/J 支持故障切换功能。这样,就允许驱动程序切换至“从”主机上,并仍能执行只读查询。仅当连接处于 autoCommit(true) 状态时,才会出现故障切换,这是因为当事务正在进行时,无法可靠地保证故障切换。在事务/连接结束后,大多数应用服务器和连接池均会将 autoCommit 设置为“真”。

故障切换功能具有下述行为方式:

如果 URL 属性“autoReconnect”为“假”:故障切换仅会在连接初始化过程中出现,当驱动程序判断第 1 台主机再次可用时,将返回。

如果 URL 属性“autoReconnect”为“真”:当驱动程序判断连接失败时 (在任意查询之前),将出现故障切换,而且当驱动程序判断第 1 台主机再次可用时 (发出 queriesBeforeRetryMaster 查询之后),将返回第 1 台主机。

在任何一种情况下,当你连接到经过故障切换的服务器时,会将连接设置为只读状态,因此,对于会更改数据的查询来说,将抛出异常 (MySQL 服务器不会处理该查询)。

配置属性定义了 Connector/J 与 MySQL 服务器进行连接的方式。除非作了其他说明,否则可以为 DataSource 对象或 Connection 对象设置属性。

可采用下述方式的一种设置 Configuration(配置) 属性:

·         在 java.sql.DataSource 的 MySQL 实施实例上使用 set*() 方法 (它是使用 java.sql.DataSource 实施实例时的首选方法):

o        com.mysql.jdbc.jdbc2.optional.MysqlDataSource

o        com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource

·         作为传递给 DriverManager.getConnection() 或 Driver.connect() 的 java.util.Properties 实例中的 键/值对。

·         作为 URL 中的 JDBC URL 参数,以传递给 java.sql.DriverManager.getConnection()、java.sql.Driver.connect()、或 javax.sql.DataSource 的 setURL() 方法的 MySQL 实施实例。

注释:

如果你用来配置 JDBC URL 的方法是基于 XML 的,需要使用 XML 字符“&amp;”来隔开配置参数,“&”是 XML 的保留字符。

在下面的表各中,列出了这些属性:

表 26.1. ;连接属性 

属性名

定义

要求?

默认值

版本

Connection/Authentication(连接/鉴定)

user

连接的用户

No

 

全部

password

连接时使用的密码。

No

 

全部

socketFactory

驱动程序用于创建与服务器套接字连接的类的名称。该类必须实现了接口“com.mysql.jdbc.SocketFactory”,并有公共无参量构造函数。

No

com.mysql.jdbc.StandardSocketFactory

3.0.3

connectTimeout

套接字连接的超时 (单位为毫秒),0 表示无超时。仅对 JDK-1.4 或更新版本有效。默认值为“0”。

No

0

3.0.1

socketTimeout

网络套接字连接的超时 (默认值 0 表示无超时)。

No

0

3.0.1

useConfigs

在解析 URL 属性或应用用户指定的属性之前,加载由逗号“,”分隔的配置属性列表。在文档的“配置”部分中解释了这些配置。

No

 

3.1.5

interactiveClient

设置 CLIENT_INTERACTIVE 标志,根据 INTERACTIVE_TIMEOUT 而不是 WAIT_TIMEOUT 向 MySQL 通报超时连接。

No

false

3.1.0

propertiesTransform

com.mysql.jdbc.ConnectionPropertiesTransform 的 1 个实施实例,在尝试连接之前,驱动程序将使用它来更改传递给驱动的 URL 属性。

No

 

3.1.4

useCompression

与服务器进行通信时采用 zlib 压缩 (真/假)? 默认值为“假”。

No

false

3.0.17

High Availability and Clustering(高可用性和簇集)

autoReconnect

驱动程序是否应尝试再次建立失效的和/或死连接? 如果允许,对于在失效或死连接上发出的查询 (属于当前事务),驱动程序将抛出异常,但在新事务的连接上发出下一个查询时,将尝试再连接。不推荐使用该特性,这是因为,当应用程序不能恰当处理 SQLExceptions 时,它会造成与会话状态和数据一致性有关的副作用,设计它的目的仅用于下述情况,即,当你无法配置应用程序来恰当处理因死连接和/或无效连接导致的 SQLExceptions 时。作为可选方式,可将 MySQL 服务器变量“wait_timeout”设置为较高的值,而不是默认的 8 小时。

No

false

1.1

autoReconnectForPools

使用适合于连接池的再连接策略 (默认值为“假”)。

No

false

3.1.3

failOverReadOnly

在 autoReconnect 模式下出现故障切换时,是否应将连接设置为“只读”?

No

true

3.0.12

reconnectAtTxEnd

如果将 autoReconnect 设置为“真”,在每次事务结束后驱动程序是否应尝试再连接?

No

false

3.0.10

roundRobinLoadBalance

启用了 autoReconnect 而且 failoverReadonly 为“假”时,是否应按照循环方式挑选要连接的主机?

No

false

3.1.2

queriesBeforeRetryMaster

出现故障切换 (使用多主机故障切换) 并返回主机之前发出的查询数。无论首先满足了哪个条件,“queriesBeforeRetryMaster”或“secondsBeforeRetryMaster”,均会再次与主机进行连接。默认值为“50”。

No

50

3.0.2

secondsBeforeRetryMaster

出现故障切换后,在尝试再次连接到主服务器之前,驱动程序应等待的时间? 无论首先满足了哪个条件,“queriesBeforeRetryMaster”或“secondsBeforeRetryMaster”,均会再次与主机进行连接。单位为秒,默认值为 30。

No

30

3.0.2

enableDeprecatedAutoreconnect

自 3.2 版开始,自动再连接功能受到冷落,在 3.3 版中将删除该功能。将该属性设置为“真”可禁止检查配置的特性。

No

false

3.2.1

Security(安全)

allowMultiQueries

在一条语句中,允许使用“;”来分隔多条查询 (真/假,默认值为“假”)。

No

false

3.1.1

useSSL

与服务器进行通信时使用 SSL(真/假),默认值为“假”。

No

false

3.0.2

requireSSL

要求 SSL 连接,useSSL=true? 默认值为“假”。

No

false

3.1.0

allowUrlInLocalInfile

驱动程序在是“LOAD DATA LOCAL INFILE”语句中否允许 URL?

No

false

3.1.4

paranoid

采取措施,防止在错误信息中泄漏敏感信息,并可可能时清除保存敏感数据的数据结构? 默认值为“假”。

No

false

3.0.1

Performance Extensions(性能扩展)

metadataCacheSize

如果将 cacheResultSetMetaData 设置为“真”,对 cacheResultSetMetadata 的查询次数 (默认值为 50)。

No

50

3.1.1

prepStmtCacheSize

如果允许预处理语句缓冲功能,应缓冲处理多少条预处理语句?

No

25

3.0.10

prepStmtCacheSqlLimit

如果允许预处理语句缓冲功能,驱动程序将执行解析缓冲处理的最大 SQL 是什么?

No

256

3.0.10

maintainTimeStats

驱动程序是否应维持各种内部定时器,以允许空闲时间计算,以及与服务器的连接失败时允许提供更详细的错误消息? 将该属性设置为“假”,对于每次查询,至少能减少两次对 System.getCurrentTimeMillis() 的调用。

No

true

3.1.9

blobSendChunkSize

组块,当通过 ServerPreparedStatements 发送 BLOB/CLOB 时使用。

No

1048576

3.1.9

cacheCallableStmts

驱动程序是否应对 CallableStatements 的解析过程执行缓冲处理。

No

false

3.1.2

cachePrepStmts

驱动程序是否应对客户端预处理语句的 PreparedStatements 的解析过程执行缓冲处理,是否应检查服务器端预处理语句的适用性以及服务器端预处理语句本身?

No

false

3.0.10

cacheResultSetMetadata

驱动程序是否应对用于 Statements 和 PreparedStatements 的 ResultSetMetaData 执行缓冲处理? 要求 JDK-1.4+,真/假,默认为“假”。

No

false

3.1.1

cacheServerConfiguration

驱动程序是否应根据每条 URL 对“HOW VARIABLES”和“SHOW COLLATION”的结果执行缓冲处理?

No

false

3.1.5

dontTrackOpenResources

JDBC 规范要求驱动程序自动跟踪和关闭资源,但是,如果你的应用程序不能明确调用作用在语句或结果集上的 close(),可能会导致内存泄漏。将该属性设置为“真”,可放宽该限制,对于某些应用程序,会提供更高的内存效率。

No

false

3.1.7

dynamicCalendars

需要时,驱动程序是否应检索默认日历,或根据连接/会话对其进行缓冲处理?

No

false

3.1.5

elideSetAutoCommits

如果使用 MySQL-4.1 或更高版本,当服务器的状态与 Connection.setAutoCommit(boolean) 请求的状态不匹配时,驱动程序是否仅应发出“set autocommit=n”查询?

No

false

3.1.3

holdResultsOpenOverStatementClose

驱动程序是否应按照 JDBC 规范的要求关闭 Statement.close() 上的结果集?

No

false

3.1.7

locatorFetchBufferSize

如果将“emulateLocators”配置为“真”,当获取关于 getBinaryInputStream 的 BLOB 数据时,缓冲区的大小应是多少?

No

1048576

3.2.1

useFastIntParsing

是否使用内部“String->Integer”转换子程序来避免创建过多对象?

No

true

3.1.4

useLocalSessionState

驱动程序是否应引用 autocommit 的内部值,以及由 Connection.setAutoCommit() 和 Connection.setTransactionIsolation() 设置的事务隔离,而不是查询数据库?

No

false

3.1.7

useNewIO

驱动程序是否应将 java.nio.* interfaces 用于网络通信 (真/假),默认为“假”。

No

false

3.1.0

useReadAheadInput

从服务器读取数据时,是否使用较新的、优化的非成组缓冲输入流?

No

true

3.1.5

Debuging/Profiling(调试/仿形)

logger

实现了 com.mysql.jdbc.log.Log 的类的名称,com.mysql.jdbc.log.Log 用于记录消息 (默认为“com.mysql.jdbc.log.StandardLogger”,它会将日志记录到 STDERR)。

No

com.mysql.jdbc.log.StandardLogger

3.1.1

profileSQL

跟踪查询以及它们对已配制记录器的执行/获取次数 (真/假),默认为“假”。

No

false

3.1.0

reportMetricsIntervalMillis

如果允许“gatherPerfMetrics”,记录它们的频率是多少 (单位毫秒)?

No

30000

3.1.2

maxQuerySizeToLog

调试或仿形时,控制将记录的查询的最大长度/大小。

No

2048

3.1.3

packetDebugBufferSize

当“enablePacketDebug”为“真”时,需要保留的最大信息包数目。

No

20

3.1.3

slowQueryThresholdMillis

如果允许“logSlowQueries”,在将查询记录为“慢”之前的查询时间是多少 (毫秒)?

No

2000

3.1.2

useUsageAdvisor

驱动程序是否应发出“使用情况”警告,就 DBC 和 MySQL Connector/J 的恰当和高效使用给出建议 (真/假,默认为“假”)?

No

false

3.1.1

autoGenerateTestcaseScript

驱动程序是否应将正在执行的 SQL(包括服务器端预处理语句) 转储到 STDERR?

No

false

3.1.9

dumpQueriesOnException

驱动程序是否应将发送至服务器的查询内容转储到 SQLExceptions 中?

No

false

3.1.3

enablePacketDebug

允许时,将保留“packetDebugBufferSize”信息包的环形缓冲区,并当在驱动程序代码的关键区域抛出异常时进行转储。

No

false

3.1.3

explainSlowQueries

如果允许了“logSlowQueries”,驱动程序是否应在服务器上自动发出“EXPLAIN”,并以 WARN 级别将结果发送给配置好的日志?

No

false

3.1.2

logSlowQueries

是否要记录时间长于“slowQueryThresholdMillis”的查询?

No

false

3.1.2

traceProtocol

是否应记录跟踪级网络协议?

No

false

3.1.2

Miscellaneous(其他)

useUnicode

处理字符串时,驱动程序是否应使用 Unicode 字符编码? 仅应在驱动程序无法确定字符集映射,或你正在强制驱动程序使用 MySQL 不是固有支持的字符集时 (如 UTF-8) 才应使用。真/假,默认为“真”。

No

false

1.1g

characterEncoding

如果“useUnicode”被设置为“真”,处理字符串时,驱动程序应使用什么字符编码? 默认为“autodetect”。

No

 

1.1g

characterSetResults

字符集,用于通知服务器以何种字符集返回结果。

No

 

3.0.13

connectionCollation

如果设置了它,将通知服务器通过“set collation_connection”使用该校对。

No

 

3.0.13

sessionVariables

以逗号隔开的“名称/值”对列表,当驱动程序建立了连接后,以“SET SESSION ...”的方式将其发送给服务器。

No

 

3.1.8

allowNanAndInf

驱动程序是否应在 PreparedStatement.setDouble() 中允许 NaN 或+/- INF 值?

No

false

3.1.5

autoDeserialize

驱动程序是否应自动检测并串并转换保存在 BLOB 字段中的对象?

No

false

3.1.5

capitalizeTypeNames

是否将 DatabaseMetaData 中的类型名转换为大写? 通常仅在使用 WebObjects 时有用,真/假。默认为“假”。

No

false

2.0.7

clobberStreamingResults

这会使“流式”结果集被自动关闭,如果在所有数据尚未从服务器中读取完之前,执行了另一查询,正在从服务器流出的任何未完成数据均将丢失。

No

false

3.0.9

continueBatchOnError

如果一条语句失败,驱动程序是否应继续处理批命令? JDBC 规范允许任何一种方式 (默认为“真”)。

No

true

3.0.3

createDatabaseIfNotExist

如果不存在,创建 URL 中给定的数据库。假定用户具有创建数据库的权限。

No

false

3.1.9

emptyStringsConvertToZero

驱动程序是否应允许从空字符串字段到数值“0”的转换?

No

true

3.1.8

emulateLocators

N/A

No

false

3.1.0

emulateUnsupportedPstmts

驱动程序是否应检测不被服务器支持的预处理语句,并用客户端模拟版替换它们?

No

true

3.1.7

ignoreNonTxTables

是否忽略关于回退的非事务表? 默认值为“假”。

No

false

3.0.9

jdbcCompliantTruncation

连接到支持告警的服务器时 (MySQL 4.1.0 和更高版本),当按照 JDBC 的要求截短数据时,驱动程序是否应抛出 java.sql.DataTruncation 异常?

No

true

3.1.2

maxRows

返回的最大行数 (0,默认值表示返回所有行)。

No

-1

all versions

noDatetimeStringSync

不保证 ResultSet.getDatetimeType().toString().equals(ResultSet.getString()。

No

false

3.1.7

nullCatalogMeansCurrent

当 DatabaseMetadataMethods 请求“目录”参数时,值“Null”是否意味着使用当前目录? 它不兼容 JDBC,但符合驱动程序早期版本的传统行为。

No

true

3.1.8

nullNamePatternMatchesAll

接受*pattern 参数的 DatabaseMetaData 方法是否应将 null 按对待“%”的相同方式处理 (不兼容 JDBC,但驱动程序的早期版本能接受与规范的这类偏离)。

No

true

3.1.8

pedantic

严格遵守 JDBC 规范。

No

false

3.0.0

relaxAutoCommit

如果驱动程序所连接的 MySQL 服务器的版本不支持事务,仍允许调用 commit()、rollback() 和 setAutoCommit()?真/假,默认为“假”。

No

false

2.0.13

retainStatementAfterResultSetClose

调用 ResultSet.close() 后,驱动程序是否应将语句引用保存在结果集中? 在 JDBC-4.0 后,与 JDBC 不兼容。

No

false

3.1.11

rollbackOnPooledClose

当连接池中的逻辑连接关闭时,驱动程序是否应发出 rollback()?

No

true

3.0.15

runningCTS13

允许在 Sun 与 JDBC 兼容的 testsuite 1.3 版中处理缺陷。

No

false

3.1.7

serverTimezone

覆盖时区的检测/映射。当服务器的时区为映射到 Java 时区时使用。

No

 

3.0.2

strictFloatingPoint

仅在兼容性测试的早期版本中使用。

No

false

3.0.0

strictUpdates

驱动程序是否应对可更新结果集进行严格检查 (选择所有的主键)?真/假,默认为“真”。

No

true

3.0.4

tinyInt1isBit

驱动程序是否应将数据类型 TINYINT(1) 当作 BIT 类型对待?创建表时,服务器会执行 BIT -> TINYINT(1) 操作。

No

true

3.0.16

transformedBitIsBoolean

如果驱动程序将 TINYINT(1) 转换为不同的类型,为了与 MySQL-5.0 兼容,驱动程序是否应使用 BOOLEAN 取代 BIT?这是因为 MySQL-5.0 具有 BIT 类型。

No

false

3.1.9

ultraDevHack

由于 UltraDev 已损坏,并为所有语句发出了 prepareCall(),需要时,是否要为 prepareCall() 创建 PreparedStatements?

真/假,默认值为“假”。

No

false

2.0.3

useHostsInPrivileges

在 DatabaseMetaData.getColumn/TablePrivileges() 中为用户添加“@hostname”。真/假,默认为“真”。

No

true

3.0.2

useOldUTF8Behavior

与 4.0 和更早版本的服务器进行通信时,使用 UTF-8。

No

false

3.1.6

useOnlyServerErrorMessages

对服务器返回的错误消息,不事先设定“标准的”SQLState 错误消息。

No

true

3.0.15

useServerPrepStmts

如果服务器支持,是否使用服务器端预处理语句? 默认值为“真”。

No

true

3.1.0

useSqlStateCodes

使用 SQL 标准状态码取代“传统的”X/Open/SQL 状态码,真/假,默认为“真”。

No

true

3.1.3

useStreamLengthsInPrepStmts

是否采用 PreparedStatement/ResultSet.setXXXStream() 方法调用中的流长度参数?真/假,默认为“真”。

No

true

3.0.2

useTimezone

是否在客户端和服务器时区间转换时间/日期类型 (真/假,默认为“假”)?

No

false

3.0.2

useUnbufferedInput

不使用 BufferedInputStream 来从服务器读取数据。

No

true

3.0.11

yearIsDateType

JDBC 驱动程序是否应将 MySQL 类型“YEAR”当作 java.sql.Date 或 SHORT 对待?

No

true

3.1.9

zeroDateTimeBehavior

当驱动程序遇到全由 0 组成的 DATETIME 值时,应出现什么?MySQL 使用它来表示无效日期。有效值是“exception”、“round”和“convertToNull”。

No

exception

3.1.4

通过“socketFactory”属性,使用 NamedPipeSocketFactory,在 Windows NT/2000/XP 平台上,通过命名管道,Connector/J 也支持对 MySQL 的访问。如果不使用 namedPipePath 属性,将使用\\.\pipe\MySQL的默认值。如果使用 NamedPipeSocketFactory,将忽略 JDBC url 中的主机名和端口号。

在 URL 中添加下述属性可启用NamedPipeSocketFactory

 

socketFactory=com.mysql.jdbc.NamedPipeSocketFactory

命名管道仅能当连接到位于相同物理机器上的 MySQL 时才能正常工作,该机器上应使用了 JDBC 驱动程序。在简单的性能测试中,命名管道的访问速度比标准的 TCP/IP 访问块 30~50%。

使用com.mysql.jdbc.NamedPipeSocketFactorycom.mysql.jdbc.StandardSocketFactory 中的示例代码,可创建你自己的套接字代理。

26.3.3.2. JDBC API 实施说明

MySQL Connector/J 通过了 Sun JDBC 兼容测试套件公共版中的所有测试。但是,在很多场合下,对于应如何实施特定的功能,JDBC 规范并未给出明确的规定,或者说,该规范允许有一定的实施范围。

在本节中,就特定实施方案将如何影响 MySQL Connector/J 的使用方式,给出了接口层面上的详细介绍。

·         Blob

Blob 实施不允许“原地”调整 (它们是“副本”,正如 DatabaseMetaData.locatorsUpdateCopies() 方法所指明的那样)。因此,应使用对应的 PreparedStatement.setBlob() 或 ResultSet.updateBlob()(对于可更新结果集) 方法,将变化保存到数据库中。

自 Connector/J version 3.1.0 开始,通过在 JDBC URL 中添加属性“emulateLocators=true”,能够使用定位器模拟 Blob。随后,必须使用带有列值的列别名,在你编写的用于检索 Blob 的 SELECT 中,将列值设为 Blob 列的世纪名称。SELECT 还必须仅引用 1 个表,该表必须有 1 个主键,而且 SELECT 必须涵盖构成主键的所有列。随后,驱动程序将延期加载实际的 Blob 数据,直至检索了 Blob 并在其上调用了检索方法为止 (getInputStream(), getBytes(),等)。

·         CallableStatement

自 Connector/J 3.1.1 开始,当通过CallableStatement 接口连接到 MySQL 5.0 或更高版本时,可支持存储程序。目前,不支持CallableStatement 的 getParameterMetaData()方法。

·         Clob

Clob 实施不允许“原地”调整 (它们是“副本”,正如 DatabaseMetaData.locatorsUpdateCopies() 方法所指明的那样)。因此,应使用 PreparedStatement.setClob() 方法将变更保存到数据库中。JDBC API 没有 ResultSet.updateClob() 方法。

·         Connection

与 MM.MySQL 的早期版本不同,“isClosed()”不会对服务器即行 Ping 操作以确定服务器是否有效。按照 JDBC 规范,如果在连接上调用了“closed()”,它仅返回“真”。如果需要确定连接是否依然有效,应发出简单查询,如“SELECT 1”。如果连接不再有效,驱动程序将抛出异常。

·         DatabaseMetaData

对于外键信息 (getImported/ExportedKeys() 和 getCrossReference()),仅在“InnoDB”类性的表中可用。但是,驱动程序会使用“SHOW CREATE TABLE”来检索该信息,因此,当其他表类型支持外键时,驱动程序也能支持它们。

·         Driver

·         PreparedStatement

PreparedStatements 是由驱动程序实现的,这是应为 MySQL 未提供预处理语句功能。出于该原因,驱动程序不实施 getParameterMetaData() 或 getMetaData(),这是因为,它要求驱动程序在客户端上具有完整的 SQL 语法分析程序。

从 3.1.0 版 MySQL Connector/J 开始,当服务器支持时,将使用服务器端预处理语句和“二进制编码”的结果集。

使用带有“large”参数 (这类参数是通过 setBinaryStream()、setAsciiStream()、setUnicodeStream()、setBlob() 或 setClob() 设置的) 的服务器端预处理语句时应谨慎。如果打算再次执行已将任何“large”参数更改为非“large”参数的语句,需要调用 clearParameters(),并再次设置所有参数。其原因如下:

o        设置了参数时,驱动程序会将“large”数据“out-of-band”发送给服务器端的预处理语句 (执行预处理语句之前)。

o        一旦完成,将关闭用于读取客户端上数据的流 (根据 JDBC 规范),而且不能再次读取流。

o        如果参数从“large”变为非“large”,驱动程序必须复位预处理语句的服务器端状态,以便允许已更改的参数区带以前的“large”值。这将删除已发送给服务器的所有“large”数据,因而需要通过 setBinaryStream()、setAsciiStream()、setUnicodeStream()、setBlob() 或 setClob() 方法再次发送数据。

因而,如果你打算将参数类型更改为非“large”类型,必须调用 clearParameters(),并在重新执行预处理语句之前再次设置预处理语句的所有参数。

·         ResultSet

在默认情况下,ResultSets(结果集) 是可完全检索的,并被保存在内存中。对于大多数情况,这是最有效的操作方式,而且还应归因于更容易实施的 MySQL 网络协议设计。如果你正在处理具有大量行或大数据的 ResultSets,而且无法在 JVM 内为所需内存分配大量空间,可以通知驱动程序以“流”方式返回结果,一次一行。

要想允许该功能,需要以下述方式创建 1 个语句实例:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
              java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

正向、只读结果集,以及 Integer.MIN_VALUE 的组合用于指示驱动程序以“流”方式按行处理结果集。此后,对于该语句创建的结果集,将按行检索。

对于该方式,有一些需注意的事项。能够在连接上发出任何其他查询之前,应读取结果集中的所有行 (或关闭结果集),否则将抛出异常。

能够释放这些锁定语句 (无论它们是 MyISAM 表级锁定,还是某些其他存储引擎如 InnoDB 中的行级锁定) 的最早时刻是完成语句时。

如果语句在事务的范围内,当事务完成后将释放锁定 (它意味着语句需首先完成)。与大多数其他数据库一样,在读取了语句上所有的未决结果集或关闭了语句的活动结果集之前,语句不会结束。

因此,如果正在使用“流式”结果,如果希望保持对特定表的同时访问,而这些表被生成结果集的语句所引用,就应尽快地处理“流式”结果。

·         ResultSetMetaData

仅当使用 MySQL 服务器 4.0 或更高版本时,“isAutoIncrement()”方法才能正确工作。

·         Statement

使用版本低于 3.2.1 的 JDBC 驱动程序,而且所连接的服务器版本低于 5.0.3 时,除了像前面介绍的那样切换结果集外,“setFetchSize()”方法不起作用。

MySQL 不支持 SQL 光标,而且 JDBC 驱动程序也不能模拟它们,因此“setCursorName()”没有效果。

26.3.3.3. Java,JDBC 和 MySQL 类型

MySQL Connector/J 在处理 MySQL 数据类型和 Java 数据类型的转换处理方面十分灵活。

尽管可能会出现舍入、溢出或精度损失,当在通常情况下,能够将任何 MySQL 数据类型转换为 java.lang.String,并能将任何数值类型转换为 Java 数值类型。

从 Connector/J 3.1.0 开始,按照 JDBC 规范的要求,JDBC 驱动程序将发出警告或抛出 DataTruncation 异常,除非通过使用“jdbcCompliantTruncation”属性并将其设为“假”,对连接进行相应配置取消了前述要求。

在下面的表格中,列出能可靠工作的转换:

表 26.2. ;转换表

下述 MySQL 数据类型

总能转换为下述 Java 类型

CHAR, VARCHAR, BLOB, TEXT, ENUM, and SET

java.lang.String, java.io.InputStream, java.io.Reader, java.sql.Blob, java.sql.Clob

FLOAT, REAL, DOUBLE PRECISION, NUMERIC, DECIMAL, TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT

java.lang.String, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Double, java.math.BigDecimal

注释:

与希望转换的 MySQL 数据类型相比,如果选择了精度较低的 Java 数值类型,可能会出现舍入、溢出或精度损失。

DATE, TIME, DATETIME, TIMESTAMP

java.lang.String, java.sql.Date, java.sql.Timestamp

在 MySQL 类型和 Java 类型之间,ResultSet.getObject()方法采用了下述类型转换方式,在可能的情况下遵从 JDBC 规范:

表 26.3. ;用于 ResultSet.getObject() 的 MySQL 类型和 Java 类型

MySQL类型名称

Java类返回

BIT(1) (new in MySQL-5.0)

java.lang.Boolean

BIT( > 1) (new in MySQL-5.0)

byte[]

TINYINT

java.lang.Boolean,如果将配置属性tinyInt1isBit”设为“真”(默认值),并将存储大小设为“1”;或java.lang.Integer,如果不是的话。

BOOL, BOOLEAN

请参见上面的TINYINT,它们目前是TINYINT(1)的别名。

SMALLINT[(M)] [UNSIGNED]

java.lang.Integer(无论是否为UNSIGNED)

MEDIUMINT[(M)] [UNSIGNED]

java.lang.Integer(无论是否为UNSIGNED)

INT,INTEGER[(M)] [UNSIGNED]

java.lang.Integer,如果是UNSIGNEDjava.lang.Long

BIGINT[(M)] [UNSIGNED]

java.lang.Long,如果是UNSIGNEDjava.math.BigInteger

FLOAT[(M,D)]

java.lang.Float

DOUBLE[(M,B)]

java.lang.Double

DECIMAL[(M[,D])]

java.math.BigDecimal

DATE

java.sql.Date

DATETIME

java.sql.Timestamp

TIMESTAMP[(M)]

java.sql.Timestamp

TIME

java.sql.Time

YEAR[(2|4)]

java.sql.Date(日期设为21日晚上2点)

CHAR(M)

java.lang.String(除非列的字符集是BINARY),然后返回字节[]

VARCHAR(M) [BINARY]

java.lang.String(除非列的字符集是BINARY),然后返回字节[]

BINARY(M)

byte[]

VARBINARY(M)

byte[]

TINYBLOB

byte[]

TINYTEXT

java.lang.String

BLOB

byte[]

TEXT

java.lang.String

MEDIUMBLOB

byte[]

MEDIUMTEXT

java.lang.String

LONGBLOB

byte[]

LONGTEXT

java.lang.String

ENUM('value1','value2',...)

java.lang.String

SET('value1','value2',...)

java.lang.String

26.3.3.4. ;使用字符集和 Unicode

对于从 JDBC 驱动程序发往服务器的所有字符串,均将自动地从固有放热 Java Unicode 形式转换为客户端字符编码,包括通过Statement.execute()Statement.executeUpdate() 和 Statement.executeQuery() 发出的所有查询,以及除了用setBytes()、setBinaryStream()setAsiiStream()setUnicodeStream()setBlob() 排除的参试之外的所有 PreparedStatementCallableStatement 参数

在 MySQL 服务器 4.1 之前,Connector/J 支持每连接单一字符编码,能够从服务器配置自动检测到它,也能由用户通过使用useUnicodecharacterEncoding属性配置它。

从 MySQL 服务器 4.1 版起,Connector/J 支持客户端和服务器之间的但以字符编码,以及针对结果集中从服务器返回至客户端的数据的任意数目字符编码。

连接时将自动检测客户端和服务器之间的字符编码。对于由驱动程序使用的编码来说,它是在服务器上通过使用配置变量“character_set”(低于 4.1.0 的服务器版本) 和“character_set_server”(4.1.0 和更高的服务器版本) 指定的。更多信息,请参见 MySQL 服务器手册中的http://www.mysql.com/doc/en/Charset-server.html一节。

要想覆盖客户端上的自动检测编码功能,可在用于连接到服务器的 URL 中使用“characterEncoding”属性。

在客户端上指定字符编码时,应使用 Java 风格名称。在下面的表格中,列出了用于 MySQL 字符集的 Java 风格名称:

表 26.4. MySQL 对 Java 编码名称的翻译

MySQL字符集名称 Java风格字符编码名称
usa7US-ASCII
big5Big5
gbkGBK
sjisSJIS
gb2312EUC_CN
ujisEUC_JP
euc_krEUC_KR
latin1ISO8859_1
latin1_deISO8859_1
german1ISO8859_1
danishISO8859_1
latin2ISO8859_2
czechISO8859_2
hungarianISO8859_2
croatISO8859_2
greekISO8859_7
hebrewISO8859_8
latin5ISO8859_9
latvianISO8859_13
latvian1ISO8859_13
estoniaISO8859_13
dosCp437
pclatin2Cp852
cp866Cp866
koi8_ruKOI8_R
tis620TIS620
win1250Cp1250
win1250chCp1250
win1251Cp1251
cp1251Cp1251
win1251ukrCp1251
cp1257Cp1257
macromanMacRoman
macceMacCentralEurope
utf8UTF-8
ucs2UnicodeBig

警告

不要用 Connector/J 发出查询“set names”,这是因为驱动程序不会检测已变化的字符集,而是会继续使用在初始连接设置中检测到的字符集。

为了允许从客户端发出的多个字符集,应使用“UTF-8”编码,方式是,将 utf8 配置为默认的服务器字符集,或通过“characterEncoding”属性配置 JDBC 驱动程序以使用“UTF-8”。

26.3.3.5. ;使用 SSL 进行安全连接

MySQL Connector/J 中的 SSL 能够对 JDBC 驱动程序和服务器之间传输的所有数据进行加密 (除了初始握手数据)。启用 SSL 会导致性能损失,体现在查询时间将增加 35~50%,具体情况取决于查询的大小以及返回的数据量。

要想使 SSL 支持能够工作,必须满足下述要求:

·         包含 JSSE(Java 安全套接字扩展) 的 JDK,如 JDK-1.4.1 或更高版本。SSL 目前不能与能够为其添加 JSSE 的 JDK 一起工作,如 JDK-1.2.x 或 JDK-1.3.x,原因在于下述 JSSE 缺陷:http://developer.java.sun.com/developer/bugParade/bugs/4273544.html

·         支持 SSL 并已编译和配置了该功能的 MySQL 服务器,如 MySQL-4.0.4 和更高版本,请参见:http://www.mysql.com/doc/en/Secure_connections.html

·         客户端证书 (在本节稍后介绍)。

首先,需要将 MySQL 服务器 CA 证书导入到 Java truststore。在 MySQL 源码分发版的“SSL”子目录下给出了 1 个示例 MySQL 服务器 CA 证书。SSL 将使用它来确定是否与安全 MySQL 服务器进行通信。

要想使用 Java 的“keytool”在当前目录下创建 truststore,并导入服务器的 CA 证书 (“cacert.pem”),可采取下述方式 (假定“keytool”位于路径中。它位于 JDK 或 JRE 的“bin”子目录下):

shell> keytool -import -alias mysqlServerCACert -file cacert.pem -keystore truststore
        

Keytool 将给出下述响应信息:

Enter keystore password:  *********
Owner: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Orenburg, ST=Some
-State, C=RU
Issuer: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Orenburg, ST=Som
e-State, C=RU
Serial number: 0
Valid from: Fri Aug 02 16:55:53 CDT 2002 until: Sat Aug 02 16:55:53 CDT 2003
Certificate fingerprints:
         MD5:  61:91:A0:F2:03:07:61:7A:81:38:66:DA:19:C4:8D:AB
         SHA1: 25:77:41:05:D5:AD:99:8C:14:8C:CA:68:9C:2F:B8:89:C3:34:4D:6C
Trust this certificate? [no]:  yes
Certificate was added to keystore

随后,需要生成客户端证书,以便 MySQL 服务器知道它正与安全客户端进行通信:

 shell> keytool -genkey -keyalg rsa -alias mysqlClientCertificate -keystore keystore 

Keytool 将给出下述提示信息,并在当目录下创建名为“keystore”的密钥存储器。

你应使用与具体情况相适应的新作出响应:

Enter keystore password:  *********
What is your first and last name?
  [Unknown]:  Matthews
What is the name of your organizational unit?
  [Unknown]:  Software Development
What is the name of your organization?
  [Unknown]:  MySQL AB
What is the name of your City or Locality?
  [Unknown]:  Flossmoor
What is the name of your State or Province?
  [Unknown]:  IL
What is the two-letter country code for this unit?
  [Unknown]:  US
Is <CN=Matthews, OU=Software Development, O=MySQL AB,
 L=Flossmoor, ST=IL, C=US> correct?
  [no]:  y
 
输入<mysqlClientCertificate>;的密码
        如果与 keystore 的密码相同,按回车):

最后,要想使 JSSE 能够使用你生成的 keystore 和 truststore,启动 JVM 时,需要设置下述系统属性,用你所创建的 keystore 文件完整路径替换“path_to_keystore_file”,用你所创建的 truststore 文件完整路径替换“path_to_truststore_file”,并为每个属性使用恰当的密码值。

-Djavax.net.ssl.keyStore=path_to_keystore_file
-Djavax.net.ssl.keyStorePassword=*********
-Djavax.net.ssl.trustStore=path_to_truststore_file
-Djavax.net.ssl.trustStorePassword=********* 

此外,还需要在用于 MySQL Connector/J 的连接参数中将“useSSL”设置为“真”,方法是,在 URL 中添加“useSSL=true”,或在准备传递给 DriverManager.getConnection() 的 java.util.Properties 实例中将“useSSL”设置为“真”。

你可以打开 JSSE 调试功能能够,测试 SSL 是否工作 (详情如下),并查找下述关键事件:

...
 *** ClientHello, v3.1
 RandomCookie:  GMT: 1018531834 bytes = { 199, 148, 180, 215, 74, 12, 54, 244, 0, 168, 55, 103, 215, 64, 16, 138, 225, 190, 132, 153, 2, 217, 219, 239, 202, 19, 121, 78 }
 Session ID:  {}
 Cipher Suites:  { 0, 5, 0, 4, 0, 9, 0, 10, 0, 18, 0, 19, 0, 3, 0, 17 }
 Compression Methods:  { 0 }
 ***
 [write] MD5 and SHA1 hashes:  len = 59
 0000: 01 00 00 37 03 01 3D B6   90 FA C7 94 B4 D7 4A 0C  ...7..=.......J.
 0010: 36 F4 00 A8 37 67 D7 40   10 8A E1 BE 84 99 02 D9  6...7g.@........
 0020: DB EF CA 13 79 4E 00 00   10 00 05 00 04 00 09 00  ....yN..........
 0030: 0A 00 12 00 13 00 03 00   11 01 00                 ...........
 main, WRITE:  SSL v3.1 Handshake, length = 59
 main, READ:  SSL v3.1 Handshake, length = 74
 *** ServerHello, v3.1
 RandomCookie:  GMT: 1018577560 bytes = { 116, 50, 4, 103, 25, 100, 58, 202, 79, 185, 178, 100, 215, 66, 254, 21, 83, 187, 190, 42, 170, 3, 132, 110, 82, 148, 160, 92 }
 Session ID:  {163, 227, 84, 53, 81, 127, 252, 254, 178, 179, 68, 63, 182, 158, 30, 11, 150, 79, 170, 76, 255, 92, 15, 226, 24, 17, 177, 219, 158, 177, 187, 143}
 Cipher Suite:  { 0, 5 }
 Compression Method: 0
 ***
 %% Created:  [Session-1, SSL_RSA_WITH_RC4_128_SHA]
 ** SSL_RSA_WITH_RC4_128_SHA
 [read] MD5 and SHA1 hashes:  len = 74
 0000: 02 00 00 46 03 01 3D B6   43 98 74 32 04 67 19 64  ...F..=.C.t2.g.d
 0010: 3A CA 4F B9 B2 64 D7 42   FE 15 53 BB BE 2A AA 03  :.O..d.B..S..*..
 0020: 84 6E 52 94 A0 5C 20 A3   E3 54 35 51 7F FC FE B2  .nR..\ ..T5Q....
 0030: B3 44 3F B6 9E 1E 0B 96   4F AA 4C FF 5C 0F E2 18  .D?.....O.L.\...
 0040: 11 B1 DB 9E B1 BB 8F 00   05 00                    ..........
 main, READ:  SSL v3.1 Handshake, length = 1712
 ...

设置了下述系统属性时,JSSE 可提供调试功能 (为 STDOUT):-Djavax.net.debug=all。它用于设定要使用的 keystores 和 truststores,以及在 SSL 握手和证书交换过程中将出现什么。当你尝试进行 SSL 连接时,如果打算确定不能工作的部分,该设置十分有用。

26.3.3.6. ;使用主/从复制和 ReplicationConnection

从 Connector/J 3.1.7 开始,我们提供了 1 个驱动程序变体,它能自动发出读/写主服务器的查询,或根据Connection.getReadOnly() 的状态对从主机进行故障切换或循环负载平衡设置。

应用程序发出信号,通过调用Connection.setReadOnly(true) 指明事务为只读的,该具有复制意识的连接将使用从连接之一,从连接是采用了循环方案的负载平衡 per-vm(给定连接与从连接密切相关,除非在服务中删除了从连接)。如果你有 1 项写事务,或 1 项对时间敏感的读事务 (记住,在 MySQL 中,复制是以异步方式进行的),请调用Connection.setReadOnly(false),将连接设置为非只读的,驱动程序会确保进一步的调用均将被发送到主 MySQL 服务器。驱动程序负责传播 autocommit 的当前状态,隔离级别,以及用于完成该负载平衡功能的所有连接之间的目录。

要想启用该该功能,在配置应用服务器的连接池时,或为独立应用程序创建 JDBC 驱动实例时,请使用“com.mysql.jdbc.ReplicationDriver”类。由于它能接受与标准 MySQL JDBC 驱动相同的 URL 格式,ReplicationDriver 目前不能与基于 java.sql.DriverManager 的连接一起使用,除非它是用 DriverManager 注册的唯一MySQL JDBC 驱动程序。

下面给出了一个简短的简单示例,介绍了如何在独立应用程序中使用 ReplicationDriver 的方法。

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Properties;
 
import com.mysql.jdbc.ReplicationDriver;
 
public class ReplicationDriverDemo {
 
    public static void main(String[] args) throws Exception {
        ReplicationDriver driver = new ReplicationDriver();
 
        Properties props = new Properties();
 
        // We want this for failover on the slaves
        props.put("autoReconnect", "true");
 
        // We want to load balance between the slaves
        props.put("roundRobinLoadBalance", "true");
 
        props.put("user", "foo");
        props.put("password", "bar");
 
        //
        // Looks like a normal MySQL JDBC url, with a comma-separated list
        // of hosts, the first being the 'master', the rest being any number
        // of slaves that the driver will load balance against
        //
 
        Connection conn =
            driver.connect("jdbc:mysql://master,slave1,slave2,slave3/test",
                props);
 
        //
        // Perform read/write work on the master
        // by setting the read-only flag to "false"
        //
 
        conn.setReadOnly(false);
        conn.setAutoCommit(false);
        conn.createStatement().executeUpdate("UPDATE some_table ....");
        conn.commit();
 
        //
        // Now, do a query from a slave, the driver automatically picks one
        // from the list
        //
 
        conn.setReadOnly(true);
 
        ResultSet rs = conn.createStatement().executeQuery("SELECT a,b,c FROM some_other_table");
 
         .......
    }
}

26.3.4. ;与 J2EE 和其他 Java 框架一起使用 Connector/J

本节介绍了在数种不同情况下使用 Connector/J 的方法。

26.3.4.1. ;一般 J2EE 概念

在本节中,介绍了与 Connector/J 使用有关的 J2EE 概念的基本知识。
26.3.4.1.1. ;理解连接池
连接池是创建和管理多个连接的一种技术,这些连接可被需要使用它们的任何线程使用。连接池技术基于下述事实:对于大多数应用程序,当它们正在处理通常需要数毫秒完成的事务时,仅需要能够访问 JDBC 连接的 1 个线程。未处理事务时,连接处于闲置状态。使用连接池,允许其他线程使用闲置连接来执行有用的任务。

事实上,当某一线程需要用 JDBC 在 MySQL 或其他数据库上执行操作时,需要用到由连接池提供的连接。使用连接完成线程后,线程会将连接返回给连接池,以便该连接能够被其他需要使用连接的线程使用。

从连接池“借出”连接时,该连接仅供请求它的线程使用。从编程观点看,其效果等同于每次需要 JDBC 连接时调用 DriverManager.getConnection(),但是,采用连接池技术,可通过使用新的或已有的连接结束线程。

连接池技术能显著增加 Java 应用程序的性能,同时还能降低资源使用率。连接池技术的主要优点包括:

·         缩短了连接创建时间

与其他数据库相比,MySQL 提供了快速的连接设置功能,连接时间通常不是问题,但创建新的 JDBC 连接仍会导致联网操作和一定的 IDBC 驱动开销,如果这类连接是“循环”使用的,使用该方式,可避免这类不利因素。

·         简化的编程模型

使用连接池技术时,每个单独线程能够像创建了自己的 JDBC 连接那样进行操作,从而允许使用直接的 JDBC 编程技术。

·         受控的资源使用

如果不使用连接池技术,而是在每次需要时为线程创建新的连接,那么应用程序的资源使用将十分浪费,而且在负载较重的情况下会导致无法预期的结果。

注意,与 MySQL 的每个连接均会在客户端和服务器端造成一定的开销 (每寸、CPU、关联转换等)。每个连接均会对应用程序和 MySQL 服务器的可用资源带来一定的限制。无论连接是否执行任何有用的任务,仍将使用这些资源中的相当一部分。

连接池能够使性能最大化,同时还能将资源利用控制在一定的水平之下,如果超过该水平,应用程序将崩溃而不仅仅是变慢。

幸运的是,Sun 公司通过 JDBC-2.0“可选”接口,完成了 JDBC 中连接池概念的标准化实施,所有主要应用服务器均实施了能够与 MySQL Connector/J 一起良好工作的这类 API。

通常,你可以在应用服务器的配置文件中配置连接池,并通过 Java 命名和目录接口 (JNDI) 访问它。在下面的代码中,介绍了在 J2E 应用服务器上运行的应用程序中使用连接池的方法:

示例 26.12. ;与 J2EE 应用服务器一起使用连接池

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.InitialContext;
import javax.sql.DataSource;


public class MyServletJspOrEjb {

    public void doSomething() throws Exception {
        /*
         * Create a JNDI Initial context to be able to
         *  lookup  the DataSource
         *
         * In production-level code, this should be cached as
         * an instance or static variable, as it can
         * be quite expensive to create a JNDI context.
         *
         * Note: This code only works when you are using servlets
         * or EJBs in a J2EE application server. If you are
         * using connection pooling in standalone Java code, you
         * will have to create/configure datasources using whatever
         * mechanisms your particular connection pooling library
         * provides.
         */

        InitialContext ctx = new InitialContext();

         /*
          * Lookup the DataSource, which will be backed by a pool
          * that the application server provides. DataSource instances
          * are also a good candidate for caching as an instance
          * variable, as JNDI lookups can be expensive as well.
          */

        DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");

        /*
         * The following code is what would actually be in your
         * Servlet, JSP or EJB 'service' method...where you need
         * to work with a JDBC connection.
         */

        Connection conn = null;
        Statement stmt = null;

        try {
            conn = ds.getConnection();

            /*
             * Now, use normal JDBC programming to work with
             * MySQL, making sure to close each resource when you're
             * finished with it, which allows the connection pool
             * resources to be recovered as quickly as possible
             */

            stmt = conn.createStatement();
            stmt.execute("SOME SQL QUERY");

            stmt.close();
            stmt = null;

            conn.close();
            conn = null;
        } finally {
            /*
             * close any jdbc instances here that weren't
             * explicitly closed during normal code path, so
             * that we don't 'leak' resources...
             */

            if (stmt != null) {
                try {
                    stmt.close();
                } catch (sqlexception sqlex) {
                    // ignore -- as we can't do anything about it here
                }

                stmt = null;
            }

            if (conn != null) {
                try {
                    conn.close();
                } catch (sqlexception sqlex) {
                    // ignore -- as we can't do anything about it here
                }

                conn = null;
            }
        }
    }
}

如上例所示,获得 JNDI InitialContext 并查找到数据库后,其余代码与过去在 JDBC 编程中使用的类似。

使用连接池时需要牢记的最重要事项是,无论在代码中出现了什么 (异常、控制流等),连接以及由连接创建的任何部分 (语句、结果集等) 均应被关闭,以便能再次使用它们。如不然,它们将纠缠在一起,在最好的情况下,意味着它们所代表的 MySQL 服务器资源 (缓冲区、锁定、套接字等) 可能会捆绑一段时间,在最坏的情况下,可能会导致永久捆绑。

连接池的最佳大小是什么?

与所有其他配置经验规则一样,回答是“它取决于具体情况”。尽管最佳大小取决与预期的负载和平均的数据库事务时间,最佳的连接池大小小于你的预期。例如,如果使用的是 Sun 公司的 Java Petstore Blueprint 应用程序,对于包含 15~20 个连接的连接池,使用 MySQL 和 Tomcat,在可接受的相应时间下,可服务于中等程度的负载 (600 个并发用户)。

要想确定用于应用程序的连接池大小,应使用诸如 Apache Jmeter 或 The Grinder 等工具创建负载测试脚本,并对应用程序进行负载测试。

确定出发点的一种简单方法是,将连接池的最大连接数配置为“无限”,运行负载测试,并测量最大的并发连接数。随后,应进行反向操作,确定出使应用程序具有最佳性能的连接池的最小和最大值。

26.3.4.2. ;与 Tomcat 一起使用 Connector/J

下述内容基于关于 Tomcat-5.x 的指示说明,http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html,在编写本文档时它是最新的。

首先安装与 Connector/J in $ CATALINA_HOME/common/lib 一起提供的.jar 文件,以便它能用于已安装的所有应用程序。

其次,在定义 Web 应用程序的 Context(场景) 内,通过为$CATALINA_HOME/conf/server.xml 增加声明资源,配置JNDI DataSource:

<Context ....>

  ...

  <Resource name="jdbc/MySQLDB"
               auth="Container"
               type="javax.sql.DataSource"/>

  <!-- The name you used above, must match _exactly_ here!

       The connection pool will be bound into JNDI with the name
       "java:/comp/env/jdbc/MySQLDB"
  -->

  <ResourceParams name="jdbc/MySQLDB">
    <parameter>
      <name>factory</name>
      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
    </parameter>

    <!-- Don't set this any higher than max_connections on your
         MySQL server, usually this should be a 10 or a few 10's
         of connections, not hundreds or thousands -->

    <parameter>
      <name>maxActive</name>
      <value>10</value>
    </parameter>

    <!-- You don't want to many idle connections hanging around
         if you can avoid it, only enough to soak up a spike in
         the load -->

    <parameter>
      <name>maxIdle</name>
      <value>5</value>
    </parameter>

    <!-- Don't use autoReconnect=true, it's going away eventually
         and it's a crutch for older connection pools that couldn't
         test connections. You need to decide if your application is
         supposed to deal with SQLExceptions (hint, it should), and
         how much of a performance penalty you're willing to pay
         to ensure 'freshness' of the connection -->

    <parameter>
      <name>validationQuery</name>
      <value>SELECT 1</value>
    </parameter>

   <!-- The most conservative approach is to test connections
        before they're given to your application. For most applications
        this is okay, the query used above is very small and takes
        no real server resources to process, other than the time used
        to traverse the network.

        If you have a high-load application you'll need to rely on
        something else. -->

    <parameter>
      <name>testOnBorrow</name>
      <value>true</value>
    </parameter>

   <!-- Otherwise, or in addition to testOnBorrow, you can test
        while connections are sitting idle -->

    <parameter>
      <name>testWhileIdle</name>
      <value>true</value>
    </parameter>

    <!-- You have to set this value, otherwise even though
         you've asked connections to be tested while idle,
         the idle evicter thread will never run -->

    <parameter>
      <name>timeBetweenEvictionRunsMillis</name>
      <value>10000</value>
    </parameter>

    <!-- Don't allow connections to hang out idle too long,
         never longer than what wait_timeout is set to on the
         server...A few minutes or even fraction of a minute
         is sometimes okay here, it depends on your application
         and how much spikey load it will see -->

    <parameter>
      <name>minEvictableIdleTimeMillis</name>
      <value>60000</value>
    </parameter>

    <!-- Username and password used when connecting to MySQL -->

    <parameter>
     <name>username</name>
     <value>someuser</value>
    </parameter>

    <parameter>
     <name>password</name>
     <value>somepass</value>
    </parameter>

    <!-- Class name for the Connector/J driver -->

    <parameter>
       <name>driverClassName</name>
       <value>com.mysql.jdbc.Driver</value>
    </parameter>

    <!-- The JDBC connection url for connecting to MySQL, notice
         that if you want to pass any other MySQL-specific parameters
         you should pass them here in the URL, setting them using the
         parameter tags above will have no effect, you will also
         need to use &amp; to separate parameter values as the
         ampersand is a reserved character in XML -->

    <parameter>
      <name>url</name>
      <value>jdbc:mysql://localhost:3306/test</value>
    </parameter>

  </ResourceParams>
</Context>

一般而言,应遵循关于相应 Tomcat 版本的安装说明,这是因为,在 Tomcat 中配置数据源的方式会随时变化,很不幸,如果在 XML 文件中使用了错误的语法,很可能会以异常结束,如下所示:

Error: java.sql.SQLException: Cannot load JDBC driver class 'null ' SQL
state: null 

26.3.4.3. ;与 JBoss 一起使用 Connector/J

下述说明适用于 JBoss-4.x。要想使应用服务器能够使用 JDBC 驱动类,请将与 Connector/J 一起提供的。jar 文件拷贝到用于服务器配置的 lib 目录下 (通常称为“默认”)。随后,在相同的配置目录下,在名为“deploy”的子目录下,创建以“-ds.xml”结尾的数据源配置文件,用于通知 Jboss 将该文件当作 JDBC 数据源。该文件应包含下述内容:

<datasources>
    <local-tx-datasource>
        <!-- This connection pool will be bound into JNDI with the name
             "java:/MySQLDB" -->

        <jndi-name>MySQLDB</jndi-name>
        <connection-url>jdbc:mysql://localhost:3306/dbname</connection-url>
        <driver-class>com.mysql.jdbc.Driver</driver-class>
        <user-name>user</user-name>
        <password>pass</password>

        <min-pool-size>5</min-pool-size>

        <!-- Don't set this any higher than max_connections on your
         MySQL server, usually this should be a 10 or a few 10's
         of connections, not hundreds or thousands -->

        <max-pool-size>20</max-pool-size>

        <!-- Don't allow connections to hang out idle too long,
         never longer than what wait_timeout is set to on the
         server...A few minutes is usually okay here,
         it depends on your application
         and how much spikey load it will see -->

        <idle-timeout-minutes>5</idle-timeout-minutes>

        <!-- If you're using Connector/J 3.1.8 or newer, you can use
             our implementation of these to increase the robustness
             of the connection pool. -->

        <exception-sorter-class-name>com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter</exception-sorter-class-name>
        <valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name>

    </local-tx-datasource>
</datasources> 

26.3.5. ;诊断 Connector/J 方面的问题

在本节中,介绍了如何解决使用 Connector/J 时遇到的问题。

26.3.5.1. ;常见问题和解决方案

对于MySQL Connector/J用户,会遇到一些常见的共同问题。在本节中,介绍了它们的症状和相应的解决方法。 关于更进一步的信息,请参见“支持”一节。

27.3.5.1.1:

问题:

当我尝试用 MySQL Connector/J 连接到数据库时,遇到下述异常:

SQLException: Server configuration denies access to data source
SQLState: 08001
VendorError: 0

出现了什么问题? 使用 MySQL 命令行客户端时,连接良好。

回答:

MySQL Connector/J 必须使用 TCP/IP 套接字来连接 MySQL,原因在于 Java 不支持 Unix Domain 套接字。因此,当 MySQL Connector/J 连接到 MySQL 时,MySQL 服务器的安全管理器将使用其授权表判断是否允许连接。必须添加授权才能允许该操作。下面给出了一个执行该操作的示例 (但并非最安全的)。

从 mysql 命令行客户端以能够授权的用户身份登录,并发出下述命令:

GRANT ALL PRIVILEGES ON [dbname].* to
                '[user]'@'[hostname]' identified by
                '[password]'

用你的数据库名称替换 [dbname],用用户名替换 [user],用 MySQL Connector/J 将连接的主机替换 [hostname],并用打算使用的密码替换 [password]。注意,对于从本地主机进行连接的主机名部分,RedHat Linux 将失败。在这种情况下,对于 [hostname] 值,需要使用“localhost.localdomain”。随后,发出 FLUSH PRIVILEGES 命令。

注释:

除非添加了“--host”标志,并为主机使用了不同于“localhost”的其他设置,否则将无法使用 mysql 命令行客户端测试连通性。如果使用了特殊的主机名“localhost”,mysql 命令行客户端将使用 Unix 域套接字。如果正在测试与“localhost”的连通性,请使用“127.0.0.1”作为主机名。

警告

如果你不了解“GRANT”命令是干什么的,或不了解该命令的工作方式,在尝试更改权限之前,请阅读 MySQL 手册中的 一般安全事宜以及MySQL访问权限体系一节。

如果在 MySQL 中不恰当地更改了权限和许可,可能会使服务器不会具有最佳的安全性能。

27.3.5.1.2:

问题:

我的应用程序抛出 SQLException“无恰当的驱动程序”。为什么会出现该情况?

回答:

出现了两种情况之一。或是 1 驱动程序未位于你的 CLASSPATH 中 (请参见前面的“安装部分”),或是 URL 格式不正确 (请参见用 MySQL Connector/J 开发应用程序)。

27.3.5.1.3:

问题:

当我试图在 Java 程序或应用程序中使用 MySQL Connector/J 时,遇到类似下面的异常:

SQLException:无法连接到 host:3306 上的 MySQL 服务器。
在你尝试连接的机器/端口上是否有正在运行的 MySQL 服务器?
 
(java.security.AccessControlException)
SQLState: 08S01
VendorError: 0 

回答:

或许是因为你正在运行 Applet,你的 MySQL 服务器是采用“--skip-networking”选项集安装的;或许是因为 MySQL 服务器位于防火墙之后。

Applet 仅能使网络连接返回运行 Web 服务器的机器,该 Web 服务器提供了用于 Applet 的。class 文件。这意味着,要想使其工作,MySQL 必须运行在相同的机器上 (或必须使某类端口重定向)。这还意味着,你无法通过你的本地文件系统来测试 Java 程序,你必须将它们放在 Web 服务器上。

MySQL Connector/J 仅能使用 TCP/IP 与 MySQL 进行通信,这是因为 Java 不支持 Unix 域套接字。如果 MySQL 是用“--skip-networking”标志启动的,或采用了防火墙,TCP/IP 与 MySQL 的通信可能会受到影响。

如果 MySQL 是用“--skip-networking”选项集启动的 (例如 MySQL 服务器的 Debian Linux 包即用于该目的),需要在文件/etc/mysql/my.cnf 或/etc/my.cnf 中将其注释掉。当然,my.cnf 文件也可能位于 MySQl 服务器的“data”目录下或其他地方 (取决于系统中 MySQL 的编译方式)。MySQL AB 创建的二进制文件总会在查找/etc/my.cnf 和 [datadir]/my.cnf。如果为 MySQL 服务器部署了防火墙,需要对防火墙进行配置,允许从运行 Java 代码的主机在 MySQL 监听的端口上 (默认为 3306) 建立与 MySQL 服务器的 TCP/IP 连接。

27.3.5.1.4:

问题:

I 我的小服务程序/应用程序白天工作良好,但在晚上却停止工作。

回答:

不工作时间超过 8 小时后,MySQL 关闭了连接。你或许需要使用能处理失效连接的连接池,或使用“autoReconnect”参数 (请参见用 MySQL Connector/J 开发应用程序)。

此外,你应在应用程序中俘获 SQLException 并处理它们,而不是在应用程序退出前一直传播它们,这是 1 个好的编程习惯。在查询处理过程中遇到网络连通性方面的问题时,MySQL Connector/J 会将 SQLState(参见 APIDOCS 中的 java.sql.SQLException.getSQLState()) 设置为“08S01”。随后,应用程序代码将尝试再次连接到 MySQL。

在下面的示例 (simplistic) 中,给出了能够处理这类异常的代码:

示例 26.13. ;重试逻辑的事务示例

public void doBusinessOp() throws SQLException {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        //
        // How many times do you want to retry the transaction
        // (or at least _getting_ a connection)?
        //
        int retryCount = 5;

        boolean transactionCompleted = false;

        do {
            try {
                conn = getConnection(); // assume getting this from a
                                        // javax.sql.DataSource, or the
                                        // java.sql.DriverManager

                conn.setAutoCommit(false);

                //
                // Okay, at this point, the 'retry-ability' of the
                // transaction really depends on your application logic,
                // whether or not you're using autocommit (in this case
                // not), and whether you're using transacational storage
                // engines
                //
                // For this example, we'll assume that it's _not_ safe
                // to retry the entire transaction, so we set retry count
                // to 0 at this point
                //
                // If you were using exclusively transaction-safe tables,
                // or your application could recover from a connection going
                // bad in the middle of an operation, then you would not
                // touch 'retryCount' here, and just let the loop repeat
                // until retryCount == 0.
                //
                retryCount = 0;

                stmt = conn.createStatement();

                String query = "SELECT foo FROM bar ORDER BY baz";

                rs = stmt.executeQuery(query);

                while (rs.next()) {
                }

                rs.close();
                rs = null;

                stmt.close();
                stmt = null;

                conn.commit();
                conn.close();
                conn = null;

                transactionCompleted = true;
            } catch (SQLException sqlEx) {

                //
                // The two SQL states that are 'retry-able' are 08S01
                // for a communications error, and 41000 for deadlock.
                //
                // Only retry if the error was due to a stale connection,
                // communications problem or deadlock
                //

                String sqlState = sqlEx.getSQLState();

                if ("08S01".equals(sqlState) || "41000".equals(sqlState)) {
                    retryCount--;
                } else {
                    retryCount = 0;
                }
            } finally {
                if (rs != null) {
                    try {
                        rs.close();
                    } catch (SQLException sqlEx) {
                        // You'd probably want to log this . . .
                    }
                }

                if (stmt != null) {
                    try {
                        stmt.close();
                    } catch (SQLException sqlEx) {
                        // You'd probably want to log this as well . . .
                    }
                }

                if (conn != null) {
                    try {
                        //
                        // If we got here, and conn is not null, the
                        // transaction should be rolled back, as not
                        // all work has been done

                        try {
                            conn.rollback();
                        } finally {
                            conn.close();
                        }
                    } catch (SQLException sqlEx) {
                        //
                        // If we got an exception here, something
                        // pretty serious is going on, so we better
                        // pass it up the stack, rather than just
                        // logging it. . .

                        throw sqlEx;
                    }
                }
            }
        } while (!transactionCompleted && (retryCount > 0));
    }

27.3.5.1.5:

问题:

我正尝试使用 JDBC-2.0 可更新结果集,但遇到异常,说我的结果集不可更新。

回答:

由于 MySQL 没有行 ID,MySQL Connector/J 仅能更新来自查询且位于有至少一个主键的表上的结果集,查询必须选择所有的主键,而且查询即能作用在 1 个表上 (即不存在联合)。在 JDBC 规范中给出了这方面的介绍。

26.3.5.2. ;如何通报缺陷和问题

通报缺陷的正常地址是http://bugs.mysql.com/,它也是我方缺陷数据库的地址。这是 1 个公共数据库,任何人都能浏览它并进行相应的搜索。如果你已登录到系统,也应能输入新的报告。

如果发现 MySQL 中存在敏感的安全缺陷,请发送电子邮件至security@mysql.com

编写良好的缺陷报告需要耐心,但在第 1 时间正确地完成它不仅能节省我们的时间,也能节省你自己的时间。良好的缺陷报告应包含对缺陷的完整测试情况,以便我们你能够在下个版本中更正该缺陷。

本节介绍的内容用于帮助你正确地编写报告,从避免将你的时间浪费在对我们帮助不大或没有帮助的事上,

如果有 1 份可重复的缺陷报告,请将其提交到缺陷数据库,http://bugs.mysql.com/

对于任何我们能再现的缺陷,在下一个 MySQL 版本中修正它的机会很大。

要想通报其他问题,请使用 MySQL 邮件列表。

请注意,我们可能会对包含过多信息的消息作出响应,但不太会对包含过少信息的消息作出回应。人们常会省略掉一些事实,因为他们认为自己知道了故障的原因,并想当然地认为这类细节无关紧要。

良好的原则是:如果你对陈述某事犹豫不定,请陈述之。如果我们要求你提供初始报告中缺少的信息,在报告中编写多行信息源比等候回复要快,麻烦也更小。

在缺陷报告,最常犯的错误包括:(a) 未包含所使用 Connector/J 或 MySQL 的版本号,以及 (b) 未完全描述安装了 Connector/J 的平台 (包括 JVM 版本,平台类型,以及所安装 MySQL 本身的版本号)。

这是高度相关的信息,如果没有它,99%的缺陷报告无用。我们遇到这类问题,“为何它对我没用”? 随后,我们发现在该 MySQL 版本中,所请求的特性尚未实施,或在较新的 MySQL 版本中已更正了报告中描述的缺陷。

有些时候,错误与平台相关,在这类情况下,如果不知道操作系统和平台的版本号,我们几乎不可能更正任何问题。

如果可能,你应创建 1 份可重复的、不含任何第三方类的独立测试案例。

为了是该进程流线化,我们与 Connector/J 一起提供了用于测试的基本类,名为com.mysql.jdbc.util.BaseBugReport。要想使用该类为 Connector/J 创建 1 个测试案例,你应应创建自己的从com.mysql.jdbc.util.BaseBugReport 继承的类,并覆盖方法 setUp()tearDown()runTest()。

setUp()方法中,创建用于创建表的代码,并用演示缺陷所需的数据填充表。

runTest () 方法中,使用在“setUp”方法中创建的表和数据,创建用于演示缺陷的代码。

tearDown()方法中,撤销在setUp() 方法中创建的任何表。

对于上述三种方法中的任何一种,应使用getConnection () 各种变体中的一种创建与 MySQL 的 JDBC 连接。

·         getConnection():提供了与在 getUrl() 中指定的 JDBC URL 的连接。如果连接已存在,返回该连接,否则将创建新的连接。

·         getNewConnection():如果需要为缺陷报告获得新的连接 (即包含 1 个以上的连接),应使用它。

·         getConnection(String url):使用给定的 URL 返回连接。

·         getConnection(String url, Properties props):使用给定的 URL 和属性返回连接。

如果需要使用不同于“jdbc:mysql:///test”的 JDBC URL,还应覆盖方法getUrl()

在演示你所预计行为的测试案例中 (相对于你观察到的世纪行为,这是你填充错误报告的最可能原因),使用assertTrue(boolean expression)assertTrue(String failureMessage, boolean expression)方法创建必须满足的条件。

最后,创建用于创建测试案例实例的main () 方法,并调用 run 方法:

public static void main(String[] args) throws Exception {
      new MyBugReport().run();
 }

完成了测试案例并证实它能演示你所通报的缺陷后,请将该案例与缺陷报告一起上传到http://bugs.mysql.com/

26.3.6. Changelog

# Changelog
# $ Id: CHANGES,v 1.38.4.206 2005/05/12 15:25:54 mmatthews Exp $
 
05-17-05:版本3.2.1-alpha
 
    - 现已不再重视 Autoreconnect 功能 (即 autoReconnect=true)。
      如果尝试并使用它将抛出异常,使用“enableDeprecatedAutoreconnect=true”可继续使用 autoReconnect。但是,在 Connector/J 3.3 中将删除该项特性,请参见手册中关于不需要使用 autoReconnect 的相应解决方案。
 
    - 现在,驱动程序将检查是否设置了服务器变量“init_connect”,如果设置了该变量,将检查 autocommit(自动提交) 设置,并应用它。
  
    - 如果连接的服务器版本在 5.0.x 以上,而且 Statement.setFetchSize( > 0),驱动程序将尝试使用服务器预处理语句,并使用结果集“cursors”获取语句。
  
    - ServerPreparedStatements 现在能正确地将 BLOB/CLOB 数据以“流方式”发送至服务器。你可以使用属性“blobSendChunkSize”配置程序块大小的阈值 (默认值为 1MB)。
  
    - 支持 sql 模式 NO_BACKSLASH_ESCAPES 以及非服务器端预处理语句。
 
12-23-04:版本3.2.0-alpha
 
    -更正了 DatabaseMetaData.supportsCatalogIn*() 错误的返回值。
    
    -使用 ServerPreparedStatements 以及 MySQL 5.0 或更高版本时,支持基于“cursor”的结果集。结果集需为“仅正向”结果集,并需启用针对该项特性的非零获取大小。
      
    - 重新分解了预处理语句的 where 逻辑,服务器端预处理语句保持有效。
 
10-07-05:版本3.1.11-stable
 
    - 更正了BUG#11629:当字符编码是“utf8”时控制台上的伪“!”。
      
    -更正了为丢失“;”(用于“plain”语句) 的测试案例生成的语句。
      
    - 更正了BUG#11663:为服务器端预处理语句生成的不正确的 testcase 脚本。
      
    -更正了因修补BUG#11552而导致的回归,对于BUG#11552,当整数处于正号类型的范围内时,对于无符号整数,该缺陷将导致驱动程序返回错误值。
    
    -将源代码移到了 svn repo。
    
    -更正了BUG#11797:转义标志不考虑用于转义用途的层套式单引号。
  
    -使用服务器端预处理语句时,不识别 GEOMETRY 类型。
    
    -更正了BUG#11879:ReplicationConnection 不会切换至从连接,抛出“目录不能为空”异常。
      
    -更正了BUG#12218,主连接和具有复制连接的从连接之间共享的属性。
      
    - 更正了BUG#10630。如果语句已关闭,Statement.getWarnings() 无法与 NPE 一起工作。
      
    -需要时,在 PreparedStatement.ParseInfo() 中,即能从 SQL 获取 char[]。
    
    -更正了BUG#12104,服务器端预处理语句不能处理 Geometry 类型。
      
    -更正了BUG#11614,使用多字节字符编码时,StringUtils.getBytes() 不工作,在“_characters_”中指定了长度。
      
    -更正了BUG#11798,Pstmt.setObject(...., Types.BOOLEAN) 抛出异常。
    
    -更正了BUG#11976,maxPerformance.properties 拼错“elideSetAutoCommits”。
  
    -更正了BUG#11575,对于在 Window 平台上的服务器,DBMD.storesLower/Mixed/UpperIdentifiers() 通报不正确的值。
  
    -更正了BUG#11190,在 ResultSet.moveToCurrentRow() 之前调用了 ResultSet.moveToInsertRow() 时,ResultSet.moveToCurrentRow() 不起作用。
  
    -更正了BUG#11115,使用服务器端预处理语句和。setBytes() 时,VARBINARY 数据发生崩溃。
 
    -更正了BUG#12229,服务器端预处理语句挂起 explainSlowQueries。
  
    -更正了BUG#11498,转义处理器不考虑用双引号分隔的字符串。
  
    -对于服务器端预处理语句,增加了对更改流参数的限制。只要在执行前设置了“_all_”流参数,可不必调用。clearParameters()。(由于客户端/服务器协议的限制,预处理语句不能复位服务器端的“_individual_ stream”数据)。
   
    -修改了 Field 类,*Buffer 和 MysqlIO,能够识别大于 Integer.MAX_VALUE 的字段长度。
  
    -更新了 DBMD.supportsCorrelatedQueries(),当版本高于 4.1 时返回“真”,更新了 supportsGroupByUnrelated() 使之返回“真”,并更新了 getResultSetHoldability() 使之返回 HOLD_CURSORS_OVER_COMMIT。
  
    -更正了BUG#12541,DatabaseMetaData.getIndexInfo() 中的 catalog(目录) 参量处理,它也意味着对 DatabaseMetaData 中下述方法的更改:
  
    - getBestRowIdentifier()
    - getColumns()
    - getCrossReference()
    - getExportedKeys()
    - getImportedKeys()
    - getIndexInfo()
    - getPrimaryKeys()
    - getProcedures() (and thus indirectly getProcedureColumns())
    - getTables()
  
上述所有方法中的“catalog”参量现具有下述行为特征:
  
  -如果指定为 Null,表示不会使用 catalog 来过滤结果 (因此将搜索所有数据库),除非在 JDBC URL 属性中设置了“nullCatalogMeansCurrent=true”。
 
  -指定为“”表示当前 catalog,尽管它不是十分兼容 JDBC 规范,但它是为传统用户保留的。
 
  -指定 catalog,使之按 API 文档中阐明的方式工作。
    
  -使得 jdbc2.optional 软件包中的“封装”连接能够使用 Connection.clientPrepare()(使用 ConnectionPoolDataSource 实例创建连接)。
 
    -为客户端增加了 Connection.isMasterConnection(),以确定多主机主/从连接是否连接至列表中的第 1 个主机。
 
    -更正了BUG#12753,URL 属性用于“=”的标志会导致“sessionVariables=....”无法正确地参数化。
 
    -更正了BUG#11781,当 DatabaseMetaData 方法使用该信息时,所引用的外键信息不能被正确解析。
 
    -考虑到流缓冲区大小和信息包报头,“sendBlobChunkSize”属性现在与“max_allowed_packet”密切结合在一起,当 max_allowed_packet 的大小类似于默认的“sendBlobChunkSize”时 (为 1MB),能避免 PacketTooBigExceptions。
 
    -CallableStatement.clearParameters() 现能清除与 INOUT/OUTPUT 参数和 INPUT 参数相关的属性。
 
    -更正了BUG#12417,Connection.prepareCall() 是区分大小写的数据库名称 (在 Windows 系统上)。
 
    -更正了BUG#12752,对于版本高于 4.0.x 的服务器,Cp1251 不正确地映射至 win1251。
 
    -更正了BUG#12970,使用 DatabaseMetaData.getColumns() 时,java.sql.Types.OTHER 返回 BINARY 和 VARBINARY 列。
  
    -引用参数约束列表前,ServerPreparedStatement.getBinding() 现在将检查语句是否已关闭,以避免抛出 NullPointerException。
 
    -更正了BUG#13277,无论何时,当调用需要连接引用的方法时,来自 Statement.getGeneratedKeys() 的 ResultSetMetaData 将导致 NullPointerExceptions 的抛出。
 
    -自 5.0 起,Field 类 ResultSetMetaData.getColumnClassName() 和 ResultSet.getObject(int) 的反向移植出现了变化,更正了 VARCHAR BINARY/VARBINARY 和相关类型有关的行为。
 
    -更正了 NullPointerException,当参数为 NULL 时,在很多 DatabaseMetaDataMethods 中将“catalog”参数转换为 byte[] 时出现的异常 (对于结果集)。(根据 JDBC 规范,从技术角度上不允许“null”,但从历史观点上,我们允许使用它)。
 
    -从 5.0 起,VAR[BINARY|CHAR] [BINARY] 类型检测的反向移植。
    
    -即使无法打开本地文件,也能读取 MysqlIO.sendFileToServer() 中响应,否则,下一个发出的查询将失败,这是因为,它正在读取对发送至服务器的空 LOAD DATA INFILE 信息包的响应。
 
    -避开了BUG#13374,已关闭结果集上的 ResultSet.getStatement() 返回 NULL(按照 JDBC 4.0 规范,但不具有向后兼容性)。将连接属性“retainStatementAfterResultSetClose”设为“真”,以便能够在通过。getStatement() 关闭了结果集后检索结果集的语句 (默认为“假”以便与 JDBC 兼容,并降低使用 JDBC 的代码名泄漏语句实例的机会)。
 
    -更正了BUG#13453,URL 配置参数不允许在它们的值中使用“&”或“=”。现在 JDBC 驱动程序能够对配置参数进行相应地解析,就像它们是使用 application/x-www-form-urlencoded 格式 (在 java.net.URLDecoder 中指定,http://java.sun.com/j2se/1.5.0/docs/api/java/net/URLDecoder.html) 进行编码那样。
 
如果在配置属性中出现字符“%”,现在必须用“%25”表示,它是使用“application/x-www-form-urlencoded”编码使“%”的已编码形式。
 
    -配置属性“sessionVariables”现在允许你指定以“@”符号开始的变量。
 
    -更正了BUG#13043,为低于 4.1.0 版的服务器允许了“gatherPerfMetrics”时,如果查询未使用任何表,结果集的构造函数将抛出 NullPointerException。
 
06-23-05:版本3.1.10-stable
 
    -更正了因无指定数据库而导致的 MysqlIO.changeDatabaseTo() 中的异常。
  
    -首次实现了用于 PreparedStatement.getParameterMetadata() 的 ParameterMetadata。仅能与 CallableStatements 一起完全发挥作用,这是因为当前的服务器端预处理语句会将所有参数返回为 VARCHAR 类型。
    
06-22-05:版本3.1.9-stable
 
    -彻底检查了字符集配置,现在所有相关项均能位于属性文件中。
  
    -如果在用于 Windows-31J 的服务器上可用,驱动程序能正确使用 CP932,以及 CP932 和 MS932 java 编码名称,否则将求助于仅为近似的 SJIS。目前,仅在 MySQL-5.0.3 和更高版本上 (以及 MySQL-4.1.12/13,取决于何时反向移植字符集),才能可靠地支持任何 CP932 变体。
 
    -更正了BUG#9064,com.mysql.jdbc.PreparedStatement.ParseInfo 对 toCharArray() 的不必要调用。
 
    -更正了Bug#10144,如果 serverPrepare() 失败,ServerPreparedStatement 中的内存泄漏。
 
    -将清单文件实际写入正确位置,以便其终止于二进制 jar 文件。
 
    -增加了“createDatabaseIfNotExist”属性 (默认为“假”),该属性会使驱动程序请求服务器创建在 URL 中指定的数据库 (如果该数据库不存在的话)。必须拥有恰当的数据库创建权限才能执行该任务。
 
    -更正了BUG#10156,对于 ResultSet.getInt(),无符号 SMALLINT 被当作带符号类型,更正了所有的 UNSIGNED 整数和服务器端预处理语句,以及用于 UNSIGNED TINYINT 的 ResultSet.getObject()。
 
    -更正了BUG#10155,解析客户端预处理语句时不能识别双引号。
  
    -使得 enableStreamingResults() 在 com.mysql.jdbc.jdbc2.optional.StatementWrapper 上可见。
  
    -使得 ServerPreparedStatement.asSql() 能正确工作,自动解释功能可以与服务器端预处理语句一起工作。
  
    -使得兼容 JDBC2 的软件包成为公共包,以便允许访问厂家扩展。
  
    -整理了剖析工具事件的记录功能,移动了代码以将剖析工具事件转储为 com.mysql.jdbc.log.LogUtils 的字符串,以便第三方能够使用它。
  
    - DatabaseMetaData.supportsMultipleOpenResults() 现在返回“真”。DBMD 刚刚丢失某一内容时,驱动程序在一段时间内支持它。
  
    -更正了BUG#10310,驱动程序不支持用来调用存储程序的{?=CALL(...)}。其中包括,为 DatabaseMetaData.getProcedures() 和 getProcedureColumns() 增加了函数检索支持。
 
    -更正了BUG#10485,用 ResultSet.getString() 检索 YEAR(2) 时抛出 SQLException。现在,驱动程序总是将 YEAR 类型当作 java.sql.Dates 对待,并为 getString() 返回正确值。
另外,可以将“yearIsDateType”连接属性设置为“假”,并将值作为 SHORT 进行处理。
  
    -当“tinyInt1isBit=true”时 (默认),使用新的配置属性“transformedBitIsBoolean”(默认为“假”),对于 TINYINT(1) 列,返回的数据类型可在 Types.BOOLEAN 和 Types.BIT 之间切换。如果设为“假”(默认),对于 TINYINT(1) 列,DatabaseMetaData.getColumns() 和 ResultSetMetaData.getColumnType() 将返回 Types.BOOLEAN。如果为“真”,将返回 Types.BOOLEAN。无论该配置属性是如何设置的,如果允许了“tinyInt1isBit”,具有 TINYINT(1) 类型的列将作为 ResultSet.getObject(..) 的 java.lang.Boolean 实例返回,而且 ResultSetMetaData.getColumnClassName() 将返回“java.lang.Boolean”。
 
    -更正了BUG#10496,与 cp932 或 eucjpms 一起使用“characterSetResults”属性时将抛出 SQLException。
 
    -重组了目录格局,源码现位于“src”文件夹下,创建时不填充父目录,输出位于“./build”下,分发版位于“./dist”下。
 
    -这类支持/缺陷跟踪特性,将“autoGenerateTestcaseScript”设置为“真”时,该特性能够为 STDERR 生成。sql 测试脚本。
 
    -更正了BUG#10850,使用服务器端预处理语句时,不会将“0 长度”流发送给服务器。
    
    -现在,如果设置了“cachePrepStmts=true”,也会使连接进行高速缓冲操作,检查驱动程序的执行情况,以判断预处理语句是否能够在服务器端工作,并能在连接的生命期内对服务器端预处理语句进行高速缓冲处理。与以往一样,参数“prepStmtCacheSize”负责控制这些高速缓冲区的大小。
 
    -进行了尝试,以更为优美的方式处理 OutOfMemoryErrors。尽管所能作的事情不是很多,但在大多数情况下它们能关闭所遇到的连接,这样,进一步的操作不会进入状态不明的连接。出现 OOM 时,连接上的任何进一步操作均将失败,同时抛出“连接已关闭”异常,还将列出作为隐式连接关闭事件原因的 OOM 异常。
 
    -如果未要求,执行服务器端预处理语句时不发送 COM_RESET_STMT。
 
    -驱动程序将检测是否正在运行 MySQL-5.0.7 或更高版本,而且不扫描正在处理的语句中的“LIMIT ?[,?]”,这是因为目前服务器支持这类查询。
 
    -更正了BUG#11115,使用服务器端预处理语句和 ResultSet.getBytes() 时,VARBINARY 数据发生崩溃
 
    -Connection.setCatalog() 想在能够识别“useLocalSessionState”配置属性,将该属性设为“真”时,如果所请求的 catalog 与当前 catalog 相同,会阻止驱动程序将“USE ...”发送给服务器。
 
    -增加了下述配置捆包,通过“useConfigs”配置属性使用 1 个或多个:
    
  * maxPerformance:考虑后果时的最大性能
  * solarisMaxPerformance:Solaris 的需性能,在可能的情况下避免系统调用。
  * 3-0-Compat:与 Connector/J 3.0.x 功能兼容。
  
    -增加了“"maintainTimeStats”配置属性 (默认为“真”),用于通知驱动程序是否应跟踪上次查询时间,以及上次成功将信息包发送到服务器的时间。如果将其设置为“假”,将删除每查询的两次系统调用。
    
    -更正了BUG#11259,autoReconnect 的 ping 操作会导致连接启动时的异常。
 
    -更正了BUG#11360,Connector/J 将查询两次转储到 SQLException。
    
    -更正了 PreparedStatement.setClob(),不接受 Null 作为参数。
    
    -更正了BUG#11411,生产包不包括JBoss集成类。
 
 
    -删除了使用“usage advisor”时无意义的“开销昂贵的类型转换”告警。
 
 
04-14-05:版本3.1.8-stable
 
    -更正了 DatabaseMetaData.getTables(),未要求时,以请求表的类型之一返回视图。
 
    -在 5.0.3 和更高版本的 MySQL 中,增加了对新精度数学 DECIMAL 类型的支持。
 
    -更正了 ResultSet.getTime(),作用于服务器端预处理语句的 Null 值上时抛出 NPE。   -使 Connection.ping() 成为 public 方法。   -更正了Bug#8868,DATE_FORMAT() 查询从 getObject() 返回 BLOB。   - ServerPreparedStatements 现在能正确地将 BLOB/CLOB 数据以“流方式”发送至服务器。你可以使用属性“blobSendChunkSize”配置程序块大小的阈值 (默认值为 1MB)。
 
    -生成预处理语句时,BlobFromLocator 现在能使用正确的 ID 引用。
 
    -使用连接属性“sessionVariables”的逗号分隔列表方式传递它们,能够在连接时预先设置服务器端会话变量。
 
    -为使用“autoReconnect=true”的用户更正了 ping() 中的回归问题。
 
    -更正了BUG#9040,PreparedStatement.addBatch() 不能与服务器端预处理语句和流式 BINARY 数据一起工作。
 
    -更正了BUG#8800,对于运行于区分大小写的文件系统上的服务器,DBMD.supportsMixedCase*Identifiers() 返回错误值。
 
    -更正了BUG#9206,对于 characterSetResults 配置属性,不能使用“UTF-8”。
 
    -更正了BUG#9236,连续BUG#8868,在查询中使用了多个函数,查询本应返回非字符串类型,但当临时表解析它们时,返回类型突然变为难以理解的二进制字符串 (针对服务器限制采取了相应的避规措施)。此外,还更正了类型为 CHAR(n) CHARACTER SET BINARY 的字段,使其能够为 RSMD.getColumnClassName() 和 ResultSet.getObject() 返回正确/匹配的类。
 
    -更正了BUG#8792,对于“仅正向/只读”结果集 (我们支持该方式),DBMD.supportsResultSetConcurrency() 未返回“真”。
 
    -更正了BUG#8803,访问时,DBMD.getBestRowIdentifier() 的“DATA_TYPE”列导致 ArrayIndexOutOfBoundsException(事实上,未返回任何值)。
 
    -检查了将 char/varchar 列数据转换为数值时的空字符串 (''),如果配置属性“emptyStringsConvertToZero”被设为“假”,抛出异常 (为了与 3.0 版的向后兼容,默认情况下,将其设为“真”,但在 3.2 版中,最可能的默认设置为“假”)。
 
    -更正了BUG#9320,在特定条件下,当未使用服务器端预处理语句时,PreparedStatement.getMetaData() 在数据库中插入了空白行。
 
    -Connection.canHandleAsPreparedStatement() 现在将尽“最大努力”来识别带有占位符的 LIMIT 子句,目的在于,对于服务器目前不能将其当作服务器端预处理语句予以处理的语句,为其生成处理措施时,获得较少的错误肯定结果。
 
    -更正了 build.xml,如果 log4j 不可用,不编译 log4j 日志功能。
 
    -增加了对 c3p0 连接池的 (http://c3p0.sf.net/) 验证/连接检验器接口的支持,如果服务器可用,该检验器接口将使用轻型“COM_PING”调用。要想使用它,请配置 c3p0 连接持的“connectionTesterClassName”属性,以使用“com.mysql.jdbc.integration.c3p0.MysqlConnectionTester”。
 
    -更好的检测引用字符串的内外 LIMIT,以便驱动程序能更加正确地判断是否可以在服务器上处理预处理语句。
 
    -更正了BUG#9319,当驱动程序试图确定参数计数/类型时,分不清不同数据库中具有相同名称的存储程序。
 
    -为 ResultSet 和 Statement 实施增加了最终确定器,以便与 JDBC 规范兼容,该规范要求,如果它们未明确关闭,在无用单元收集阶段应关闭这些资源。
 
    -更正了BUG#9682,对于具有 DECIMAL 参数和存储要求的存储程序,如果包含“,”,将失败。
 
    - PreparedStatement.setObject(int, Object, int type, int scale) 现在能使用针对 BigDecimal 实例的标度值。
 
    -更正了BUG#9704,当已有结果集是。close()d 时,Statement.getMoreResults() 可能抛出 NPE。
 
    -性能度量特性现能收集关于 SELECT 中引用的表数量的信息。
 
    -现在能够自动配置日志系统。如果用户通过 URL 属性“logger”或系统属性“com.mysql.jdbc.logger”设置了值,那么将使用用户的设置,否则将采用下述步骤自动检测设置:
 
   如果 Log4j 可用,将使用它,接下来是 JDK1.4 日志功能,再接下来是 STDERR 日志功能。
 
    -更正了BUG#9778,即使数据库版本不支持视图,如果请求了视图,DBMD.getTables() 不应返回表。
 
    -更正了驱动程序,当在服务器端预处理语句返回的结果集上调用了 ResultSet.getBoolean() 时,对于“-1”不返回“真”。
 
    -为。jar 文件增加了 Manifest.MF 文件以及实施信息。
 
    -在 Field.isOpaqueBinary() 中提供了更多测试,以识别晦涩的二进制字段 (即具有 CHAR(n) 和 CHARACTER SET BINARY 类型的字段),这类字段来自各种标量函数和聚合函数 (返回字符串) 的输出。
 
    -更正了BUG#9917,出于传统方面的考虑,即使它与 JDBC 不兼容,也应接受 DBMD 方法中用于 catalog(使用当前值) 的 Null。将连接属性“nullCatalogMeansCurrent”设置为“假”可禁止它 (在 C/J 3.2.x 中,它是默认设置)。
 
    -更正了BUG#9769,出于传统方面的考虑,即使它与 JDBC 不兼容,也应接受 DBMD 中用于名称 (“%”) 的 Null。将连接属性“nullNamePatternMatchesAll”设置为“假”可禁止它 (在 C/J 3.2.x 中,它是默认设置)。
 
02-18-05:版本3.1.7-stable
 
    -更正了BUG#7686,Timestamp 关键字列数据需要分离的“_binary”,用于 UpdatableResultSet.refreshRow()。
 
    -更正了BUG#7715,对于服务器端预处理语句和可更新结果集,Timestamps 错误地转换为字符串。
 
    -检测字符串表单 (以前为整数) 中的 sql_mode 变量,并恰当调整字符串的引用方法。
 
    -增加了“holdResultsOpenOverStatementClose”属性 (默认为“假”),它能将 statement.close() 的结果集保持打开状态,或执行相同语句 (由 Kevin Burton 推荐)。
 
    -更正了BUG#7952,在故障切换配置下回退至主连接时的无限递归。
 
    -如果允许了高速缓冲,将禁止 4.1.10 版之前 MySQL-4.1 版本的多语句功能 (如果以允许的话),这是因为在该配置下,服务器会返回错误的结果。
 
    -更正了 configureClientCharset() 中的重复代码,该类代码将阻止 useOldUTF8Behavior=true 的恰当运行。
 
    -删除了“dontUnpackBinaryResults”功能,现在,驱动程序将按原样保存来自服务器端预处理语句的结果 (与服务器提供的相同,并在需要时展开)。
 
    -更正了BUG#8096,使用服务器端预处理语句时,模拟定位器破坏了二进制数据。
 
    -更正了 ServerPreparedStatement.serverPrepare() 的同步事宜,如果在多个线程间共享连接,可能会导致死锁/崩溃。
 
    -默认情况下,驱动程序能通过各种Connection.prepareStatement() 的各种变体扫描 SQL,以判断它是否是能够在服务器端支持的语句类型,如果不被服务器端支持,会将其作为客户端模拟预处理语句进行处理 (BUG#4718))。也可以通过在 JDBC URL 中传递“emulateUnsupportedPstmts=false”禁止该特性。
 
    -从 CallableStatement 中删除了用作输入/输出参数的“_binary”引介词。
 
    -对于注册为*BINARY 的输出参数,总返回 byte[]。
 
    -对于 PreparedStatement.setObject(n, "true", Types.BIT),将布尔“True”的正确值发送给服务器。
 
    -更正了与连接有关的缺陷,当语句不是服务器端预处理语句时,无法对来自 prepareStatement() 的语句进行高速缓冲处理。
 
    -使用 ResultSet.get(..., cal) 和 PreparedStatement.set(...., cal) 时,如果客户端和服务器均位于 GMT(格林威治标准时间) 时区,选择进行时间调整的正确方向。
 
    -增加了“dontTrackOpenResources”选项 (默认为“假”以便兼容 JDBC),对于具有不良特性的应用程序 (例如应关闭语句时,却未关闭语句的应用程序),它有助于改善内存的使用。
 
    -更正了BUG#8428,ResultSet.getString() 不能保持存储在服务器上的格式,仅当将“noDatetimeStringSync”属性设置为“真”(默认为“假”) 时,才能允许缺陷更正。
 
    -更正了使用“usage advisor”而且结果集已关闭时 ResultSet.realClose() 中的 NPE。
 
    -更正了BUG#8487,不创建流式结果集的 PreparedStatements。
 
    -不将 NULL 传给给 ResultSet.getNativeConvertToString() 中的 String.valueOf(),原因在于 String.valueOf() 会对其进行字符串处理 (即返回“null”),对于所述方法,这是错误的。
 
    -更正了BUG#8484,当需要舍入操作以设定标度时,ResultSet.getBigDecimal() 抛出异常。如果非舍入性 BigDecimal.setScale() 失败,驱动程序现在将选择“半向上”舍入模式。
 
    -增加了“useLocalSessionState”配置属性,将其设置为“真”时,JDBC 驱动程序将认为应用程序行为良好,并会使用 java.sql.Connection 提供的方法仅设置 autocommit 和事务隔离级别,因此,能够在大多数情况下处理这些值,而不引发数据库服务器循环。
 
    -为连接池实施实例的语句增加了 enableStreamingResults(),可检查 Statement.setFetchSize() 是否存在兼容规范的值。调用“Statement.setFetchSize(>=0)”可禁止关于该语句的流式结果。
 
    -增加了对 MySQL-5.0.3 中 BIT 类型的支持。驱动程序会将 BIT(1-8) 当作 JDBC 的 BIT 类型对待 (映射至 java.lang.Boolean),这是因为当声明了“< 9 bits”) 时,服务器目前不会发送能确定比特字段 (bitfield) 大小的足够信息。BIT(>9) 将被当作 VARBINARY 对待,并当调用 getObject() 时返回 byte[]。
 
12-23-04:版本3.1.6-stable
 
    -更正了 SocketInputStream.read() 的挂起问题,当驱动程序必须直接截取结果集,而不是跟踪结果集末尾的“LIMIT n”时,与 Statement.setMaxRows() 和多个结果集一起使用时 SocketInputStream.read() 挂起。
 
    -更正了BUG#7026,DBMD.getProcedures() 不考虑 catalog 参数。
 
12-02-04:版本3.1.5-gamma
 
    -更正了字符串常数和动态字符串之间的比较事宜,或是 toUpperCase()d 或是 toLowerCase()d,以使用 Locale.ENGLISH,将其用作英语的覆盖规则。此外,还使用 StringUtils.indexOfIgnoreCase() 替代了。toUpperCase().indexOf(),以避免创建很短的过渡性字符串实例。
 
    -更正了BUG#5235,服务器端预处理语句不考虑“zeroDateTimeBehavior”属性,而且当使用 ResultSet.getObject() 时会导致类抛弃异常,这是因为总返回全 0 字符串。
 
    -更正了批更新和服务器预处理语句有关的问题,与以前的集合相比,如果在给定的批参数集合中发生了类型变更,服务器预处理语句不会检测这类变化,从而导致服务器返回错误“Wrong arguments to mysql_stmt_execute()”。
 
    -解决了当时间戳的字符串表示包含后缀“.”但其后没有数字时的情况。
 
    -更正了BUG#5706,对 ResultSet.getNativeString() 中以前存在字符串实例的低效检测。
 
    -不抛出针对 Connection.releaseSavepoint() 的异常。
 
    -解码来自 ServerPreparedStatements 的日期时,默认情况下使用按会话进行的日历实例 (通过设置“dynamicCalendars=true”,设置为早期的性能较低的方式)。
 
    -增加了实验性配置属性“dontUnpackBinaryResults”,它延迟了解包二进制结果集取值的功能,直至请求了它们为止 (默认情况下设为“假”)。对于某些 usecase/jvm 组合,它对无用信息收集器更友好。
 
    -更正了BUG#5729,对来自服务器端预处理语句结果集的 UNSIGNED BIGINT,未能正确解包。
 
    -更正了BUG#6225,ServerSidePreparedStatement,分配了不必要的具有短生存时间的对象。
 
    -删除了 ResultSet 构造函数中有害的新 Throwable(),原因在于不良合并 (导致任何所创建结果集永远不会使用的新对象),分析BUG#6359时发现。
 
    -更正了在 EscapeProcessor.escapeSQL() 中过早创建 StringBuffer 的问题,而且在不需要转义功能时仍返回字符串 (防止不必要的对象分配)。分析BUG#6359时发现。
 
    -为可更新结果集中的键比较使用“null-safe-equals”。
 
    -更正了BUG#6537,如果需要 0 填充,作用在 Decimal 上的 SUM() 以及服务器端预处理语句均将忽略标度 (由于服务器将其转换为 DOUBLE,0 填充将结束,将其转换为 BigDecimal 类型的字符串进行解析时,丢失所有的填充“0”)。
 
    -创建 DBMD 查询时使用 DatabaseMetaData.getIdentifierQuoteString()。
 
    -如果在服务器上 LOAD DATA LOCAL INFILE 小于“max_allowed_packet”,使用 1MB 的信息包发送文件。
 
    -更正了BUG#6399,对于多字节字符集,ResultSetMetaData.getColumnDisplaySize() 返回错误值。
 
    -通过“autoDeserialize”属性 (默认为“假”),能够对保存在 BLOB 中的 java.lang.Objects 的自动串并转换功能进行配置。
 
    -修改了 Field.isOpaqueBinary() 以检测“CHAR(n) CHARACTER SET BINARY”,从而能够支持用于 ResultSet.getObject() 的固定长度二进制字段。
 
    -使用我们自己的缓冲输入流实施方式来处理 java.io.BufferedInputStream 的封闭行为。使用“useReadAheadInput=false”可禁止它。
 
    -更正了BUG#6348,当给定主机名的某一地址是 IPV6 时无法连接到服务器 (服务器尚未与 IPV6 捆绑) 驱动程序现在能够查找给定主机的所有 IP 地址,并停在接受 socket.connect() 的第 1 个地址上。
 
09-04-04:版本3.1.4-beta
 
    -更正了BUG#4510,Connector/j 3.1.3 beta 不能正确处理整数 (由为了支持 Buffer.readInt() -> Buffer.readShort() 中的无符号读取操作所作的更改而导致)。
 
    -在 DatabaseMetaData.getTables() 和 getTableTypes() 中增加了对 VIEW 的支持,该类特性现已在 MySQL 服务器 5.0.x 版中提供。
 
    -更正了BUG#4642,解包字段元数据时,ServerPreparedStatement.execute*() 有时会抛出 ArrayIndexOutOfBoundsException。
 
    -优化了整数解析功能,通过“useFastIntParsing=false”属性,允许使用 JDK 类较慢的解析功能。
 
    -增加了“useOnlyServerErrorMessages”属性,它会使服务器生成的异常中的消息文本仅包含由服务器发送的文本 (与 SQLState“标准”介绍中给出的相反,此时文本后面还包括服务器的错误消息)。默认情况下,该属性被设置为“真”。
 
    -更正了BUG#4689,如果前面的 Null 已被返回,对于原语,ResultSet.wasNull() 不工作。
 
    -如果“enablePacketDebug=true”,跟踪信息包的序列号,如果收到的信息包次序混乱,抛出异常。
 
    -更正了BUG#4482,使用预处理语句时,对于字符串,ResultSet.getObject() 返回错误类型。
 
    -两次调用 MysqlPooledConnection.close()(虽然也是应用程序错误) 会导致 NPE。已更正。
 
    -更正了BUG#5012,处理 DECIMAL 类型的返回值的 ServerPreparedStatements 不工作。
 
    -更正了BUG#5032,对于来自 4.1.x 版预处理语句的伪位类型,ResultSet.getObject() 不返回布尔类型 (在针对伪位类型的 getObject() 中使用二进制编码的结果集模糊测试时,它提供了避免额外类型转换的快捷方式)。
 
    -现在能够在“LOAD DATA LOCAL INFILE”语句中使用 URL,而且驱动程序将使用 Java 的内置处理程序来检索数据,并将其发送到服务器。默认情况下不允许该特性,要想使用它,必须将“allowUrlInLocalInfile”连接属性设置为“真”。
 
    -对于在 ResultSet.get*() 的数值上执行的截取操作,驱动程序将更加严格,而且当检测到截取操作时将抛出 SQLException。将“jdbcCompliantTruncation”设置为“假”,可以禁止该功能 (在默认情况下允许该功能,这是因为该功能是兼容 JDBC 所需的)。
 
    -从结果集读取“全零”日期时间值时,增加了三种处理它们的方法,“exception”,(默认值),用代码为“S1009”的 SQLState 抛出 SQLException;“convertToNull”,返回 NULL 而不是数据;以及“round”,对日期进行舍入处理,使之成为最接近的值,即“0001-01-01”。
 
    -更正了 ServerPreparedStatement,使之能够“以脱线”方式读取预处理语句元数据,尽管在目前它是取代在任何时侯均不工作的 MysqlIO.clearInputStream() 的占位符,之所以如此,是因为目前尚未从服务器读取数据。通过抛出 ArrayIndexOutOfBoundExceptions 的 erverPreparedStatements,它修正了用户遇到的偶发性错误。
 
    -加载资源捆包时使用 com.mysql.jdbc.Message 的类加载器,应能更正调用器的类加载器不能确定资源捆包位置时出现的偶发性错误。
 
07-07-04:版本3.1.3-beta
 
    -对 CallableStatements 的输出参数名进行 Mangle 处理,使得在与用户变量名一起使用时,这类名称不会崩溃。
 
    -增加了对 CallableStatements 中 INPUT 参数的支持。
 
    -更正了BUG#4119,为服务器端预处理语句发送的 null 比特掩码不正确。
 
    -默认情况下使用 SQL 的标准 SQL 状态,除非将“useSqlStateCodes”属性设置为“假”。
 
    -增加了信息包调试代码 (请参见“enablePacketDebug”属性文档)。
 
    -为 MySQL 错误编号增加了常量 (可公共访问,请参见 com.mysql.jdbc.MysqlErrorNumbers),并增加了生成映射的能力,能够将厂家代码映射为驱动程序使用的 SQLStates(出于文档编制目的)。
 
    -使更多消息更为具体 (正在努力)。
 
    -更正了BUG#4311,在检索具有预处理语句和二进制协议特性的 mediumint 列时发生错误。
 
    -当“useTimezone=true”时,在 MySQL-4.1.3 中支持新的时区变量。
 
    -支持无符号数值作为预处理语句返回的类型。对于“bigint unsigned”类型,这也会导致 ResultSet.getObject() 中的内容发生变化,“bigint unsigned”类型用于返回 BigDecimal 实例,现在它将返回 java.lang.BigInteger 实例。
 
06-09-04:版本3.1.2-alpha
 
    更正了为参数 (如 char(), varchar()) 指定大小时存储程序参数的解析信息。
 
    -通过“cacheCallableStmts”属性,允许对可调用语句进行高速缓冲处理。
 
    -更正了下述问题:未为存储程序指定输出参数时,发出虚假查询来检索输出参数,从而导致服务器语法错误。
 
    -更正了在 CallableStatement.setOutputParameters() 中没有任何参数会导致 NullPointerException 的问题。
 
    -删除了 MysqlIO.changeUser() 中的异常捆包。
 
    -更正了关于发送大型查询分离信息包方面的问题,也允许发送大信息包的 nio 功能。
 
    -为 ServerPreparedStatement 增加了。toString() 功能,如果你正在调试作为预处理语句 (显示为服务器应处理的 SQL) 的查询,它应有所帮助。
 
    -增加了“gatherPerformanceMetrics”属性,以及用于控制在何时/何处记录这类信息的多种属性 (更多信息请参见相关文档)。
 
    -调用。close() 时,ServerPreparedStatements 实际上不能取消对服务器端资源的分配。
 
    -增加了“logSlowQueries”属性,以及“slowQueriesThresholdMillis”属性,以控制应在何时将查询视为“缓慢”。
 
    -相对于 registerOutParameter() 中隐含的顺序,正确地将输出参数映射到 prepareCall() 中给定的位置,;更正了BUG#3146
 
    -对于版本等于高于 4.1.0 的服务器,能正确地检测字符集。
 
    -整理了服务器属性的检测功能。
 
    -对于版本等于高于 4.1.2 的服务器,支持用于参数元数据的占位符。
 
    -更正了BUG#3539,getProcedures() 未返回结果集中的任何进程。
 
    -更正了BUG#3540,getProcedureColumns() 不能与程序名的通配符一起使用。
 
    -更正了BUG#3520,DBMD.getSQLStateType() 返回不正确的值。
 
    -增加了“connectionCollation”属性,如果给定字符集的默认校对不恰当,驱动程序将在连接初始过程中发出“set collation_connection=...”查询。
 
    -更正了在 MySQL-5.0.0 上运行时的 DatabaseMetaData.getProcedures() 问题 (在 5.0.1 和 5.0.0 间,“show procedure status”的输出有所不同)。
 
    -更正了BUG#3804,getWarnings() 返回 SQLWarning 而不是 DataTruncation。
 
    -对于版本为 5.0.0 或 5.0.1 的服务器,不要启用服务器端预处理语句,这是因为,它们与驱动程序使用的“4.1.2+”风格不兼容 (驱动程序预计返回的信息并不存在,因而挂起)。
 
02-14-04:版本3.1.1-alpha
 
    -更正了与不使用客户端预处理语句的 UpdatableResultSets 有关的缺陷。
 
    -当 MySQL 不提供字符集并将 JVM 设置为多字节编码时,更正了将字节转换为 ASCII 时的字符编码事宜 (通常会影响数值检索)。
 
    -将服务器预处理语句的“未知”数据类型解包为字符串。
 
    -为服务器预处理语句实现了长数据类型 (Blob、Clob、InputStreams、Readers)。
 
    -为 MySQL-4.1 和更高版本实现了 Statement.getWarnings()(使用“SHOW WARNINGS”)。
 
    -默认结果集类型更改为 TYPE_FORWARD_ONLY(兼容 JDBC)。
 
    - 结果集类型和并发性的集中设置。
 
    -再次确定了连接属性的设置方式和显示为 DriverPropertyInfo 的方式,以及 Connection 和 DataSource 属性。
 
    -支持 NIO。在支持 NIO 的平台上使用“useNIO=true”。
 
    -支持 SAVEPOINTs(MySQL >= 4.0.14 或 4.1.1)。
 
    -支持“mysql_change_user()...”,请参见“com.mysql.jdbc.Connection”中的 changeUser() 方法。
 
    -减少了平均查询中调用的方法数目,使之更有效率。
 
    -自动再连接时重新处理预处理语句。任何遇到的错误均被延迟,直至首次尝试再执行经过重新处理的语句为止。
 
    -按照 JDBC 规范,确保在预处理语句上执行查询前给出的警告是明确的 (目前,我们支持警告功能)。
 
    -在 ConnectionProperties 中,支持“旧的”profileSql 大写特性。该属性已受到冷落,应尽量使用“profileSQL”。
 
    -优化了 Buffer.readLenByteArray(),以便当长度为 0 时返回共享的空字节数组。
 
    -在对。execute*() 的多次调用之间,允许保留 PreparedStatement.setBlob() 的内容。
 
    -处理了 EscapeProcessor 中的 0 长度令牌 (由可调用语句转义语法导致)。
 
    -在 UpdatableResultSet 中的删除/更新/插入行操作上,检查关闭的连接。
 
    -更正了检查 UpdatableResultSet 中的所有主键时对表别名的支持事宜。
 
    -删除了 useFastDates 连接属性。
 
    -对来自 JNDI Refs 的数据源属性进行了正确的初始化,包括明确指定的 URL。
 
    -对于版本为 5.0.0 或更高的 MySQL,DatabaseMetaData 现在能通报 supportsStoredProcedures()。
 
    -更正了 Connection.prepareCall() 中的堆栈溢出问题 (不良合并)。
 
    -对低于 1.4 版的 JDK,更正了对 DateTimeValue 中 Calendar.getTimeInMillis() 的 IllegalAccessError(非法访问错误)。
 
    -更正了BUG#1673,对于非“%”列名,DatabaseMetaData.getColumns() 未返回正确的列顺序信息。
 
    -合并了数据类型映射的更正事项,从 MySQL 类型“FLOAT”到 java.sql.Types.REAL(自 3.0 版起) 的数据类型映射。
 
    -检测用于 RSMD.isCaseSensitive() 的列校对。
 
    -更正了与发送大于 16M 查询有关的问题。
 
    -为 CallableStatement 增加了命名和索引式输入/输出参数支持。
MySQL-5.0.x 或更高版本。
 
    -更正了 ServerPreparedStatement.setTimestamp() 中的 NullPointerException,以及 ServerPreparedStatement.setTimestamp()、setDate() 中的年月差异。
 
    -为 build.xml 中的一致性和递归/单元测试增加了拥有多个数据库/JVM 目标的能力。
 
    -更正了访问 ServerPreparedStatements 和其结果集中某些日期时间功能时的 NPE 和不良年月转换问题。
 
    -显示关闭连接的位置和原因 (用于帮助调试)。
 
    -实现了 CommunicationsException,它能尝试判断与服务器失去通信的原因,并能在调用。getMessage() 时显示可能的原因。
 
    -更正了BUG#2359,二进制编码结果集中数值类型的 NULL 值会导致 NullPointerExceptions。
 
    -实现了 Connection.prepareCall(),DatabaseMetaData.getProcedures(),以及 getProcedureColumns()。
 
    -调用 clearParameters() 时,通过发送 COM_RESET_STMT 至服务器,复位了 ServerPreparedStatement 中的“long binary”参数。
 
    -自 3.0 版起,合并了预处理语句高速缓冲和。getMetaData() 支持。
 
    -解包来自服务器端预处理语句的结果时,在某些情况下,对于 TimeUtil.fastDate/TimeCreate() 的年份,会出现 off-by-1900 错误,更正了该错误。
 
    -更正了BUG#2502,getTables() 中的字符集转换事宜。
 
    -实现了由语句或存储程序返回的多个结果集。
 
    -更正了BUG#2606,服务器端预处理语句未正确返回数据类型“YEAR”。
 
    -允许对来自服务器端预处理语句的结果集进行流处理。
 
    -更正了BUG#2623,使用滚动结果集和服务器端预处理语句时出现类舍弃异常。
 
    -自 3.0 版起,合并了无缓冲输入代码。
 
    -更正了不能通过存取器恰当显示的 ConnectionProperties,并整理了 ConnectionProperties 代码。
 
    -更正了BUG#2671,在服务器端预处理语句中,在任何情况下均不能正确编码 NULL 字段。
 
    -更正了将数字写入缓冲以发送预处理语句执行请求时出现的罕见缓冲区下溢问题。
 
    -对于交付的驱动程序,使用了文档的 DocBook 版。
 
02-18-03:版本3.1.0-alpha
 
    -增加了“requireSSL”属性。
 
    -增加了“useServerPrepStmts”属性 (默认为“假”)。当服务器版本支持并将该属性设置为“真”时 (4.1 和更高版本),驱动程序将使用服务器端预处理语句。目前其默认设置为“假”,除非所有的捆绑/获取功能均已实施。目前,仅为 4.1 版的服务器端预处理语句实现了 DML 预处理语句。
 
    -跟踪打开的语句,并在调用 Connection.close() 时关闭所有打开的语句 (JDBC 兼容)。
 
06-23-05:版本3.0.17-ga
 
    -更正了BUG#5874,当 useTimeZone='true';而且服务器时区不同于客户端时区时,Timestamp/Time 转换出现方向错误。
 
    -更正了BUG#7081,DatabaseMetaData.getIndexInfo() 忽略“唯一”参数。
 
    -支持新的协议类型“MYSQL_TYPE_VARCHAR”。
 
    -增加了“useOldUTF8Behavoior”配置属性,连接到 MySQL-4.1 或更高版本且字符编码为“utf-8”时,该属性能使 JDBC 驱动程序的行为方式类似于在 MySQL-4.0.x 和更早版本下的行为方式。
 
    -更正了BUG#7316,调用 getConnection() 时,从连接池创建的语句返回实际连接而不是逻辑连接。
 
    -更正了BUG#7033,在静态 SQL 字符串中,PreparedStatements 不能正确编码 Big5(以及其他多字节) 字符集。
 
    -更正了BUG#6966,启动了故障切换的连接 (由于主连接失败) 从不再次尝试主连接。
 
    -更正了BUG#7061,PreparedStatement.fixDecimalExponent() 增加额外“+”,使得 MySQL 服务器无法解析数值。
 
    -更正了BUG#7686,Timestamp 关键字列数据需要分离的“_binary”,用于 UpdatableResultSet.refreshRow()。
 
    -反向移植了来自 Connector/J 3.1 的 SQLState 代码映射,使用连接属性“useSqlStateCodes=true”可启用它,在本版本中默认为“假”,以免破坏传统应用程序 (对于 Connector/J 3.1,默认为“真”)。
 
    -更正了BUG#7061,PreparedStatement.fixDecimalExponent() 增加额外“+”,使得 MySQL 服务器无法解析数值。
 
    -转义序列{fn convert(..., type)}现在支持由 SQL 预先设定的 ODBC 类型。
 
    -更正了 configureClientCharset() 中的重复代码,该类代码将阻止 useOldUTF8Behavior=true 的恰当运行。
 
    -通过更正行数计数器的环绕式处理程序,能正确处理大于 20 亿行的流式结果集。
 
    -更正了BUG#7607,MS932、SHIFT_JIS 和 Windows_31J 不接受针对 sjis 的别名。
 
    -更正了BUG#6549(更正#7607 的同时),为 sjis 增加了 CP943 别名。
 
    -更正了BUG#8064,与预处理语句一起使用多字节字符集时,要求对二进制数据进行十六进制转义处理。
 
    -更正了BUG#8812,DBMD.getIndexInfo() 的 NON_UNIQUE 列返回倒置值。
 
    -解决了服务器BUG#9098,无法将 DATE/TIME/TIMESTAMP/TIMESTAMP 列 CURRENT_*的默认值与“字符串”值区别开,因此,插入默认值时,UpdatableResultSet.moveToInsertRow() 会生成不良的 SQL。
 
    -更正了BUG#8629,将“EUCKR”作为“SET NAMES euc_kr”发送,MySQL-4.1 以及更高版本不能理解该特性。
 
    -根据服务器的版本,DatabaseMetaData.supportsSelectForUpdate() 返回正确值。
 
    -对于含别名 Windows-31J、CP934、MS932 的双字节字符集,对于 PreparedStatement.setBytes(),采用十六进制转义特性。
 
    -增加了对“EUC_JP_Solaris”字符编码的支持,映射到“eucjpms”的 MySQL 编码 (从 3.1 版开始的反向移植)。它只能在支持 eucjpms 的服务器山工作,也就是说 5.0.3 或更高版本。
 
11-15-04:版本3.0.16-ga
 
    -连接至 MySQL-4.1 或更高版本且再次使用连接池和/或 Connection.changeUser() 时,将再次发出字符集配置命令。
 
    -更正了 ResultSetMetaData.isReadOnly(),以便在连接至 MySQL-4.1 或更高版本时,能根据“原始的”表名和列名,检测不可写的列。
 
    -更正了BUG#5664,当 ResultSet.updateByte() 位于插入行上时抛出 ArrayOutOfBoundsException。
 
    -更正了 DatabaseMetaData.getTypes(),对于 NUMERIC 类型,它返回不正确的 (非负) 标度。
 
    -更正了BUG#6198,Buffer.readString(string) 中的“off-by-one”问题。
 
    -通过“tinyInt1isBit”属性,使得能够对 TINYINT(1) -> BIT/Boolean 转换进行配置 (为了与 JDBC 兼容,默认为“真”)。
 
    -如果服务器版本大于等于 4.1.1,在连接建立过程中仅设置“character_set_results”。
 
    -更正了回归问题,其中,useUnbufferedInput 默认为“假”。
 
    -更正了BUG#6231,ResultSet.getTimestamp() 作用在具有 TIME 的列上时失败。
 
09-04-04:版本3.0.15-production
 
    -更正了BUG#4010,对于 GBK,StringUtils.escapeEasternUnicodeByteStream 仍被破坏。
 
    -更正了BUG#4334,对于 autoReconnect 的故障切换,对任何主机均不使用端口“#”,而且不重试所有主机。(警告:需要更改 SocketFactory connect() 方法的特征,它目前是公共套接字连接 (String host,int portNumber,Properties props)。也能次,必须更改任何第三方套接字实施方式以支持该特征。
 
    -当它们已被关闭并被返回到连接池时,由 MysqlConnectionPoolDataSource 创建的逻辑连接将发出 rollback()。如果你的应用服务器/连接池已帮助你完成了该任务,可以将“rollbackOnPooledClose”属性设置为“假”以避免额外的 rollback() 开销。
 
    -删除了结果集中对 checkRowPos() 的多余调用。
 
    -更正了BUG#4742,在 DBMD.getTypeInfo() 中,“DOUBLE”映射了两次。
 
    -增加了 FLOSS 许可豁免。
 
    -更正了BUG#4808,在 PooledConnection 上调用两次。close() 将导致 NPE。
 
    -更正了BUG#4138BUG#4860,对于无符号列,DBMD.getColumns() 返回错误的 JDBC 类型。这也会影响对 RSMD.getColumnType() 和 RSMD.getColumnTypeNames() 方法中所有数值类型的类型映射,以确保 DBMD.getColumns() 的类似类型与 RSMD.getColumnType() 和 RSMD.getColumnTypeNames() 返回的类型匹配。
 
    -分发版命名方案中的“Production”-“GA”。
 
    -更正了BUG#4880,对于非数值类型,RSMD.getPrecision() 返回 0(对于非二进制类型,应返回字符的最大长度,对于二进制类型,应返回最大字节长度)。根据服务器发回的长度 (在网络协议层,服务器不区分 TINYBLOB、BLOB、MEDIUMBLOB 或 LONGBLOB),它还更正了针对 BLOB 类型的 RSMD.getColumnType() 和 RSMD.getColumnTypeName() 映射。
 
    -更正了BUG#5022,结果集应在“.close()”中释放 Field[] 实例。
 
    -更正了BUG#5069,如果结果集已关闭,ResultSet.getMetaData() 不应返回未正确初始化的元数据,而是应抛出 SQLException。此外,在对实例级别的字段 (.close() 过程中取消的字段) 进行操作之前,通过调用 checkClosed(),它还更正了 getRow()、getWarnings() 和遍历方法。
 
    -从 4.1.x 版服务器开始,能解析新的时区变量。
 
    -与 MySQL-4.1.x 或更高版本连接时,为 PreparedStatement.setBytes() 和 set*Stream() 使用“_binary”引介词,以防止在字符集转换过程中出现错误判断。
 
05-28-04:版本3.0.14-production
 
    -更正了 URL 解析错误。
 
05-27-04:版本3.0.13-production
 
    -更正了BUG#3848,无服务器名称时,不能使用 MySQLDatasource。
 
    -更正了BUG#3920,使用 MysqlConnectionPoolDataSource 时出现“No Database Selected”(未选择数据库)。
 
    -更正了BUG#3873,对于批插入,PreparedStatement.getGeneratedKeys() 方法仅返回 1 个结果。
 
05-18-04:版本3.0.12-production
 
    -为 TYPE_NAME 列中的 DatabaseMetaData.getColumns() 输出增加了无符号属性。
 
    -增加了“failOverReadOnly”属性,允许最终用户配置出现故障切换时的连接状态 (只读/可写)。
 
    -自 3.1 开始,反向移植了“change user”和“reset server state”功能,允许 MysqlConnectionPoolDataSource 的客户端复位连接池上 getConnection() 的服务器状态。
 
    -使用 MySQL-4.1 或更高版本时,不对 SJIS/GBK/BIG5 进行转义处理。
 
    -允许 MysqlDataSource 和 MysqlConnectionPool 数据源使用“url”参数,以便能够从内部应用服务器传递其他属性。
 
    -将复制键和外键错误映射到“23000”的 SQLState。
 
    -自 3.1 开始,反向移植了文档编制工具。
 
    -返回用于结果集的创建语句,该结果集由 getGeneratedKeys() 创建 (BUG#2957)。
 
    -允许作为参数将 java.util.Date 发送到 PreparedStatement.setObject(),将其转换为 Timestamp 类型以保持完整精度 (BUG#3103)。
 
    -使用 setBytes() 和/或 setBinary/CharacterStream() 时,不截取 BLOB/CLOB(BUG#2670)。
 
    -连接时,在使用“SHOW COLLATION”的 MySQL-4.1.0 和更高版本上,为字段级字符集动态配置字符集映射。
 
    -将“binary”字符集映射到“US-ASCII”,以支持 4.1.2 和更高版本服务器的 DATETIME 字符集识别功能。
 
    -在初始化过程中使用“SET character_set_results”,允许将结果集的任何字符集返回到驱动程序。
 
    -在>= 4.1.0 的 MySQL 上发出“SET NAMES”之前,在连接至编码查询的过程中,使用返回的 charsetnr。
 
    -为 ResultSetMetaData(getColumnCharacterEncoding() 和 getColumnCharacterSet()) 增加了 Helper(助手) 方法,允许最终用户查看驱动程序认为应在列上使用的字符集。
 
    -在>= 4.1.0 的 MySQL 上仅设置 character_set_results。
 
    -更正了BUG#3511,StringUtils.escapeSJISByteStream() 不能正确处理所有的东方双字节字符集。
 
    -将 StringUtils.escapeSJISByteStream() 重新命名为更贴切的 escapeEasternUnicodeByteStream()。
 
    -更正了BUG#3554,在 URL 中未指定数据库将导致 MalformedURL exception。
 
    -如果使用了 characterEncoding 属性,自动将 MySQL 编码名称转换为 Java 编码名称。
 
    -增加了在某些 JVM 上能识别的编码名称,以更正错误地将其逆向映射为 MySQL 编码名称的问题。
 
    -为所有单元测试使用 junit.textui.TestRunner(允许在 Ant 或 Eclipse 以外的命令行上运行它们)。
 
    -更正了BUG#3557,UpdatableResultSet 不能获取 moveToInsertRow() 的默认值。
 
    -更正了BUG#3570,不一致的列类型通报。服务器仍不能正确返回*BLOBs *TEXT 的所有类型,因此驱动程序也不能正确返回它们。
 
    -更正了BUG#3520,DBMD.getSQLStateType() 返回不正确的值。
 
    -更正了 PreparedStatement.setString() 和东方字符编码中的递归问题。
 
    - 增加了对 StringRegressionTest 4.1-unicode 的识别。
 
02-19-04:版本3.0.11-stable
 
    -通过“characterEncoding”属性将编码方式强制设为“utf8”或“utf-8”时,触发“SET NAMES utf8”。以前,只能用 Java 风格的“utf-8”编码名称才能触发该操作。
 
    -AutoReconnect 时间的增长速度快于指数速度 (BUG#2447)。
 
    -更正了故障切换总跳至列表中最后 1 个主机的问题 (BUG#2578)。
 
    -增加了“useUnbufferedInput”参数,它也是目前的默认参数 (因 JVM 事宜,http://developer.java.sun.com/developer/bugParade/bugs/4401235.html)。
 
    -检测服务器上 lower_case_table_names 的“on/off”,或“1”、“2”、“3”形式。
 
    -为 ResultSetMetaData.getColumnClassName() 的 TINYINT 和 SMALLINT 类型返回“java.lang.Integer”(更正了BUG#2852)。
 
    -为 ResultSetMetaData.getColumnClassName() 的 FLOAT 类型返回“java.lang.Double”(更正了BUG#2855)。
 
    -为 ResultSetMetaData.getColumnClassName() 的 BINARY、VARBINARY 和 LONGVARBINARY 类型返回“[B”而不是“java.lang.Object”(兼容 JDBC)。
 
    -在由 ConnectionPoolDataSource 创建的所有实例上发出连接事件。
 
01-13-04:版本3.0.10-stable
 
    -在 PreparedStatement 解析中,当位于“字符串”内时,不对引用的 ID 进行计数 (更正了BUG#1511)。
 
    -关于 PacketTooLargeException 的“Friendlier”异常消息 (BUG#1534)。
 
    -从 3.1 版开始,反向移植了对 checkUpdatability() 方法中别名表和 UpdatableResultSets 的补丁。
 
    -更正了使用 Statement.setMaxRows() 时出现的 ArrayIndexOutOfBounds 异常 (BUG#1695)。
 
    -更正了BUG#1576,处理未正确读取的大 BLOB 和分离信息包。
 
    -更正了 Statement.getGeneratedKeys() 和 REPLACE 语句的递归问题。
 
    -更正了BUG#1630,如果结果集是不可更新的,对 ResultSet.updateFoo() 的后续调用将导致 NPE。
 
    -确定了 4.1.1 风格的 auth,无密码。
 
    -更正了BUG#1731,外键列的顺序与 DatabaseMetaData.getImported/Exported/CrossReference() 不一致。
 
    -更正了BUG#1775,DatabaseMetaData.getSystemFunction() 返回错误函数“VResultsSion”。
 
    -更正了BUG#1592,未正确检查交叉数据库可更新结果集的可更新性。
 
    -对于 MySQL LONGTEXT 类型,DatabaseMetaData.getColumns() 应返回 Types.LONGVARCHAR。
 
    -作用在 TINYINT 和 SMALLINT 列上的 ResultSet.getObject() 应返回 Java 类型“Integer”(BUG#1913)。
 
    -增加了“alwaysClearStream”连接属性,它会使驱动程序在每次查询前清空输入流上任何余留的数据。
 
    -增加了更具描述性的错误消息“Server Configuration Denies Access to DataSource”(服务器配置拒绝对数据源的访问),并能从服务器上检索消息。
 
    -如果已发生变化,Autoreconnect 代码在红心连接时不设置 catalog。
 
    -实现了 ResultSet.updateClob()。
 
    -对于 CHAR/VARCHAR 列,ResultSetMetaData.isCaseSensitive() 返回错误值。
 
    -更正了BUG#1933,不尊重连接属性“maxRows”。
 
    -更正了BUG#1925,在 DBMD.extractForeignKeyFromCreateTable() 中,创建语句的次数太多。
 
    -更正了BUG#1914,支持转义序列{fn convert ... }
 
    -更正了BUG#1958,当参数编号等于参数数目+1 时,ArrayIndexOutOfBounds。
 
    -更正了BUG#2006,当 SELECT 查询中有多个重复列名时,ResultSet.findColumn() 应使用第 1 个匹配的列名 (兼容 JDBC)。
 
    -从 PreparedStatement.setTimestamp() 中删除了静态同步瓶颈。
 
    -从 SingleByteCharsetConverter 的实例方法中删除了静态同步瓶颈。
 
    -允许通过“cachePrepStmts”、“prepStmtCacheSize”和“prepStmtCacheSqlLimit”属性,对预处理语句的解析步骤进行高速缓冲处理 (默认情况下禁止)。
 
    -加快了 PreparedStatements 的解析操作,只要可能,尽量采用一次性方式。
 
    -更正了在小应用程序中使用时的安全异常问题 (小应用程序不能读取 LOAD DATA LOCAL INFILE 所需的系统属性“file.encoding”)。
 
    -为 SQLStates 使用常数。
 
    -连接至 MySQL-4.1.0 或更高版本时,将字符集“ko18_ru”映射到“ko18r”。
 
    -确保 Buffer.writeString() 保存在“\0”之外的空间内。
 
    -更正了“connect w/ JDK-1.4.0”上的异常“未知字符集 danish”。
 
    -更正了 SQLError 中的映射功能,用“41000”SQLStates 通报死锁状态。
 
    -“maxRows”属性会影响内部语句,因此,应检查为驱动程序创建的所有内部语句,并在不是内部语句的情况下将其设为 0。
 
10-07-03:版本3.0.9-stable
 
    -ResultSet 和 PreparedStatement 中更快的日期处理代码 (不再使用用来同步静态日历的 Date 方法)。
 
    -更正了对 Buffer.readString() 中缓冲区末端的测试。
 
    -更正了 ResultSet.previous() 行为方式,当位于结果集的第 1 行上时,将当前位置移到结果集之前 (bugs.mysql.com BUG#496)。
 
    -更正了当已使用 setMaxRows() 而且在查询中包含 LIMIT 子句时发出伪查询的语句和 PreparedStatement。
 
    -更正了BUG#661,当主键值包含需要转义的值时 refreshRow 不工作 (以双倍转义结束)。
 
    -提取 DatabaseMetaData 中的外键信息时,支持 InnoDB 约束名,BUG#517BUG#664(由 Parwinder Sekhon 提出)。
 
    -从 3.1 版开始,反向移植了 4.1 协议变化 (服务器端 SQL 状态,新字段信息,较大的客户端能力标志,与数据库的连接等)。
 
    -更正了 UpdatableResultSet,作用在插入行上时,为 getXXX() 返回值 (BUG#675)。
 
    -调用 moveToInsertRow() 时,能够用默认的列值加载 UpdatableResultSet 中的 insertRow(BUG#688)。
 
    -对于指定为 NULL 的默认值,DatabaseMetaData.getColumns() 未返回 NULL。
 
    -将默认的语句类型/并发行更改为 TYPE_FORWARD_ONLY 和 CONCUR_READ_ONLY(兼容规范)。
 
    -如果 MySQL 不支持,不要尝试或复位再连接上的隔离级别。
 
    -不将 SQLExceptions 封在 RowDataDynamic 内。
 
    -如果 useTimezone==true,不更改时间戳 TZ 两次 (BUG#774)。
 
    -更正了大的分离信息包处理中存在的回归问题 (BUG#848)。
 
    -更好地诊断“流式”结果集异常中的错误消息。
 
    -在空结果集上抛出关于 ResultSet.getXXX() 的异常 (在某些情况未被俘获)。
 
    -不隐藏关于在 I/O 层中抛出异常的消息。
 
    -关闭连接池时或在具有已打开连接的 PooledConnection.getConnection() 上,不触发连接关闭时间 (BUG#884)。
 
    -截短+/- INF(最小和最大代表值,对于 MySQL 中的类型),以及 NaN(至 0,对于 setDouble/setFloat()),当服务器不支持+/- INF 或 NaN 时,就语句发出警告。
 
    -更正了BUG#879,当字符集为 SJIS 或 GBK 时,以及“\”出现在非转义输入中时对“\”的双转义处理。
 
    -清空“流式”结果集未使用行的输入流时,每 100 行均有当前线程 yield(),以免独占 CPU 时间。
 
    -更正了BUG#1099,DatabaseMetaData.getColumns() 弄不清字符列中的关键字“set”。
 
    -更正了与 Statement.setMaxRows() 相关的死锁事宜。
 
    -更正了 CLOB.truncate(),BUG#1130
 
    -优化了 CLOB.setChracterStream(), BUG#1131
 
    -使 databaseName、portNumber 以及 serverName 成为 MysqlDataSourceFactory 的可选参数 (BUG#1246)。
 
    -修订了BUG#1247,导致字符 127 损坏的 ResultSet.get/setString。
 
    -从 3.1 版开始,反向移植了针对 4.11 和更高版本的 auth.更改。
 
    -增加了 com.mysql.jdbc.util.BaseBugReport,以帮助创建缺陷报告的测试范例。
 
    -通过将“clobberStreamingResults”属性设置为“真”(默认为“假”),为“clobber”流式结果增加了属性。这会使“流式”结果集被自动关闭,如果在所有数据尚未从服务器中读取完之前,执行了另一查询,正在从服务器流出的任何未完成数据均将被舍弃。
 
05-23-03:版本3.0.8-stable
 
    -允许在 Driver.getPropertyInfo() 中使用伪 URL。
 
    -与 Statement.getGeneratedKeys() 一起使用多值 INSERTS 时,返回所生成键的列表。
 
    -与文件名和“LOAD DATA [LOCAL] INFILE”一起使用 JVM 字符集。
 
    -更正了与 Connection.cleanup() 有关的无限循环。
 
    -将 Ant 目标“compile-core”更改为“compile-driver”,并使测试套件编译成为单独的目标。
 
    -更正了未获得关于 Statement.executeUpdate() 的集合的结果集,在某些情况下,它会影响 getGeneratedKeys() 和 getUpdateCount()。
 
    -字符串中的 Unicode 字符 0xFFFF 会导致驱动程序抛出 ArrayOutOfBoundsException(Bug #378)。
 
    -使用“REPLACE”语句时返回所生成键的正确数目。
 
    -更正了在某些情况下检测服务器字符集的问题。
 
    -更正了使用极大信息包时的行数据解码错误。
 
    -优化了行数据解码。
 
    -在已关闭预处理语句上执行操作使抛出异常。
 
    -更正了 SJIS 编码缺陷,感谢 Naoto Sato。
 
    -优化了 EscapeProcessor 的使用。
 
    -允许对 Statement.close() 的多次调用。
 
04-08-03:版本3.0.7-stable
 
    -更正了调用错误事件类型的 MysqlPooledConnection.close()。
 
    -更正了 PreparedStatement.setClob() 中的 StringIndexOutOfBoundsException。
 
    - 4.1 版列元数据更正。
 
    -从 Driver.connect() 和 Driver.acceptsUrl() 中删除了同步功能。
 
    -事务过程中的 IOExceptions 现在会导致关闭连接。
 
    -更正了 ResultSetMetaData.getColumnTypeName() 中丢失的“YEAR”类型转换。
 
    -对于 DBMD.getPrimaryKeys(),不提取以“pri”作为主键起始的索引。
 
    -试图在强制关闭的连接上执行操作时抛出 SQLExceptions(即,通信链路失败时)。
 
    -现在,可以使用 Connection.setProfileSql(boolean) 来打开或关闭仿型功能。
 
    更正了与数据库元数据有关的字符集事宜 (字符集不能正确获取集合)。
 
    -与 MySQL-4.1 或更高版本连接时,现在能够为别名表/列创建可更新结果集。
 
    -更正了文件大于“max_allowed_packet”时的“LOAD DATA LOCAL INFILE”缺陷。
 
    -对于 GBK 和 Big5 字符集,更正了 0x5c ('\') 字符的转义功能。
 
    -更正了基础字段为 DATE 类型时的 ResultSet.getTimestamp() 问题。
 
    -保证了来自 alignPacketSize() 的信息包大小不超过 MAX_ALLOWED_PACKET(JVM 缺陷)。
 
    -autoReconnecting(自动再连接) 时不复位 Connection.isReadOnly()。
 
02-18-03:版本3.0.6-stable
 
    -更正了 ResultSetMetaData,当 catalog 未知时返回""。更正了与 Sun CachedRowSet 有关的 NullPointerExceptions。
 
    -更正了 DBMD.getTypeInfo() 和 DBMD.getColumns() 为 TEXT/BLOB 类型中的精度返回不同值的问题。
 
    -通过将“ignoreNonTxTables”设置为“真”,在回退期间 (兼容性/可用性),允许忽略“non transactional tables”(非事务表) 告警。
 
    -更正了在初始连接上 SQLExceptions 耗尽的问题。
 
    -更正了 Statement.setMaxRows(),当其不需要时,停止发送“LIMIT”类型的查询 (性能)。
 
    -整理了语句查询/方法失配测试 (即,不允许与。executeQuery() 一起使用 INSERT)。
 
    -在 ResultSet 遍历方法中增加了更多检查,以获取何时处于关闭状态的信息。
 
    -更正了 ResultSetMetaData.isWritable() 以返回正确值。
 
    -为 DBMD.nullsAreSortedAtStart 增加了不同 NULL 分类行为的“窗口”(4.0.2 至 4.0.10,真,其他为“否”)。
 
    -实现了 Blob.setBytes()。仍需要将所得的 Blob 传回到可更新 ResultSet(结果集) 或 PreparedStatement 以保持变更,这是因为 MySQL 不支持“定位器”。
 
    -从 Connector/J 3.1 反向移植了 4.1 字符集字段。
 
01-22-03:版本3.0.5-gamma
 
    -更正了解包字段时对某些查询 Buffer.fastSkipLenString() 导致 ArrayIndexOutOfBounds 异常的问题。
 
    -为 Connection.getTypeMap() 实现了空的 TypeMap,以便某些第三方应用程序能与 MySQL 一起工作 (IBM WebSphere 5.0 连接池)。
 
    -为 DBMD.getColumns() 增加了丢失的 LONGTEXT 类型。
 
    -当 MySQL 版本支持时,Connection.getTransactionIsolation() 能从数据库检索 TX_ISOLATION,而不是实例变量。
 
    -引用 DatabaseMetaData.getColumns()、getPrimaryKeys()、getIndexInfo()、getBestRowIdentifier() 中的表名。
 
    -大幅度降低了 PreparedStatements 中 setBinaryStream() 所需的内存。
 
    -更正了 ResultSet.isBeforeFirst() 处理空结果集方面的问题。
 
    -为外键元数据增加了“更新”选项。
 
 
01-06-03:版本3.0.4-gamma
 
    -为 Connection.setCatalog 增加了对数据库名的引用 ID。
 
    -在 PreparedStatement 分析程序中增加了对引用 ID 的支持。
 
    -对于 setByte(),在 PreparedStatements 中,流线式字符转换和 byte[] 处理。
 
    -通过与 MysqlIO 共享出站信息包,降低了 PreparedStatements 的内存占用。
 
    -增加了“strictUpdates”属性,能够对可更新结果集的大量“正确性”检查进行控制。如果希望获得更快的可更新结果集,并使用主键通过作用在表上的 SELECT 创建了结果集,而且在查询中选择了所有的主键,应将其设置为“假”。
 
    -增加了对 4.0.8 风格大信息包的支持。
 
    -更正了 PreparedStatement.executeBatch() 参数重写的问题。
 
12-17-02:版本3.0.3-dev
 
    -将 SingleByteCharConverter 中的 charsToByte 更改为非静态类型。
 
    -更改了 SingleByteCharConverter,以使用各转换器的空闲初始化特性。
 
    -更正了 Fields.java 中的字符集处理功能。
 
    -实现了 Connection.nativeSQL()。
 
    -更可靠的转义标志“-- recognize '--'”注释,并允许嵌套式转义序列 (请参见 testsuite.EscapeProcessingTest)。
 
    -DBMD.getImported/ExportedKeys() 现在能处理每个表上的多个外键。
 
    -更正了对某些浮点类型 ResultSetMetaData.getPrecision() 返回错误值的问题。
 
    -更正了 ResultSetMetaData.getColumnTypeName() 对 TEXT 类型返回 BLOB,对 BLOB 类型返回 TEXT 的问题。
 
    -对于 4.1 和更高版本服务器,更正了 Buffer.isLastDataPacket()。
 
    -增加了 CLIENT_LONG_FLAG,以便能获得更多的列标志 (isAutoIncrement() 最重要)。
 
    -由于上述原因,实现了 ResultSetMetaData.isAutoIncrement() 以使用 Field.isAutoIncrement()。
 
    -在 DatabaseMetaData 方法中比较表名且在服务器中允许时,优先考虑“lower_case_table_names”。
 
    -一些 MySQL-4.1 协议支持 (扩展字段信息)。
 
    -使用非别名表/列名和数据库名,以完全限定 UpdatableResultSet 中的表和列 (需要 MySQL-4.1 或更高版本)。
 
    -允许用户通过“continueBatchOnError”属性 (默认为“真”) 更改 Statement/PreparedStatement.executeBatch() 的行为。
 
    -在更多连接方法 (createStatement、prepareStatement、setTransactionIsolation、setAutoCommit) 中检查关闭的连接。
 
    -更可靠地实现了可更新结果集。检查表的所有主键是否已被选择。
 
    -如果在服务器的配置允许,“LOAD DATA LOCAL INFILE ...”现在能正常工作。不能使用“allowLoadLocalInfile”属性关闭它 (请参见 README)。
 
    -在单字节字符集中,对于未知的字符转换,用“?”替代“\0”。
 
    - NamedPipeSocketFactory 现能正常工作 (仅对 Windows 平台)。具体说明请参见 README。
 
11-08-02:版本3.0.2-dev
 
    -更正了可更新结果集和 PreparedStatements 不工作的问题。
 
    -更正了 ResultSet.setFetchDirection(FETCH_UNKNOWN)。
 
    -更正了使用任意值并调用 Statement.setFetchSize() 时的问题。
 
    -更正了 ResultSet.getLong() 中的不正确转换。
 
    -实现了 ResultSet.updateBlob()。
 
    -删除了 UpdatableResultSet 中的重复代码 (能从 ResultSet 继承而来,不需要各方法处理可更新性的额外代码,但我认为在将来可能需要)。
 
    -更正了通过属性“强制”字符编码时抛出的“UnsupportedEncodingException”。
 
    -更正了各种非 ASCII 字符编码问题。
 
    -增加了驱动程序属性“useHostsInPrivileges”。默认值为“真”。它将影响是否在“DBMD.getColumn/TablePrivileges”中使用“@hostname”。
 
    -描述方案的所有 DBMD 结果集列现返回 NULL,以便能与用于其他数据库的其他 JDBC 驱动程序的行为更兼容 (MySQL 不支持方案)。
 
    -增加了 SSL 支持。关于如何使用它的更多信息,请参见 README。
 
    -执行自动再连接或故障切换时,恰当恢复连接属性,包括 autoCommit 状态以及隔离级别。
 
    -可能时,使用“SHOW CREATE TABLE”,以确定用于 DatabaseMetaData 的外键信息,对于返回的 DELETE 信息还允许级联选项。
 
    -对于 SJIS 字符集,转义了字符串中的“0x5c”字符。
 
    -更正了 Clob.getSubString() 中起始位置偏离 1 的错误。
 
    -实现了 Clob.truncate()。
 
    -实现了 Clob.setString()。
 
    -实现了 Clob.setAsciiStream()。
 
    -实现了 Clob.setCharacterStream()。
 
    -增加了 com.mysql.jdbc.MiniAdmin 类,该类允许你将“shutdown”命令发送至 MySQL 服务器。在最终用户应用中嵌入 Java 和 MySQL 服务器时使用。
 
    -增加了“connectTimeout”参数,允许 JDK-1.4 和更高版本的用户指定建立连接所需等候的最长时间。
 
    -仅当连接处于 autoCommit(false) 状态时,故障切换和 autoReconnect 才能工作,目的在于保持事务的安全。
 
    -增加了“queriesBeforeRetryMaster”属性,出现故障切换时而且在重新连接到主服务器之前,该属性指定了能够发出的查询数目 (默认为 50)。
 
    -更正了 DBMD.supportsResultSetConcurrency(),以便为 ResultSet.TYPE_SCROLL_INSENSITIVE 和 ResultSet.CONCUR_READ_ONLY 或 ResultSet.CONCUR_UPDATABLE 返回“真”。
 
    -更正了 ResultSet.isLast() 处理空结果集方面的问题 (应返回“假”)。
 
    - PreparedStatement 现在将优先考虑 setBinary/Ascii/Character Stream() 中的流长度,除非将连接属性“useStreamLengthsInPrepStmts”设置为“假”。
 
    -删除了一些使用 EscapeProcessor、Connection 和 DatabaseMetaData 类中的“Strings smarter”创建的不需要的临时对象。
 
09-21-02:版本3.0.1-dev
 
    -更正了 ResultSet.getRow() 偏差 1 的缺陷。
 
    -更正了 RowDataStatic.getAt() 偏差 1 的缺陷。
 
    -增加了有限 Clob 功能 (ResultSet.getClob()、PreparedStatemtent.setClob()、PreparedStatement.setObject(Clob))。
 
    -为 URL 增加了 socketTimeout 参数。
 
    - Connection.isClosed() 不再对服务器执行“Ping”操作。
 
    -当“getAutoCommit() == false”时 Connection.close() 发出 rollback()。
 
    -增加了“妄想”参数,通过删除其中的“敏感”信息清理了错误消息 (即,主机名、端口、用户名等),并在可能的情况下,清理了“敏感”的数据结构。
 
    -更正了 ResultSetMetaData.isSigned() 在处理 TINYINT 和 BIGINT 方面的问题。
 
    - 现在将自动检测字符集。优化了单字节字符集转换的代码。
 
    -实现了 ResultSet.getCharacterStream()。
 
    -为 DatabaseMetaData.getTableTypes() 中的表类型增加了“LOCAL TEMPORARY”。
 
    - 整理了大块代码,以遵循 Java 编码惯例 (时机成熟)。
 
 
07-31-02:版本3.0.0-dev
 
    - !!! 许可变化!!!驱动现在是 GPL。如果需要非 GPL 许可,请与我们联系 (mark@mysql.com)。
 
    - JDBC-3.0 功能包括 Statement/PreparedStatement.getGeneratedKeys() 和 ResultSet.getURL()。
 
    -性能增强,在大多数情况下,驱动程序快了 50-100%,而且创建的临时对象更少。
 
    -重新封装...新的驱动程序名是“com.mysql.jdbc.Driver”,但旧名称依然有效 (驱动程序现由 MySQL-AB 提供)。
 
    -更好地在语句和 PreparedStatement 中检查已关闭的连接。
 
    -支持流式结果集 (按行),请参见 README,感谢 Doron。
 
    -支持大信息包 (MySQL-4.0 协议的新增内容),更多信息请参见 README。
 
    - JDBC 兼容,除了存储程序测试外,提供了所有测试。
 
 
    -更正并分类了 DBMetaData 中的主键名称 (SF 缺陷 582086 和 582086)。
 
    -浮点类型现为 java.sql.Types.FLOAT(SF 缺陷 579573)。
 
    - ResultSet.getTimestamp() 现在能处理 DATE 类型 (SF 缺陷 559134)。
 
    - ResultSet.getDate/Time/Timestamp 现在能识别由 MySQL 设置为全零的所有形式的无效值 (SF 缺陷 586058)。
 
    - Testsuite 现在将使用 Junit(可从www.junit.org获得)。
 
    -驱动程序现在仅能与 JDK-1.2 或更高版本一起工作。
 
    -增加了多主机故障切换支持 (请参见 README)。
 
    -进行了一般性的源码清理。
 
    -读取信息包时,通过控制 MysqlIO 类创建的过渡对象,改善了总的速度。
 
    -改善了字符串处理和字段元数据创建的性能 (例示),由 Alex Twisleton-Wykeham-Fiennes 提供。
 
 
05-16-02:版本2.0.14
 
    -更多代码整理。
 
    - PreparedStatement 现在能释放。close() 上的资源 (SF 缺陷 553268)。
 
    -如果服务器版本不支持,不使用引用 ID。此外,如果服务器是以“ansi”或“--sql-mode=ANSI_QUOTES”开始,那么“"”将用作 ID 引用,否则将使用“`”。
 
    - ResultSet.getDouble() 现在能更准确地使用 JDK 内置的代码 (但较慢)。
 
    - LogicalHandle.isClosed() 调用,直至物理连接。
 
    -增加了 SQL 仿型功能 (到 STDERR)。在 JDBC url 中设置“profileSql=true”。更多信息请参见 README。
 
    -更正了 relaxAutoCommit 参数的类型。
 
04-24-02:版本2.0.13
 
    -更多代码整理。
 
    -更正了未能正确读取的 unicode 字符 (SF 缺陷 541088)。
 
    -为 PrepStmt 提供了更快的 Blob 转义功能。
 
    -为 DataSource(s) 增加了 set/getPortNumber()(SF 缺陷 548167)。
 
    -为 MySQLXADataSource 增加了 setURL()(SF 缺陷 546019)。
 
    -更正了 PreparedStatement.toString()(SF 缺陷 534026)。
 
    -实现了 ResultSetMetaData.getColumnClassName()。
 
    - 现在实施了来自 JDBC-3.0 的 Statement.getGeneratedKeys() 的初级版本 (要想使之工作,需要使用 JDK-1.4,我个人认为)。
 
    - DBMetaData.getIndexInfo(),更正了不良的 PAGES(SF 缺陷 542201)。
 
04-07-02:版本2.0.12
 
    -一般性代码整理。
 
    -为 Connection 和 MysqlLogicalHandle 增加了 getIdleFor() 方法。
 
    -放松了所有类中的功能,应更正 520615 和 520393。
 
    -为 DBMD 增加了 getTable/ColumnPrivileges()(更正 484502)。
 
    -为 getTypeInfo() 增加了新类型,更正了已有类型,感谢 Al Davis 和 Kid Kalanon。
 
    -为 PreparedStatement 增加了 BIT 类型支持 (51870)。
 
    -更正了 ResultSet 中的 getRow() 缺陷 (527165)。
 
    -更正了 PreparedStatement 中的 ResultSet 可更新性。
    -更正了 PreparedStatement 中时区偏差 1 小时的缺陷 (538286、528785)。
 
    - ResultSet:更正了可更新性 (如果不可更新,将值设为 NULL)。
 
    - DataSources,更正了 setUrl 缺陷 (511614、525565),错误的数据源类名 (532816、528767)。
 
    -为需要它们的所有 DatabaseMetaData 方法增加了 ID 引用 (应更正 518108)。
 
    -增加了对 YEAR 类型的支持 (533556)。
 
    - ResultSet.insertRow() 目前能够在大多数情况下检测 auto_increment 字段,并在新行中使用该值。但是,该检测不适用于多值键,原因在于 MySQL 协议不返回该类信息。
 
    -实现了 ResultSet.refreshRow()。
 
    -更正了 testsuite.Traversal afterLast() 缺陷,感谢 Igor Lastric。
 
01-27-02:版本2.0.11
 
    
-更正了DBMD.getImported/ExportedKeys()getCrossReference()中丢失的DELETE_RULE值。
 
    -Statement.java 的完全同步。
 
    -多处修改,更正了读取 BLOB 时的“Unexpected end of input stream”(输入流意外结束) 错误。这应是最后更正。
 
01-24-02:版本2.0.10
 
     -更正了 MysqlIO 中的虚假“Unexpected end of input stream”(输入流意外结束) 错误 (缺陷 507456)。
 
     -更正了与 Websphere 4 一起使用 MysqlConnectionPoolDataSource 时的“null-pointer-exceptions”(缺陷 505839)。
 
01-13-02:版本2.0.9
 
     - Ant 创建失败,包括 jar 文件,已更正 (缺陷 487669)。
 
     -更正了 MysqlIO.readPacket() 中额外的内存分配 (缺陷 488663)。
 
     -实现了 DatabaseMetaData.getExported/ImportedKeys() 和 getCrossReference()。
 
     -在更改实例和类共享引用的方法上,实现了完全同步,驱动程序现在是完全线程安全的 (如果遇到问题,请告诉我)。
 
     -将 DataSource 实施移至 org.gjt.mm.mysql.jdbc2.optional 软件包,PooledConnectionDataSource 和 XADataSource 的原始实施仍保留在原处 (感谢 Todd Wolff 给出了 PooledConnectionDataSource 与 IBM WebSphere 4 一起的实施方案和测试结果)。
 
     -增加了读取信息包时对关闭网络连接的检测 (感谢 Todd Lizambri)。
 
     -更正了与转义处理其有关的错误 (缺陷 486265)。
 
     -通过 DatabaseMetaData,支持批更新 (缺陷 495101)。
 
     -更正了 PreparedStatement.setTimestamp() 中偏差 1 小时的错误 (缺陷 491577)。
 
     -从驱动程序中删除了级连支持 (“||”操作符),较早的 VisualAge 版本似乎是使用它的唯一软件,它与逻辑“||”操作符冲突。要想使用“||”操作符作为级联,需要用“--ansi”标志启动 mysqld(缺陷 491680)。
 
     -更正了 PreparedStatement 中的舍弃缺陷 (488663)。
 
11-25-01:版本2.0.8
 
     -现在支持批更新 (感谢 Daniel Rall 的鼓励)。
 
     - XADataSource/ConnectionPoolDataSource 代码 (实验性)。
 
     - PreparedStatement.setAnyNumericType() 现在能正确处理正指数 (增加了“+”,因此 MySQL 能理解它)。
 
     - DatabaseMetaData.getPrimaryKeys() 和 getBestRowIdentifier() 目前在识别主键方面更加可靠 (匹配,不管主键在 Key_type 列中的大小写、或缩写/全名)。
 
10-24-01:版本2.0.7
 
     - PreparedStatement.setCharacterStream() 现已实现。
 
     -更正了处于高利用率模式 (autoReconnect=true) 下时的悬挂套接字问题,连接的 finalizer 将关闭任何在 GC 上悬挂的套接字。
 
     -更正了在较新版本的 MySQL 上 ResultSetMetaData.getPrecision() 返回的值比实际值小 1 的问题。
 
     -如果列值为 NULL,ResultSet.getBlob() 现在将返回 NULL。
 
     -如果 useUnicode=true 而且未设置 characterEncoding,将从数据库读取字符集。(感谢 Dmitry Vereshchagin)。
 
     -从数据库读取初始事务隔离级别 (如果可用的话)(感谢 Dmitry Vereshchagin)。
 
     -更正了 DatabaseMetaData.supportsTransactions(),supportsTransactionIsolationLevel(),getTypeInfo() SQL_DATETIME_SUB,以及不可读取的 SQL_DATA_TYPE 字段。
 
     -更正了用于生成 SQL 并回在某些查询中以语法错误结束的 PreparedStatement。
 
     -更正了 ResultSet.isAfterLast() 总返回“假”的问题。
 
     -更正了 PreparedStatement.setTimestamp() 中的时区问题 (感谢 Erik Olofsson)。
 
     -在 URL 或属性中传递了“captializeTypeNames=true”时,将类型名转换为大写 (对于 WebObjects,感谢 Anjo Krank)。
 
     -可更新结果集现在能正确处理字段中的 NULL 值。
 
     - PreparedStatement.setDouble() 现在能使用双精度值 (撤销了以前所作的截取更正)。
 
     -如果 MySQL 的版本高于或等于 3.21.23,PreparedStatement.setBoolean() 将使用 1/0 值。
 
06-16-01:版本2.0.6
 
     -更正了 PreparedStatement 参数检查功能。
 
     -更正了 ResultSet.java 中区分大小写的列名。
 
06-13-01:版本2.0.5
 
     - 更正了 ResultSet.getBlob() ArrayIndex 超出范围的问题。
 
     -更正了 ResultSetMetaData.getColumnTypeName 关于 TEXT/BLOB 的问题。
 
     -更正了发送大 BLOB 查询时的 ArrayIndexOutOfBounds 问题 (未设置最大信息包大小)。
 
     -为 Connection.setIsolationLevel() 增加了 ISOLATION 级别支持。
 
     -更正了所有列均未设置时在 PreparedStatement.executeUpdate() 上的 NPE 问题。
 
     -更正了采用两位数字年份的 TIMESTAMP 的数据解析问题。
 
     -为 PreparedStatement.setObject() 增加了 Byte。
 
     - ResultSet.getBoolean() 现在能将“-1”识别为“真”。
 
     - ResultSet 具有+/-Inf/inf 支持特性。
 
     -即使并非所有列均已被设置 (设为 NULL),ResultSet.insertRow() 现在也能工作。
 
     - DataBaseMetaData.getCrossReference() 不再使用 ArrayIndexOOB。
 
     -作用在结果集上的 getObject() 能正确执行 TINYINT->Byte 和 SMALLINT->Short 操作。
 
12-03-00:版本2.0.3
 
     -为 JDBC2 实现了不带标度组分的 getBigDecimal()。
 
     -更正了与可更新结果集有关的复合键问题。
 
     -增加了-/+INF 对双精度的检测。
 
     -更快的 ASCII 字符串操作。
 
     -更正了 MAX_ALLOWED_PACKET 的不正确检测,因此,现在能发送大的 Blob。
 
     -更正了 java.sql.Blob 实施代码中的“偏差 1”错误。
 
     -增加了“ultraDevHack”URL 参数,将其设置为“真”,可允许 Macromedia UltraDev 使用该驱动程序。
 
04-06-00:版本2.0.1
 
     -更正了 RSMD.isWritable() 返回错误值的问题。感谢 Moritz Maass。
 
     -整理了连接确定时的异常处理功能。
 
     -使用 getObject(),具有 TEXT 类型的列现在会作为字符串返回。
 
     - DatabaseMetaData.getPrimaryKeys() 现在能正确工作 (写入到 key_seq)。感谢 Brian Slesinsky。
 
     -按照 JDBC 规范,在 PreparedStatements 上,不再进行转义处理。
 
     -更正了很多 JDBC-2.0 遍历、定位错误,尤其是写入空结果集的问题。感谢 Ron Smits、Nick Brook、Cessar Garcia 和 Carlos Martinez。
 
     -更正了使用多个主键时,与结果集中可更新性支持有关的一些问题。
 
02-21-00:版本2.0pre5
 
     -更正了不良的握手问题。
 
01-10-00:版本2.0pre4
 
     -更正了针对 insertRow() 的结果集,感谢 Cesar Garcia。
 
     -对驱动程序进行了修改,使之能够通过加载 JDBC-2.0 类来识别 JDBC-2.0,而不是依靠 JDK 版本号。感谢 John Baker。
 
     -更正了结果集,以返回正确的行号。
 
     - Statement.getUpdateCount() 现在能返回匹配的行,而不是实际更新的行,它更像 SQL-92。
 
10-29-99
 
     -更正了 Statement/PreparedStatement.getMoreResults() 缺陷。感谢 Noel J. Bergman。
 
     -为 PreparedStatement.setObject() 增加了 Short 类型。感谢 Jeff Crowder。
 
     -驱动程序现在能通过查询服务器自动配置最大/首选的信息包大小。
 
     -如果服务器支持,Autoreconnect 代码将使用更快的 ping 命令。
 
     -更正了从服务器读取信息包、以及为写入到服务器而分配信息包时与信息包大小有关的多种缺陷。
 
08-17-99:版本2.0pre
 
     -目前是在 JDK-1.2 下编译的。通过核心类集合,驱动程序同时支持 JDK-1.1 和 JDK-1.2。在运行时,通过判断你所使用的 JVM 版本,驱动程序将加载恰当的接口类。
 
     -修正了在首行中全为 NULL 的结果集。(由 Tim Endres 指出)。
 
     -更正了结果集内 SQLExceptions 的列编号 (感谢 Blas Rodriguez Somoza)。
 
     -不再需要将数据库指定给连接。(感谢 Christian Motschke)。
 
07-04-99:版本1.2b
 
     -更好的文档 (不断改善),doc/mm.doc/book1.html。
 
     -对于列名模式,DBMD 现在允许 null(未在规范中定义),它将被更改为“%”。
 
     - DBMD 现在提供了针对 getXXX() 的正确类型/长度。
 
     -修改了 ResultSet.getDate()、getTime() 和 getTimestamp()。(由 Alan Wilken 提供)。
 
     - EscapeProcessor 现在能正确处理引号内的“\{ \}”和“{ or }”。(感谢 Alik 就如何修正它给出的观点)。
 
     -对连接中的属性处理功能进行了修正。(由 Juho Tikkala 提供)。
 
     -对于表中的 NULL 列,ResultSet.getObject() 现在能返回 NULL,而不是销毁。(感谢 Ben Grosman)。
 
     -对于 MySQL 不了解的类型,ResultSet.getObject() 现在能返回字符串。(由 Chris Perdue 建议)。
 
     -删除了不需要的 DataInput/Output 流,对于每次 IO 操作,1/2 的方法调用都是不需要的。
 
     -如果未指定字符编码,使用默认的字符编码。这是对已损坏 JVM 的一种避规措施,这是因为,按照规范,所有的 JVM 都必须支持“ISO8859_1”,但并非如此。
 
     -更正了连接事宜,如果未明确设置字符编码,将使用平台的字符编码,而不是“ISO8859_1”。它修正了加载并不总存在的字符转换器类时存在的问题 (JVM 缺陷)。(感谢 Fritz Elfert 指出了该问题)。
 
     -修改了 MysqlIO,使之在可能的情况下再次使用信息包,而不是降低内存使用率。
 
     -更正了与引号内“{}”有关的转义处理器缺陷。
 
04-14-99:版本1.2a
 
     -更正了对非 Javasoft JVM 的字符集支持 (感谢很多指出该问题的人员)。
 
     -更正了 ResultSet.getBoolean(),使之能够识别作为布尔标志的“y”和“n”,以及“1”和“0”。(感谢 Tim Pizey)。
 
     -更正了 ResultSet.getTimestamp(),以提供更好的性能。(感谢 Richard Swift)。
 
     - 更正了 getByte() 在处理数值类型方面的问题。(感谢 Ray Bellis)。
 
     - 更正了 DatabaseMetaData.getTypeInfo() 在处理 DATE 类型时存在的问题。(感谢 Paul Johnston)。
 
     -更正了用于“fn”调用的 EscapeProcessor。(感谢 locomotive.org 的 Piyush Shah)。
 
     -更正了 EscapeProcessor,如果没有转义代码,不执行额外操作。(感谢 Ryan Gustafson)。
 
     -更正了驱动程序,使之能解析“jdbc:mysql://host:port”形式的 URL(感谢 Richard Lobb)。
 
03-24-99:版本1.1i
 
     -更正了关于 PreparedStatements 的 Timestamps 问题。
 
     -更正了 RSMD 和 RS 中的 Null 指针异常。
 
     -对于有效的类文件,与 jikes 一起进行了再编译 (感谢 ms!)。
 
03-08-99:版本1.1h
 
     -更正了转义处理器,以处理不匹配的“{”和“}”(感谢 Craig Coles)。
 
     -更正了转义处理器,以创建移植性更好的 (在 DATETIME 和 TIMESTAMP 类型间) 表达式,以便能与 BETWEEN 子句一起使用。(感谢 Craig Longman。
 
     - MysqlIO.quit() 现在能关闭套接字连接。在此之前,多次连接失败后,某些操作系统将耗尽文件描述符。(感谢 Michael Brinkman)。
 
     -更正了 Driver.getPropertyInfo 中的 NullPointerException(感谢 Dave Potts)。
 
     -修正了 MysqlDefs,允许字字符串形式检索所有的*text 字段。(感谢 Chris at Leverage)。
 
     -更正了 PreparedStatement 中的 setDouble,使之能用于处理大数字,防止将科学记数法发送到数据库。(感谢 J.S. Ferguson)。
 
     -更正了 RSMD 中的 getScale() 和 getPrecision()。(由 James Klicman 贡献)。
 
     -更正了字段为 DECIMAL 或 NUMERIC 时的 getObject()(感谢 Bert Hobbs)。
 
     -传递 Null 表名时,DBMD.getTables() 出现严重故障。已更正 (感谢 Richard Lobb)。
 
     -增加了在连接过程中对“client not authorized”(客户端未被授权) 错误的检查。(感谢 Hannes Wallnoefer)。
 
02-19-99:版本1.1g
 
     -结果集行现在是字节数组。Blob 和 Unicode 现在能双向工作。目前实施了 useUnicode 和编码选项。
 
     -修正了 PreparedStatement,使用 setXXXStream(不改变地发送) 将二进制集合发送到 MySQL 服务器。
 
     -修正了 getDriverPropertyInfo()。
 
12-31-98:版本1.1f
 
     -将所有的结果集字段更改为字符串,这样,应能使 Unicode 工作,但你的 JVM 必须能够在字符集间进行转换。它还能使对服务器的数据读取更快,原因在于,现在不存在从 StringBuffer 到 String(字符串) 的转换。
 
     -更改了 PreparedStatement.streamToString(),使之更有效 (代码由 Uwe Schaefer 提供)。
 
     - URL 解析功能更可靠 (对于错误,抛出 SQL 异常,而不是 NullPointerExceptions)。
 
     - PreparedStatement 现在能通过 setObject() 将 String 转换为 Time/Date 值 (代码由 Robert Currey 提供)。
 
     -在 Buffer.readInt() 中,IO 进程不再被挂起,该缺陷是在 1.1d 中当将结果集更改为全字节数组时引入的。(由 Samo Login 指出)。
 
11-03-98:版本1.1b
 
     -修正了 DatabaseMetaData,允许 IBM VA 和 J-Builder 同时工作。请告诉我它的工作机制。(感谢 Jac Kersing)。
 
     -修正了 ResultSet.getBoolean() 在处理 NULL 字符串方面的问题 (感谢 Barry Lagerweij)。
 
     -开始代码整理,并进行了格式处理。开始将其分出为并行的 JDBC-2.0 源树。
 
     -为 MysqlIO 和 Buffer 内的关键部分增加了“最终”限定符,允许编译器采用内联方法以提高速度。
 
9-29-98
 
     -如果传递给 PreparedStatement 中 setXXX() 的对象引用是空的,将自动调用 setNull()。(感谢 Erik Ostrom 给出的提议)。
 
     -对于 Types.OTHER 对象和未知类型对象,PreparedStatement 中的 setObject() 现在会尝试将对象的串行化表示写入到数据库。
 
     - Util 现在有了 1 个静态方法 readObject(),结果集和列索引将以上述方式在此例示序列化的对象。
 
9-02-98 – 版本1.1
 
     -消除了 MysqlIO.nextRow() 中的“丑陋缺陷”。更正了 Buffer.isLastDataPacket(),而不是获取异常。
 
     - Connection.getCatalog() 和 Connection.setCatalog() 现在能够工作。
 
     - Statement.setMaxRows() 能够正常工作,也能使用属性 maxRows 进行设置。通过属性或 URL 参数,Statement.setMaxRows() 能覆盖 maxRows 设置。
 
     -提供了自动再连接功能。由于在每次查询前不得不 Ping 数据库,在默认情况下,它将被关闭。要想使用该功能,请在连接 URL 中传递“autoReconnect=true”。通过“maxReconnects=n”(默认为 3) 和“initialTimeout=n”(默认为 2 秒) 参数,你也可以更改再连接尝试的次数和初始超时值。Timeout 是超时的指数补偿类型。例如,如果初始超时设置为 2 秒,maxReconnects 为 3,那么再连接尝试之间的间隔分别是 2 秒,4 秒和 16 秒。
 
8-24-98:版本1.0
 
     - 更正了 Buffer.java 中 Blob 数据的处理功能。
 
     -更正了与尺寸过小的鉴定信息包有关的缺陷。
 
     -JDBC 驱动程序现在采用 LPGL。
 
8-14-98 -
 
     - 更正了 Buffer.readLenString(),使之能正确读取 BLOB 数据。
 
     -更正了 PreparedStatement.stringToStream,使之能正确读取 BLOB 数据。
 
     -更正了 PreparedStatement.setDate(),使之不增加 1 天。(感谢 Vincent Partington 在上述修正项方面的贡献)。
 
     -增加了 URL 参数解析功能 (?user=...等等)。
 
 
8-04-98:版本0.9d
 
     - 重大新闻! 新的软件包名。ICE 工程公司的 Tim Endres 着手为 GNU GPL 的 Java 软件建立新的源树。他友好地将 org.gjt.mm 软件包目录提供给我,因此,现在驱动程序在 org.gjt.mm.mysql 软件包中。目前我是合法用户。期待 Tim 项目的更多信息。
 
     -现在采用了动态确定大小的信息包,向数据库发送命令时,能够减少内存使用。
 
     -对 getTypeInfo() 的参数等方面进行了小的修正。
 
     - DatabaseMetaData 现已完全实现。如果这些驱动程序能与各种 IDE 一起工作,请告知。我已听说它们正与 Jbuilder 一起使用。
 
     -在软件包中增加了 JavaDoc 文档。
 
     -软件包采用。zip 或。tar.gz 格式提供。
 
7-28-98:版本0.9
 
     -实现了 getTypeInfo()。根据 JDBC 规范,Connection.rollback() 现在能抛出 SQLException。
 
     -增加了 PreparedStatement,它支持预处理语句的所有 JDBC API 方法,包括 InputStreams。请检查该点,如有问题,请告知。
 
     -更正了 ResultSet 中的 1 个缺陷,该缺陷会破坏仅返回 1 行的某些查询。
 
     - 更正了 DatabaseMetaData.getTables()、DatabaseMetaData.getColumns() 和 DatabaseMetaData.getCatalogs() 中存在的缺陷。
 
     -增加了语句的功能,允许 executeUpdate() 保存由 AUTO_INCREMENT 字段自动生成的 ID 值。一般而言,执行 executeUpdate() 后,将查找 SQLWarnings 以了解警告信息,如 LAST_INSERTED_ID = 'some number',COMMAND = 'your SQL query'。
 
 如果在表中正使用 AUTO_INCREMENT 字段,并在一条语句上执行了多个 executeUpdate(),务必每次都执行 clearWarnings() 以节省内存。
 
7-06-98:版本0.8
 
     -将 MysqlIO 和 Buffer 分离为单独类。对于这两个类中的某些字段,一些 ClassLoader(类加载器) 会给出 IllegalAccess(非法访问) 错误。现在,mm.mysql 能够在小应用程序和所有类加载器中正常工作。
 
 感谢 Joe Ennis jce@mail.boone.com指出该问题,并与我一起进行了修正。
 
7-01-98:版本0.7
 
     -更正了 getColumns() 中的 DatabaseMetadata problems,并更正了字段构造函数内开关语句中存在的缺陷。
 
 感谢 Costin Manolache costin@tdiinc.com指出了它们。
 
5-21-98:版本0.6
 
     -在 MysqlIO.java 和 ResultSet.java 中,结合 Richard Swift Richard.Swift@kanatek.ca给出的有效变更内容。
 
     -现在,我们的驱动程序比 GWE 的驱动程序快 15%。
 
     - 开始着手处理 DatabaseMetaData。
 
 实现了下述方法:
  * getTables()
  * getTableTypes()
  * getColumns
  * getCatalogs()

26.4. MySQL Connector/MXJ

26.4.1. ;前言

MySQL Connector/MXJ 是一种 Java 实用工具软件包,用于部署和管理 MySQL 数据库。可以将 Connector/MXJ 捆绑到已有的 Java 应用程序,或将其作为 JMX Mbean 部署。MySQL 的部署和使用十分简单,就像为 JDBC 连接 URL 添加额外参数一样简单,连接建立后,连接 URL 将启动数据库。这样,Java 开发人员能够通过降低其最终用户的安装难度,更容易地部署需要数据库的应用程序。

MySQL Connector/MXJ 使得 MySQL 数据库像是基于 java 的组件。它通过下述步骤完成该任务,确定系统所运行的平台,选择恰当的二进制文件,并执行程序。也能可选地部署具有任何指定参数的个初始数据库。

作为一种 JMX Mbean,MySQL Connector/MXJ 需要与 JMX v1.2 兼容的 Mbean 容器,如 Jboss 版本 4。Mbean 将使用标准的 JMX 管理 API 来展示与平台相适应的参数 (并允许设置参数)。

其中包含与 JDBC 驱动程序一起使用的说明,以及以 JMX Mbean 方式将其部署至 Jboss 的说明。

可从下述站点下载源版本和二进制版本:http://dev.mysql.com/downloads/connector/mxj/

这是一种测试板,欢迎反馈和鼓励。

如有任何问题或意见,请发送电子邮件至java@lists.mysql.com

26.4.2. ;支持平台:

  • Linux, i386

  • Windows NT, x86

  • Windows 2000, x86

  • Windows XP, x86

  • Solaris 9, SPARC 32

26.4.3. Junit 测试要求

要想确保你的平台是在支持范围内,最好方法是运行 Junit 测试。

首先应确保组件能够在平台上工作。由于“MysqldResource”类实际上是 MySQL 固有版本的包装器,并非所有的平台均支持它。编写本文时,对运行在 i386 架构上的 Linux 进行了测试,看上去工作良好,就像在 OS X v10.3 上一样。在 Windows 和 Solaris 平台上进行了有限测试。

要求:

1.    JDK-1.4 或更高版本 (或 JRE,如果不打算编译源文件或 JSP 的话)。

2.    通过 CLASSPATH 安装了并提供了 MySQL Connector/J 版本 3.1 或更高版本 (http://dev.mysql.com/downloads/connector/j/ )。

3.    用于 JMX 版本 1.2.1 的javax.management类,它们位于下述应用服务器上:

·         JBoss - 4.0rc1 或更高版本

·         Apache Tomcat - 5.0 或更高版本

·         Sun 公司的 JMX 参考实施版本 1.2.1,http://java.sun.com/products/JavaManagement/

4.      Junit 3.8.1(http://www.junit.org/)

如果从源码创建,除了上述所有要求外,还须满足:

1.      Ant 版本 1.5 或更高版本 (可从http://ant.apache.org/上下载)。

26.4.4. ;运行 Junit 测试

1.    这类测试将尝试在 3336 端口上启动 MySQL。如果有正在运行的 MySQL,可能会出现冲突,但可能性不大,原因在于 MySQL 的默认端口是 3306。然而,也可以将“c-mxj_test_port”Java 属性设置为你所选择的端口。作为可选方式,你也可以通过关闭运行在目标机器上的 MySQL 实例来启动测试。

默认情况下,测试结果将输出到控制台。要想获得详细输出,可以将“c-mxj_test_silent”Java 属性设置为“假”。

2.    要想运行 Junit 测试套件,$ CLASSPATH 必须包含下述部分:

·         JUnit

·         JMX

·         Connector/J

·         MySQL Connector/MXJ

3.    如果你下载的文件中不含connector-mxj.jar,请解包 MySQL Connector/MXJ 源码档案文件。

4.           cd mysqldjmx
5.           ant dist
     

随后,将$TEMP/cmxj/stage/connector-mxj/connector-mxj.jar 添加到CLASSPATH(类路径)。

6.    如果有junit,执行单元测试。从命令行上输入:

7.           java junit.textui.TestRunner com.mysql.management.AllTestsSuite
    

输出与下面给出的类似:

.........................................
.........................................
..........
Time: 259.438
 
OK (101 tests)
  

注意,在快结束时速度会变慢,请耐心等候。

26.4.5. ;作为 JDBC 驱动程序的一部分运行

MySQL Connector/J JDBC 驱动程序的 1 个特点是,能够在 JDBC 连接字符串中将“SocketFactory”指定为参数。MySQL Connector/MXJ 包含 1 个定制的 SocketFactory。首次连接时,SocketFactory 将部署并启动 MySQL 数据库。SocketFactory 也会显示 1 个“shutdown”方法。

要想使用它,请在 JDBC 连接字符串上指定“socketFactory”参数,并将其值设为“com.mysql.management.driverlaunched.ServerLauncherSocketFactory”。

在下面的示例中,有 1 个能创建连接的程序,执行查询,并将结果输出到 System.out。MySQL 数据库将作为连接进程的组成部分予以部署并启动,最后是结束部分。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import com.mysql.management.driverlaunched.ServerLauncherSocketFactory;

public class ConnectorMXJTestExample {
    public static void main(String[] args) throws Exception {
        String hostColonPort = "localhost:3336";

        String driver = com.mysql.jdbc.Driver.class.getName();
        String url = "jdbc:mysql://" + hostColonPort + "/" + "?"
                + "socketFactory="
                + ServerLauncherSocketFactory.class.getName();
        String userName = "root";
        String password = "";

        Class.forName(driver);
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, userName, password);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT VERSION()");
            rs.next();
            String version = rs.getString(1);
            rs.close();
            stmt.close();

            System.out.println("------------------------");
            System.out.println(version);
            System.out.println("------------------------");
        } finally {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            ServerLauncherSocketFactory.shutdown(hostColonPort);
        }
    }
}
  

要想运行上述程序,在 CLASSPATH 中必须有 connector-mxj.jar 和 Connector/J。然后键入:

java ConnectorMXJTestExample
  

当然,对于 MySQL 数据库,有很多可设置的选项。通过为每个服务器选项冠以前缀“server”,可将其作为 JDBC 连接字符串的部分,简单地指定这些选项。在下述示例中,我们设置了 3 个驱动程序参数和 2 个服务器参数:

        String url = "jdbc:mysql://" + hostColonPort + "/"
                + "?"
                + "socketFactory="
                + ServerLauncherSocketFactory.class.getName();
                + "&"
                + "cacheServerConfiguration=true"
                + "&"
                + "useLocalSessionState=true"
                + "&"
                + "server.basedir=/opt/myapp/db"
                + "&"
                + "server.datadir=/mnt/bigdisk/myapp/data";
  

26.4.6. ;在 Java 对象中运行

有 1 个 java 应用程序并打算嵌入 MySQL 数据库,直接使用 com.mysql.management.MysqldResource 类。可以使用默认的构造函数 (无参量) 例示该类,或者通过在 java.io.File 对象 (代表希望服务器解包至的目录) 中传递类来例示之。也可用针对“stdout”和“stderr”(用于记录) 的输出流例示它。

一旦完成例示,java.util.Map,该对象将能提供与平台以及希望使用的 MySQL 版本相适应的服务器选项的 java.util.Map。

MysqldResource 允许你使用所提供的服务器选项的 java.util.Map 启动 MySQL,并允许你关闭数据库。在下面的示例中,给出了使用明码 java 对象将 MySQL 嵌入到应用程序的简单方法。

import com.mysql.management.MysqldResource;

 ...

    public void startMySQL() {
        File baseDir = new File(ourAppDir, "mysql");
        mysqldResource = new MysqldResource(baseDir);
        Map options = new HashMap();
        options.put("port", "3336");
        String threadName = "OurApp MySQL";
        mysqldResource.start(threadName, options);
    }

    public void stopMySQL() {
        if (mysqldResource != null) {
            mysqldResource.shutdown();
        }
        mysqldResource = null;
    }

    public java.sql.Connection getConnection() throws Exception {
        String db = "test";
        String url = "jdbc:mysql://localhost:3336/" + db;
        String userName = "root";
        String password = "";
        Class.forName(com.mysql.jdbc.Driver.class.getName());
        return DriverManager.getConnection(url, userName, password);
    }
  

26.4.7. MysqldResource API

构造函数:

·         public MysqldResource(File baseDir, PrintStream out, PrintStream err);

允许设置安装 MySQL 文件的“basedir”,并设置标准输出和标准错误的输出流。

·         public MysqldResource(File baseDir);

允许设置安装 MySQL 文件的“basedir”。标准输出和标准错误的输出将被导至 System.out 和 System.err。

·         public MysqldResource();

Basedir 是 java.io.tempdir 的默认子目录。标准输出和标准错误的输出将被导至 System.out 和 System.err。

MysqldResource API 包含下述方法:

·         void start(String threadName, Map mysqldArgs);

部署并启动 MySQL。“threadName”字符串用于命名实际执行 MySQL 命令行命令的线程。“map”是将要传递给命令行的参量和参联值的集合。

·         void shutdown();

关闭由 MysqldResource 对象管理的 MySQL 实例。

·         Map getServerOptions();

返回所有选项以及 MySQL 数据库可用的当前选项 (或默认选项,如果未运行的话) 的映射。

·         boolean isRunning();

如果 MySQL 数据库正在运行,返回“真”。

·         boolean isReadyForConnections();

一旦数据库通报它已做好连接准备,返回“真”。

·         void setKillDelay(int millis);

默认的“Kill Delay”是 30 秒。它表示发出初始关闭请求和发出“强制杀死”(如果数据库未关闭) 命令之间需要等待的时间。

·         void addCompletionListenser(Runnable listener);

当服务器进程完成时,允许通知应用程序。每个“listener”(监听程序) 将在自己的线程中发出。

·         String getVersion();

返回 MySQL 的版本。

·         void setVersion(int MajorVersion, int minorVersion, int patchLevel);

标准分发版本仅提供了 1 种版本的 MySQL 软件包。但也能将多个版本封装在一起,并指定要使用的版本。

26.4.8. ;在 JMX 代理 (custom) 中运行

如果你正在使用 JMX 的 SUN 参考实施版本,可跳过本节。或者,如果你正在部署 Jboss,请跳到下一节。

我们希望在 JMX 代理的活动中看到 MysqldDynamicMBean。在com.mysql.management.jmx.sunri软件包中,它是带有 2 个 Mbeans 的 JMX 代理:

1.      MysqldDynamicMBean,以及

2.    com.sun.jdmk.comm.HtmlAdaptorServer,它提供了用于操控 JMX 代理内众多元素的 Web 接口。

启动了这个十分简单的代理程序后,允许用 Web 浏览器启动并停止 MySQL 数据库。

1.    如前所述,完成平台测试。

·         当前 JDK, JUnit, Connector/J, MySQL Connector/MXJ

·         本节需要 JMX 的 SUN 参考实施版本

·         PATH, JAVA_HOME, ANT_HOME, CLASSPATH

2.      如果不是从源码创建的,跳到下一步。

rebuild with the "sunri.present"

ant -Dsunri.present=true dist 
re-run tests:
java junit.textui.TestRunner com.mysql.management.AllTestsSuite

3.    从命令行启动测试代理:

4.    java com.mysql.management.jmx.sunri.MysqldTestAgentSunHtmlAdaptor &
     

5.    从浏览器:

6.           http://localhost:9092/
     

7.      在 MysqldAgent 下

8.             选择“name=mysqld”
     

9.      观察 Mbean 视图

10.  滚动到屏幕底部,按startMysqld按钮

11.  点击“Back to MBean View”(返回 Mbean 视图)

12.  滚动到屏幕底部,按stopMysqld按钮

13.  杀死运行测试代理的 Java 进程 (jmx 服务器)

26.4.9. ;部署在标准的 JMX 代理环境下 (JBoss)

一旦确定 Mbean 能够在平台上工作,接下来应在标准的 JMX 代理内部署 Mbean。其中包含部署到 Jboss 的说明。

1.    确保有最新版本的 java 开发工具箱 (v1.4.x),请参见前面的介绍。

·         确保设置JAVA_HOME(Jboss 要求JAVA_HOME)。

·         确保JAVA_HOME/bin位于PATH中 (不需要设置 CLASSPATH,也不需要以前测试中使用的任何 jar 文件)。

2.      确保安装了 Jboss 的最新版本 (v4.0RC1 或更高)。

3.             http://www.jboss.org/index.html
4.             选择“Downloads”。
5.             选择“jboss-4.0.zip”。
6.             选择 1 个镜像。
7.             unzip ~/dload/jboss-4.0.zip
8.             创建 JBOSS_HOME 环境变量,设置解包目录。
9.             仅对 Unix:
10.       cd $ JBOSS_HOME/bin
11.       chmod +x *.sh

12.connector-mxj.jar 安装 (拷贝) 到 $JBOSS_HOME/server/default/lib

13.mysql-connector-java-3.1.4-beta-bin.jar 安装 (拷贝) 到$ JBOSS_HOME/server/default/lib

14.$JBOSS_HOME/server/default/deploy 下创建 mxjtest.war目录。

15.  index.jsp 安装 (拷贝) 到$ JBOSS_HOME/server/default/deploy/mxjtest.war。

16.$JBOSS_HOME/server/default/deploy 下创建 mysqld-service.xml 文件

17.       <?xml version="1.0" encoding="UTF-8"?>
18.        <server>
19.         <mbean code="com.mysql.management.jmx.jboss.JBossMysqldDynamicMBean"
20.            name="mysql:type=service,name=mysqld">
21.         <attribute name="datadir">/tmp/xxx_data_xxx</attribute>
22.         <attribute name="autostart">true</attribute>
23.         </mbean>
24.        </server>
     

25.启动 jboss:

·         在 Unix 上:$ JBOSS_HOME/bin/run.sh

·         在 Windows 上:%JBOSS_HOME%\bin\run.bat

准备就绪:Jboss 在屏幕上显示大量输出。

26.  当 Jboss 看上去停止将信息输出到屏幕上时,打开 Web 浏览器:http://localhost:8080/jmx-console

27.滚动到mysql 部分页面底部,选择bulleted mysqld 链接。

28.观察 JMX MBean View 页面。MySQL 应已运行。

29.  (如果设置了“autostart=true”可跳过该步)。滚动到屏幕底部。按Invoke按钮停止 (或启动)MySQL,观察已成功完成而且无返回值的操作。点击“Back to MBean View”(返回 Mbean 视图)

30.  要想确定 MySQL 是否正在运行,打开 Web 浏览器http://localhost:8080/mxjtest/,应看到:

SELECT 1

returned with a result of

1

31.按照$JBOSS_HOME/server/default/deploy/mxjtest.war/index.jsp 中的介绍,能够在你的 Web 应用程序中使用 MySQL。其中提供了供测试用的测试数据库和根用户 (无密码)。创建表,插入一些行,并进行一些选择。

32.  关闭 MySQL。停止 Jboss 时,MySQL 将自动停止,或:在浏览器中,滚动到 MBean View 底部,并按停止服务Invoke 按钮中止服务。观察已成功完成而且无返回值的操作。使用ps或任务管理器查看 MySQL 是否已不再运行。

对于 1.0.6-beta 版,能够在启动时让 Mbean 启动 MySQL 数据库。此外,我们还借鉴了 Jboss 生命周期扩展方法的优点,关闭 Jboss 时能优雅地关闭数据库。

26.4.10. ;安装

如果阅读了上述部分,应已完成了这些步骤。但我们在下面列出了它们,以供快速参考。

启动了驱动程序:

1.      下载并解包 Connector/MXJ,将 connector-mxj.jar 添加到 CLASSPATH。

2.    为 JDBC 连接字符串添加下述参数:"socketFactory=" + ServerLauncherSocketFactory.class.getName()

JBoss:

1.    下载 Connector/MXJ,将connector-mxj.jar文件拷贝到目录$ JBOSS_HOME/server/default/lib

2.    下载 Connector/J,将connector-mxj.jar文件拷贝到目录$JBOSS_HOME/server/default/lib

3.    有任意属性设置在$ JBOSS_HOME/server/default/deploy 目录下创建Mbean 服务 xml 文件,例如datadirautostart

4.      设置 Web 应用程序的 JDBC 参数,以使用:String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql:///test?propertiesTransform="+ "com.mysql.management.jmx.ConnectorMXJPropertiesTransform"; String user = "root"; String password = ""; Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password);

你或许希望为每个应用程序创建单独用户和数据库表空间,而不是使用根用户和测试数据库。

强烈建议定期备份,将数据库文件备份到 datadir 目录下。


这是 MySQL 参考手册的翻译版本,关于 MySQL 参考手册,请访问dev.mysql.com。原始参考手册为英文版,与英文版参考手册相比,本翻译版可能不是最新的。