不幸的是,不同数据库产品所支持的 SQL 类型之间有很大的不同。即使不同的数据库以相同的语义支持 SQL 类型,它们也可能用不同的名称。例如,绝大多数的主流数据库都支持一种表示大型二进制值的 SQL 类型,但 Oracle 把这种类型叫做 LONG RAW
,Sybase 把它叫做 IMAGE
,Informix 却把它叫做 BYTE
,而 DB2 又把它叫做 LONG VARCHAR FOR BIT DATA
。
幸运的是,JDBC 程序员通常并不需要自己去关心目标数据库所用的实际 SQL 类型的名称。大多数时候,JDBC 程序员将根据一些现有的数据库表来进行编程。他们无须关心用于创建这些表的确切 SQL 类型的名称。
JDBC 在 java.sql.Types
类中定义了一系列的常规 SQL 类型标识符。这些类型可用于表示那些最为常用的 SQL 类型。在用 JDBC API 编程时,程序员通常可以使用这些 JDBC 类型来引用一般的 SQL 类型,而无须关心目标数据库所用的确切 SQL 类型的名称。
如果想要编写一种可在各种数据库上创建表的可移植 JDBC 程序,用户主要有两个选择。第一个选择是:限制自己只使用那些被广为接受的 SQL 类型名称(例如 INTEGER
、NUMERIC
或VARCHAR
)。这些类型有可能能适应所有的数据库。第二个选择是:用 java.sql.DatabaseMetaData.getTypeInfo
方法来找出给定的数据库实际上支持哪些 SQL 类型,然后选择与给定 JDBC 类型相匹配的特定于数据库的 SQL 类型名。
JDBC 类型 CHAR
、VARCHAR
和 LONGVARCHAR
密切相关。CHAR
表示固定长度的小字符串,VARCHAR
表示长度可变的小字符串,而 LONGVARCHAR
表示长度可变的大字符串。
与 JDBC CHAR
对应的是 SQL CHAR
类型,其定义由 SQL-92 给出,且所有主要的数据库都支持它。它接受用于指定字符串最大长度的参数,例如 CHAR(12)
即定义了一个长度为 12 个字符的字符串。所有主要的数据库都支持长度达 254 个字符的 CHAR
。
与 JDBC VARCHAR
对应的是 SQL VARCHAR
类型,其定义由 SQL-92 给出,且所有的主要数据库都支持它。它接受用于指定字符串最大长度的参数,例如 VARCHAR(12)
即定义了一个最大长度为 12 个字符的字符串。所有主要数据库都至少支持长度达 254 个字符的 VARCHAR
。当把字符串的值赋给 VARCHAR
变量时,数据库就记住该字符串的长度,使用 SELECT 时,它可以
返回准确的原始字符串。
不幸的是,对于 JDBC LONGVARCHAR
类型,目前并没有一致的 SQL 映射。所有主要数据库都支持某种类型的长度可变的大字符串,这种字符串支持高达十亿位字节的数据,但 SQL 类型名称却变化多样。
Java 程序员不必区分 CHAR
、VARCHAR
和 LONGVARCHAR
这三种类型的 JDBC 字符串。它们都可表示为 Java String
,并且在不知道所需要的确切数据类型时也可正确读写 SQL 语句。
CHAR
、VARCHAR
和 LONGVARCHAR
可映射为 String
或 char[]
,但 String
更适合于一般用法。同时, String
类能使 String
和 char[]
之间的转换更为容易:它有一个用于将 String
对象转换为 char[]
的方法,还有一个将 char[]
转换为 String
对象的构造函数。
JDBC 类型 BIT
代表一个位值,可为 0 或 1。SQL-92 定义了 SQL BIT
类型。但与 JDBC BIT
类型不同,这种 SQL-92 BIT 类型带参数,用于定义固定长度的二进制字符串。幸运的是,SQL-92 也允许用简单的非参数化的 BIT
类型来代表单个的二进制数字。这种用法对应于 JDBC BIT
类型。不幸的是,SQL-92 BIT
类型只有在 “完全” SQL-92 中才要求,且目前只有一部份主流数据库支持它。因此,可移植的代码也许宁愿用 JDBC SMALLINT
类型,这种类型已得到广泛支持。
JDBC 类型 TINYINT
代表一个 8 位无符号整数,其值在 0 到 255 之间。
对应的 SQL 类型 TINYINT
目前只有一部份的数据库支持它。因此,可移植的代码也许宁愿用 JDBC SMALLINT
类型,这种类型已得到广泛支持。
JDBC TINYINT
类型的 Java 映射的推荐类型是 Java byte
或 Java short
。8 位的 Java byte
类型代表一个有符号的整数,其值在 -128 到 127 之间,因此对于大的 TINYINT
值它并非总合适,而 16 位的 Java short
类型却总能存储所有的 TINYINT
值。
JDBC 类型 SMALLINT
代表一个 16 位的有符号整数,其值在 -32768 和 32767 之间。
对应的 SQL 类型 SMALLINT
,其定义由 SQL- 92 给出,并为所有主流数据库所支持。SQL-92 标准将 SMALLINT
的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 16 位。
JDBC SMALLINT
类型的 Java 映射的推荐类型是 Java short
类型。
JDBC 类型 INTEGER
代表一个 32 位的有符号整数,其值在 - 2147483648 和 2147483647 之间。
对应的 SQL 类型 INTEGER
,其定义由 SQL- 92 给出,并为所有主流数据库所广为支持。SQL-92 标准将 INTEGER
的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 32 位。
INTEGER
类型 Java 映射的推荐类型是 Java int
类型。
JDBC 类型 BIGINT
代表一个 64 位的有符号整数,其值在 -9223372036854775808 和 9223372036854775807 之间。
对应的 SQL 类型 BIGINT
是 SQL 的一个非标准扩展。事实上,目前还没有任何数据库实现 SQL BIGINT
类型。我们建议在可移植的代码中避免使用该类型。
BIGINT
类型的 Java 映射的推荐类型是 Java long 类型。
JDBC 类型 REAL
代表一个有 7 位尾数的“单精度”浮点数。
对应的 SQL 类型 REAL
,其定义由 SQL- 92 给出。虽然未得到普遍支持,但在主流数据库中却已得到广泛支持。SQL-92 标准将 REAL
的精度留给实现去决定。但事实上,所有的支持 REAL
类型的主流数据库都支持至少 7 位数的尾数精度。
REAL
类型的 Java 映射的推荐类型为 Java float
类型。
JDBC 类型 DOUBLE
代表一个有 15 位尾数的“双精度”浮点数。
对应的 SQL 类型是 DOUBLE
PRECISION
,其定义由 SQL- 92 给出,并为主流数据库所广为支持。SQL-92 标准将 DOUBLE
PRECISION
的精度留给实现去决定。但事实上,所有支持 DOUBLE
PRECISION
类型的主流数据库都支持至少 15 位数的尾数精度。
DOUBLE
类型的 Java 映射的推荐类型为 Java double
类型。
JDBC 类型 DECIMAL
和 NUMERIC
两者非常相似。它们都表示固定精度的十进制值。
相应的 SQL 类型 DECIMAL
和 NUMERIC
,其定义在 SQL-92 中给出,并得到广泛支持。这些 SQL 类型都带有精度和比例参数。精度是所支持的十进制数字的总位数,比例是小数点后的数字位数。比例必须永远小于或等于精度。例如,值 "12.345" 有 5 位精度和 3 位比例,而值 ".11" 有 2 位精度和 2 位比例。JDBC 要求所有 DECIMAL
和 NUMERIC
类型都必须支持至少 15 位的精度和比例。
DECIMAL
和 NUMERIC
之间的唯一区别是 SQL-92 规范要求 NUMERIC
类型必须以确切指定的精度来表示,而对 DECIMAL
类型,它允许实现在创建该类型时所指定的精度以外再添加额外的精度。因此,创建为类型 NUMERIC(12,4)
的列将总是用 12 位数来表示,而创建为类型 DECIMAL(12,4)
的列则可用更大的位数来表示。
DECIMAL
和 NUMERIC
类型的 Java 映射的推荐类型是 java.math.BigDecimal
,该 Java 类型也用绝对精度来表示定点数。java.math.BigDecimal
类型提供了一些数学操作,可对BigDecimal
类型与其它的 BigDecimal
类型、整数类型和浮点数类型进行加、减、乘、除的运算。
用于检索 DECIMAL
和 NUMERIC
值的推荐方法是 ResultSet.getBigDecimal
。JDBC 还允许将这些 SQL 类型作为简单的 Strings
或 char
数组来访问。因此,Java 程序员可用getString
来检索 DECIMAL
或 NUMERIC
结果。然而,这将使常见的用 DECIMAL
或 NUMERIC
来表示的货币值变得极为尴尬,因为它意味着应用程序编程人员必须对字符串进行数学运算。当然,也可将这些 SQL 类型作为 Java 数值型类型来检索。
有三种 JDBC 类型与时间有关:
- JDBC
DATE
类型表示一个由年、月、日组成的日期。对应的是 SQLDATE
类型,其定义由 SQL-92 给出,但只有一部份主流数据库实现它。某些数据库提供了另外一些支持类似语义的 SQL 类型。 - JDBC
TIME
类型表示一个由小时、分钟和秒组成的时间。对应的是 SQLTIME
类型,其定义由 SQL-92 给出,但只有一部份主流数据库实现它。与DATE
一样,某些数据库提供了另外一些支持类似语义的 SQL 类型。 - JDBC
TIMESTAMP
类型表示DATE
加上TIME
,外加一个纳秒域。对应的TIMESTAMP
类型,其定义由 SQL-92 给出,但只有少数几个数据库实现它。
由于标准的 Java 类 java.util.Date
并不与这三个 JDBC 日期—时间类型完全匹配(它含有 DATE
和 TIME
的信息但不含纳秒信息),因此 JDBC 定义了三个 java.util.Date
的子类与 SQL 类型对应。它们是:
java.sql.Date
,对应于 SQLDATE
信息。java.util.Date
基本类中的小时、分钟和秒都设为 0。java.sql.Time
,对应于 SQLTIME
信息。java.util.Date
基本类中的年、月、日域设为 1970 年 1 月 1 日。这是 Java 纪元的“零”日期。java.sql.Timestamp
,对应于 SQLTIMESTAMP
信息。该类扩展了java.util.Date
,添加了纳秒域。
所有这三个与时间有关的 JDBC 类都是 java.util.Date
的子类,因此它们可用在任何可以使用 java.util.Date
的地方。例如,国际化 (internationalization) 方法将 java.util.Date
对象用作变量,因此可将这三个与时间有关的 JDBC 类中任何一个的实例作为参数传给国际化方法。
JDBC Timestamp
对象除了具有其父类的日期和时间成份外,还有一个独立的纳秒组件。如果将 java.sql.Timestamp
对象用于需要 java.util.Date
对象的地方,则纳秒组件将丢失。但由于是以毫秒的精度来储存 java.util.Date
对象的,因此将 java.sql.Timestamp
对象转换为 java.util.Date
对象时可以保持这样的精度。这可通过将纳秒组件中的纳秒转换为毫秒(用纳秒数除以 1,000,000)并将之添到 java.util.Date
对象中来实现。转换中可能丢失高达 999,999 纳秒,但所产生的 java.util.Date
对象将可精确到毫秒以内。
下述代码段将 java.sql.Timestamp
对象转换为精度达到毫秒量级的 java.util.Date
对象:
Timestamp t = new Timestamp(100, 0, 1, 15, 45, 29, 987245732);
java.util.Date d;
d = new java.util.Date(t.getTime() + (t.getNanos() / 1000000));
最后欢迎大家访问我的个人网站:1024s