精华内容
下载资源
问答
  • java.sql.Types,数据库字段类型,java数据类型的对应关系   以下转自:http://kummy.itpub.net/post/17165/172850 本文在原文基础上有增减。 本概述是从《 JDBC TM  Database Access from Java TM : A ...
    原文地址为:
    java.sql.Types,数据库字段类型,java数据类型的对应关系
    

     

    以下转自:http://kummy.itpub.net/post/17165/172850 本文在原文基础上有增减。


    本概述是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference》这本书中摘引来的。JavaSoft 目前正在准备这本书。这本书是一本教程,同时也是 JDBC 的重要参考手册,它将作为 Java 系列的组成部份,在 1997 年春季由 Addison-Wesley 出版公司出版。

    8.1 概述

    由于 SQL 数据类型和 Java 数据类型是不同的,因此需要某种机制在使用 Java 类型的应用程序和使用 SQL 类型的数据库之间来读写数据。

    为此,JDBC 提供了 getXXX 和 setXXX 方法集、方法 registerOutParameter 和类 Types

    本章汇集了影响各种类和接口的数据类型的有关信息,并列出所有的对应关系表(这些表显示了 SQL 类型和 Java 类型之间的映射关系)以便于参考。

    8.2 将 SQL 数据类型映射为 Java 类型

    不幸的是,不同数据库产品所支持的 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 类型名称的主要地方是在用 SQL 的 CREATE TABLE 语句创建新的数据库表时。这种情况下,程序员必须注意应该使用目标数据库所支持的 SQL 类型名称。如果需要知道各种 SQL 类型在某个特定的数据库中的行为的确切定义,我们建议查阅一下数据库文档。

    如果想要编写一种可在各种数据库上创建表的可移植 JDBC 程序,用户主要有两个选择。第一个选择是:限制自己只使用那些被广为接受的 SQL 类型名称(例如 INTEGERNUMERIC 或VARCHAR)。这些类型有可能能适应所有的数据库。第二个选择是:用 java.sql.DatabaseMetaData.getTypeInfo 方法来找出给定的数据库实际上支持哪些 SQL 类型,然后选择与给定 JDBC 类型相匹配的特定于数据库的 SQL 类型名。

    JDBC 定义了一个从 JDBC 数据库类型到 Java 类型的标准映射。例如,JDBC 的 INTEGER 类型通常映射为 Java 的 int 类型。这可支持简单的接口,将 JDBC 值读写为简单的 Java 类型。

    Java 类型不必与 JDBC 类型完全形同;它们只须能够用足够的类型信息来代表 JDBC 类型,从而能正确地存储和取出参数和从 SQL 语句恢复结果就可以了。例如,Java String 对象可能并不能精确地与任何 JDBC CHAR 类型匹配,但它却可给出足够的类型信息来成功地表示 CHAR、 VARCHAR 或 LONGVARCHAR 类型。

    8.3 JDBC 类型

    本节描述各种 JDBC 数据类型及其与标准 SQL 类型和 Java 类型的关联方式。

    8.3.1 CHAR、 VARCHAR 和 LONGVARCHAR

    JDBC 类型 CHARVARCHAR 和 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 程序员不必区分 CHARVARCHAR 和 LONGVARCHAR 这三种类型的 JDBC 字符串。它们都可表示为 Java String,并且在不知道所需要的确切数据类型时也可正确读写 SQL 语句。

    CHARVARCHAR 和 LONGVARCHAR 可映射为 String 或 char[],但 String 更适合于一般用法。同时, String 类能使 String 和 char[] 之间的转换更为容易:它有一个用于将 String对象转换为 char[] 的方法,还有一个将 char[] 转换为 String 对象的构造函数。

    必须提及的一个问题是:如何处理类型为 CHAR(n) 的固定长度的 SQL 字符串。答案是 JDBC 驱动程序(或 DBMS)将用适当的空格来进行填补。因此,当从数据库中检索 CHAR(n) 域时,驱动程序将把它转换为长度为 n 的 Java String 对象,对象末尾可能含有一些填补空格。反之,当把 String 对象送到某个 CHAR(n) 域时,驱动程序和/或数据库将在字符串的末尾填上一些必要的空格,使字符串的长度达到 n

    方法 ResultSet.getString 用于分配和返回新的 String 对象。我们建议用它来从 CHARVARCHAR 和LONGVARCHAR 域中检索数据。它适用于检索普通的数据,但如果用 JDBC 类型LONGVARCHAR 来储存多个兆字节的字符串时,用它进行检索将显得十分笨拙。为此,ResultSet 接口中有两个方法可供程序员将 LONGVARCHAR 值作为 Java 输入流进行检索,之后可从该流中以任意大小的块来读取数据。这两个方法是:getAsciiStream 和 getUnicodeStream,它们将把储存在 LONGVARCHAR 列的数据作为 Ascii 或 Unicode 字符流来传送。

    8.3.2 BINARY、VARBINARY 和 LONGVARBINARY

    JDBC 类型 BINARYVARBINARY 和 LONGVARBINARY 密切相关。BINARY 表示固定长度的小二进制值, VARBINARY 表示长度可变化的小二进制值,而 LONGVARBINARY 表示长度可变化的大二进制值。

    不幸的是,这些不同 BINARY 类型的使用还未被标准化,因而在各种主要数据库提供的支持有很大的不同。

    对应于 JDBC BINARY 类型的 SQL BINARY 类型,是一种非标准的 SQL 扩展,只在某些数据库上才实现。它接受用于指定二进制字节数的参数。例如,BINARY(12) 即定义了一个长度为 12 个字节的 binary 类型。通常,BINARY 值被限定在 254 个字节以内。

    对应于 JDBC VARBINARY 类型的 SQL VARBINARY 类型,是一种非标准的 SQL 扩展,只在某些数据库上才实现。它接受用于指定二进制字节最大数的参数。例如,VARBINARY(12) 即定义了一个长度最大可为 12 个字节的二进制类型。通常,VARBINARY 的值被限定在 254 个字节以内。当把二进制的值赋给 VARBINARY 变量时,数据库就记住这个所赋值的长度,调用 SELECT时,它返回准确的原始值。

    遗憾的是,目前还没有一致的 SQL 类型名称与 JDBC LONGVARBINARY 类型相对应。所有主要数据库都支持某种类型的长度可变的大二进制类型,它可支持高达十亿个字节的数据,但 SQL 类型名称却变化多样。

    在 Java 中,BINARYVARBINARY 和 LONGVARBINARY 都可用同一 byte数组来表示。由于可在不知道所需的确切 BINARY 数据类型的情况下正确地读写 SQL 语句,因此,Java 程序员无需区分它们。

    检索 BINARY 和 VARBINARY 值时,我们建议使用 ResultSet.getBytes。然而,如果类型为 JDBC LONGVARBINARY 的某列储存的是几兆字节长度的字节数组,则建议用方法getBinaryStream 来检索。与 LONGVARCHAR 的情形类似,该方法可以使 Java 程序员将 LONGVARBINARY 值作为 Java 输入流检索,然后可从该流中以更小的块来读取。

    8.3.3 BIT

    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 BIT 类型的 Java 映射的推荐类型是 Java 布尔型。

    8.3.4 TINYINT

    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 值。

    8.3.5 SMALLINT

    JDBC 类型 SMALLINT 代表一个 16 位的有符号整数,其值在 -32768 和 32767 之间。

    对应的 SQL 类型 SMALLINT,其定义由 SQL- 92 给出,并为所有主流数据库所支持。SQL-92 标准将 SMALLINT 的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 16 位。

    JDBC SMALLINT 类型的 Java 映射的推荐类型是 Java short 类型。

    8.3.6 INTEGER

    JDBC 类型 INTEGER 代表一个 32 位的有符号整数,其值在 - 2147483648 和 2147483647 之间。

    对应的 SQL 类型 INTEGER,其定义由 SQL- 92 给出,并为所有主流数据库所广为支持。SQL-92 标准将 INTEGER 的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 32 位。

    INTEGER 类型 Java 映射的推荐类型是 Java int 类型。

    8.3.7 BIGINT

    JDBC 类型 BIGINT 代表一个 64 位的有符号整数,其值在 -9223372036854775808 和 9223372036854775807 之间。

    对应的 SQL 类型 BIGINT 是 SQL 的一个非标准扩展。事实上,目前还没有任何数据库实现 SQL BIGINT 类型。我们建议在可移植的代码中避免使用该类型。

    BIGINT 类型的 Java 映射的推荐类型是 Java long 类型。

    8.3.8 REAL

    JDBC 类型 REAL 代表一个有 7 位尾数的“单精度”浮点数。

    对应的 SQL 类型 REAL,其定义由 SQL- 92 给出。虽然未得到普遍支持,但在主流数据库中却已得到广泛支持。SQL-92 标准将 REAL 的精度留给实现去决定。但事实上,所有的支持 REAL类型的主流数据库都支持至少 7 位数的尾数精度。

    REAL 类型的 Java 映射的推荐类型为 Java float 类型。

    8.3.9 DOUBLE

    JDBC 类型 DOUBLE 代表一个有 15 位尾数的“双精度”浮点数。

    对应的 SQL 类型是 DOUBLE PRECISION,其定义由 SQL- 92 给出,并为主流数据库所广为支持。SQL-92 标准将 DOUBLE PRECISION 的精度留给实现去决定。但事实上,所有支持 DOUBLEPRECISION 类型的主流数据库都支持至少 15 位数的尾数精度。

    DOUBLE 类型的 Java 映射的推荐类型为 Java double 类型。

    8.3.10 FLOAT

    JDBC 类型 FLOAT 基本上与 JDBC 类型 DOUBLE 相同。我们同时提供了 FLOAT 和 DOUBLE,其目的是与以前的 API 实现一致。但这却有可能产生误导。FLOAT 代表一个有 15 位尾数的“双精度”浮点数。

    对应的 SQL 类型 FLOAT,其定义由 SQL-92 给出。SQL-92 标准将 FLOAT 的精度留给实现去决定。但事实上,所有支持 FLOAT 类型的主流数据库都支持至少 15 位数的尾数精度。

    FLOAT 类型的 Java 映射的推荐类型为 Java double 类型。然而,由于 SQL FLOAT 和单精度的 Java float类型间可能产生混淆,因此建议 JDBC 程序员通常选用 JDBC DOUBLE 类型而不选用 FLOAT

    8.3.11 DECIMAL 和 NUMERIC

    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 数值型类型来检索。

    8.3.12 DATE、TIME 和 TIMESTAMP

    有三种 JDBC 类型与时间有关:

    • JDBC DATE 类型表示一个由年、月、日组成的日期。对应的是 SQL DATE 类型,其定义由 SQL-92 给出,但只有一部份主流数据库实现它。某些数据库提供了另外一些支持类似语义的 SQL 类型。
    • JDBC TIME 类型表示一个由小时、分钟和秒组成的时间。对应的是 SQL TIME 类型,其定义由 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,对应于 SQL DATE 信息。java.util.Date 基本类中的小时、分钟和秒都设为 0。
    • java.sql.Time,对应于 SQL TIME 信息。java.util.Date 基本类中的年、月、日域设为 1970 年 1 月 1 日。这是 Java 纪元的“零”日期。
    • java.sql.Timestamp,对应于 SQL TIMESTAMP 信息。该类扩展了 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));

    8.4 映射示例

    任何情况下,当 Java 程序要从数据库中检索数据时,必须存在某种形式的映射和数据转换。大多数时候, JDBC 程序员将在知道其目标数据库机制的情况下进行编程。例如,他们将知道数据库含有哪些表、表中每一列的数据类型。因此,他们可使用 ResultSet、 PreparedStatement和 CallableStatement 接口中那些与类型有关的存取方法。本节给出三个示例,描述各种情形中所要求的数据映射和转换。

    8.4.1 简单的 SQL 语句

    在最常见的情形中,用户将执行简单的 SQL 语句,然后取回含有结果的 ResultSet 对象。由数据库返回并存放在 ResultSet 列的值,其类型为 JDBC 数据类型。调用ResultSet.getXXX 方法将把该值检索为 Java 数据类型。例如,如果某个 ResultSet 列含有一个 JDBC FLOAT 值,则方法 getDouble 将把它检索为 Java double 类型。8.6.6 节所示的表显示了哪些 getXXX 方法可检索哪些 JDBC 类型(如果用户不知道某个 ResultSet 列的类型,可通过调用 ResultSet.getMetaData 方法来获得有关信息,然后再调用ResultSetMetaData 的 getColumnType 或 getColumnTypeName 方法)。以下代码段示范了如何获得结果中各列的类型名称:

        String query = "select * from Table1";
    ResultSet rs = stmt.executeQuery(query);
    ResultSetMetaData rsmd = rs.getMetaData();
    int columnCount = rsmd.getColumnCount();
    for (int i = 1; i <= columnCount; i++) {
    String s = rsmd.getColumnTypeName(i);
    System.out.println ("Column " + i + " is type " + s);
    }

    8.4.2 带 IN 参数的 SQL 语句

    在另一个可能的情况中,用户将发送带输入参数的 SQL 语句。这种情况下,用户通过调用 PreparedStatement.setXXX 方法为每个输入参数赋值。例如,PreparedStatement.setLong(1, 2345678) 将把值 2345678 作为 Java 的 long 类型赋给第一个参数。为了将 2345678 到数据库中,驱动程序将把它转换为 JDBC BIGINT。驱动程序将把哪种 JDBC 类型送到数据库中是由 Java 类型到 JDBC 类型的标准映射所决定的

    8.4.3 带 OUT 参数的 SQL 语句

    还有一个情况是,用户要调用已存储过程,将值赋给其 INOUT 参数,从结果中检索值,然后从参数中检索值。这种情形极为少见且相当复杂,但它却不失为映射和数据转换的好范例。

    这种情况下,首先要做的是用 PreparedStatement.setXXX 方法对 INOUT 参数赋值。此外,由于这些参数同时也用于输出,因此程序员必须为每个参数注册 JDBC 类型,该类型是数据库所要返回给该参数的值的 JDBC 类型。这可用 CallableStatement.registerOutParameter 方法来完成,后者接受在类 Types 中所定义的 JDBC 类型作为其变量。程序员可以用ResultSet.getXXX 方法系列来检索返回给ResultSet 对象的结果,用 CallableStatement.getXXX 方法系列来检索存放在输出参数中的值。

    用于 ResultSet.getXXX 方法的 XXX 类型在某些情况下非常灵活。8.6.6 节中所示的表显示了哪些 ResultSet.getXXX 方法可用于检索哪些 JDBC 类型。

    用于 CallableStatement.getXXX 方法的 XXX 类型必须映射为那个参数所注册的 JDBC 类型。例如,如果数据库应返回类型为 JDBC REAL 的输出值,则该参数应被注册为java.sql.Types.REAL。因此,要检索该 JDBC REAL 值,必须调用 CallableStatement.getFloat 方法(从 JDBC 类型到 Java 类型的映射在 8.6.1 节中的表中给出)。方法 getFloat先把储存在输出参数中的值从 JDBC REAL 类型转换为 Java float 类型,然后将它返回。为了适应各种数据库和使应用程序具有更高的可移植性,建议先检索 ResultSet 对象中的值,再检索输出参数中的值。

    下述代码示范的是调用名为 getTestData 的已存储过程。它有两个参数,且都是 INOUT 参数。首先, Connection 对象 con 将创建 CallableStatement 对象 cstmt。然后,方法setByte 把第一个参数设置为 Java byte 类型,其值为 25。驱动程序将把 25 转换为 JDBC TINYINT 类型并将之送到数据库中。方法 setBigDecimal 用输入值 83.75 来设置第二个参数。驱动程序将把这个 java.math.BigDecimal 对象转换为 JDBC NUMERIC 值。接下来将这两个参数注册为 OUT 参数,第一个参数注册为 JDBC TINYINT 类型,第二个参数注册为小数点后面带两位数字的 JDBC DECIMAL 类型。执行 cstmt 后,就用 ResultSet.getXXX 方法将值从 ResultSet 对象中检索出来。方法 getString 将第一列中的值作为 Java String 对象获取,getInt 将第二列中的值作为 Java int 获取,getInt 将第三列中的值作为 Java int 获取。

    之后, CallableStatement.getXXX 方法检索存放在输出参数中的值。方法 getByte 将 JDBC TINYINT 检索为 Java bytegetBigDecimal 将 JDBC DECIMAL 检索为小数点后面带有两位数字的 java.math.BigDecimal 对象。注意,当参数既是输入参数同时又是输出参数时,setXXX 方法所用的 Java 类型与 getXXX 方法所用的相同(正如 setByte 和 getByte 中一样)。registerOutParameter 方法将它注册成由 Java 类型映射来的 JDBC 类型(Java byte 类型映射为 JDBC TINYINT,如 8.6.2 节中的表所示)。

        CallableStatement cstmt = con.prepareCall(
    "{call getTestData(?, ?)}");
    cstmt.setByte(1, 25);
    cstmt.setBigDecimal(2, 83.75);
    // 将第一个参数注册为 JDBC TINYINT,第二个
    // 参数注册为小数点后面带有两位数字的 JDBC DECIMAL 类型
    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
    cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 2);
    ResultSet rs = cstmt.executeUpdate();
    // 检索并打印结果中的值。
    while(rs.next()) {
    String name = rs.getString(1);
    int score = rs.getInt(2);
    int percentile = rs.getInt(3);
    System.out.print("name = " + name + ", score = " + score + ", "
    System.out.println("percentile = " + percentile);
    // 检索输出参数中的值
    byte x = cstmt.getByte(1);
    java.math.BigDecimal n = cstmt.getBigDecimal(2, 2);

    总之,CallableStatement.getXXX 和 PreparedStatement.setXXX 方法系列中的 XXX 是 Java 类型。对于 setXXX 方法,驱动程序先把 Java 类型转换为 JDBC 类型,再把它送到数据库中(使用 8.6.2 节中的表所示的标准映射)。对于 getXXX 方法, 驱动程序先把数据库返回的 JDBC 类型转换为 Java 类型(用 8.6.1 节表中所示的标准映射),再把它返回给 getXXX 方法。

    registerOutParameter 方法只接受 JDBC 类型的变量,而 setObject 方法却可接受 JDBC 类型的变量。

    注意,如果在可选的第三个变量的位置上提供了 JDBC 类型,则 setObject 方法将把参数值从 Java 类型显式地转换为所指定的 JDBC 类型。如果没有为 setObject 提供目标 JDBC 类型,则将把参数值转换为 Java 类型的标准映射 JDBC 类型(如 8.6.2 节的表中所示)。在将参数送到数据库中之前,驱动程序都要进行显式或隐式转换。

    8.5 动态数据存取

    大多数时候,用户要存取的结果和参数其数据类型在编译时是已知的。然而,有些应用程序(例如普通的浏览器或查询工具)在编译时对它们所要存取的数据库的机制并不知晓。因此,JDBC 除了支持静态数据类型存取外,还支持类型完全动态确定的数据存取。

    有三种方法和一个常量可用于访问那些在编译时其数据类型尚属未知的值:

    • ResultSet.getObject 
    • PreparedStatement.setObject 
    • CallableStatement.getObject 
    • java.sql.Types.OTHER (用作 CallableStatement.registerOutParameter 的一个变量)  

    例如,如果应用程序想要接受多种类型作为其 ResultSet 对象中的结果,它可以使用 ResultSet.getObject 方法。

    ResultSet.getObject 和 CallableStatement.getObject 方法将值检索为 Java Object。由于 Object 是所有 Java 对象的基本类,因此可将任何 Java 类的实例检索为 Object 的实例。然而,以下 Java 类型是内置的“基本”类型,因此,它们不是类 Object 的实例: booleancharbyteshortintlong、 float 和 double。因此,不能用 getObject 方法来检索它们。然而,这些基本类型每种都有相应的可用作 wrapper 的类。这些类的实例是对象,这意味着可用 ResultSet.getObject 和 CallableStatement.getObject 方法来检索它们。第 67 页中的表 8.6.3 显示了从 JDBC 类型到 Java Object 类型的映射。该表与 JDBC 类型到 Java 类型的标准映射不同:在该表中,除了 JDBC TINYINT 和 JDBC SMALLINT 类型映射为 Java 类Integer 之外,每一个基本的 Java 类型都被替换为它们的 wrapper 类。

    方法 getObject 还可用于检索用户定义的 Java 类型。随着抽象数据类型(ADT)和其它用户定义的类型在某些数据库系统中的出现,一些提供者可能会发现用 getObject 来检索这些类型将更方便。

    8.6 数据类型映射表

    本节含有以下表,它们是 JDBC 类型 和 Java 数据类型之间的映射关系表:

    8.6.1 节 — 从 JDBC 类型映射到 Java 类型

    8.6.2 节 — 从 Java 类型映射到 JDBC 类型

    8.6.3 节 ─ 从 JDBC 类型映射到 Java Object 类型

    8.6.4 节 ─ 从 Java Object 类型映射到 JDBC 类型

    8.6.5 节 ─ 由 setObject 所进行的转换

    8.6.6 节 — 由 ResultSet.getXXX 方法所检索的 JDBC 类型

    8.6.1 从 JDBC 类型映射到 Java 类型

    JDBC 类型Java 类型
    CHARString
    VARCHARString
    LONGVARCHARString
    NUMERICjava.math.BigDecimal
    DECIMALjava.math.BigDecimal
    BITboolean
    TINYINTbyte
    SMALLINTshort
    INTEGERint
    BIGINTlong
    REALfloat
    FLOATdouble
    DOUBLEdouble
    BINARYbyte[]
    VARBINARYbyte[]
    LONGVARBINARYbyte[]
    DATEjava.sql.Date
    TIMEjava.sql.Time
    TIMESTAMPjava.sql.Timestamp


     

    8.6.2 从 Java 类型映射到 JDBC 类型

    该表显示的是表 8.6.1 的反映射:Java 类型到 JDBC 类型的映射。

    Java 类型JDBC 类型
    StringVARCHAR 或 LONGVARCHAR
    java.math.BigDecimalNUMERIC
    booleanBIT
    byteTINYINT
    shortSMALLINT
    intINTEGER
    longBIGINT
    floatREAL
    doubleDOUBLE
    byte[]VARBINARY 或 LONGVARBINARY
    java.sql.DateDATE
    java.sql.TimeTIME
    java.sql.TimestampTIMESTAMP


     String 类型的映射通常是 VARCHAR,但如果所给的值超出了驱动程序对 VARCHAR 值所限定的极限,则将转换为 LONGVARCHAR 类型。对 byte[]VARBINARY 及 LONGVARBINARY 值也一样。

    8.6.3 从 JDBC 类型到 Java Object 类型的映射

    由于 Java 内置类型(例如 boolean 和 int)不是 Object 的子类型,因此对于 getObject/setObject 方法,从 JDBC 类型到 Java object 类型的映射稍有不同。此种映射如下表所示:

     

    JDBC 类型Java Object 类型
    CHARString
    VARCHARString
    LONGVARCHARString
    NUMERICjava.math.BigDecimal
    DECIMALjava.math.BigDecimal
    BITBoolean
    TINYINTInteger
    SMALLINTInteger
    INTEGERInteger
    BIGINTLong
    REALFloat
    FLOATDouble
    DOUBLEDouble
    BINARYbyte[]
    VARBINARYbyte[]
    LONGVARBINARYbyte[]
    DATEjava.sql.Date
    TIMEjava.sql.Time
    TIMESTAMPjava.sql.Timestamp


      

    8.6.4 Java Object 类型映射到 JDBC 类型

    Java Object 类型JDBC 类型
    StringVARCHAR 或 LONGVARCHAR
    java.math.BigDecimalNUMERIC
    BooleanBIT
    IntegerINTEGER
    LongBIGINT
    FloatREAL
    DoubleDOUBLE
    byte[]VARBINARY 或 LONGVARBINARY
    java.sql.DateDATE
    java.sql.TimeTIME
    java.sql.TimestampTIMESTAMP


     注意,String 的映射通常为 VARCHAR,但如果所给的值超出了驱动程序对 VARCHAR 值所限定的极限值,则将转换为 LONGVARCHAR。对 byte[]VARBINARY 和 LONGVARBINARY 值也一样。

     

    8.6.5 由 setObject 所进行的转换

    setObject

     

     T
    I
    N
    Y
    I
    N
    T
    S
    M
    A
    L
    L
    I
    N
    T
    I
    N
    T
    E
    G
    E
    R
    B
    I
    G
    I
    N
    T
    R
    E
    A
    L
    F
    L
    O
    A
    T
    D
    O
    U
    B
    L
    E
    D
    E
    C
    I
    M
    A
    L
    N
    U
    M
    E
    R
    I
    C
    B
    I
    T
    C
    H
    A
    R
    V
    A
    R
    C
    H
    A
    R
    L
    O
    N
    G
    V
    A
    R
    C
    H
    A
    R
    B
    I
    N
    A
    R
    Y
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    L
    O
    N
    G
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    D
    A
    T
    E
    T
    I
    M
    E
    T
    I
    M
    E
    S
    T
    A
    M
    P
    Stringxxxxxxxxxxxxxxxxxxx
    java.math.BigDecimalxxxxxxxxxxxxx      
    Booleanxxxxxxxxxxxxx      
    Integerxxxxxxxxxxxxx      
    Longxxxxxxxxxxxxx      
    Floatxxxxxxxxxxxxx      
    Doublexxxxxxxxxxxxx      
    byte[]             xxx   
    java.sql.Date          xxx   x x
    java.sql.Time          xxx    x 
    java.sql.Time- stamp          xxx   xxx


     从 Java object 类型到 JDBC 类型的转换。

     

    8.6.6 由 ResultSet.getXXX 方法检索的 JDBC 类型

    "x" 表示该方法可以检索 JDBC 类型。"X" 表示建议使用该方法来检索该 JDBC 类型。

     

     T
    I
    N
    Y
    I
    N
    T
    S
    M
    A
    L
    L
    I
    N
    T
    I
    N
    T
    E
    G
    E
    R
    B
    I
    G
    I
    N
    T
    R
    E
    A
    L
    F
    L
    O
    A
    T
    D
    O
    U
    B
    L
    E
    D
    E
    C
    I
    M
    A
    L
    N
    U
    M
    E
    R
    I
    C
    B
    I
    T
    C
    H
    A
    R
    V
    A
    R
    C
    H
    A
    R
    L
    O
    N
    G
    V
    A
    R
    C
    H
    A
    R
    B
    I
    N
    A
    R
    Y
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    L
    O
    N
    G
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    D
    A
    T
    E
    T
    I
    M
    E
    T
    I
    M
    E
    S
    T
    A
    M
    P
    getByteXxxxxxxxxxxxx      
    getShortxXxxxxxxxxxxx      
    getIntxxXxxxxxxxxxx      
    getLongxxxXxxxxxxxxx      
    getFloatxxxxXxxxxxxxx      
    getDoublexxxxxXXxxxxxx      
    getBigDecimalxxxxxxxXXxxxx      
    getBooleanxxxxxxxxxXxxx      
    getStringxxxxxxxxxxXXxxxxxxx
    getBytes             XXx   
    getDate          xxx   X x
    getTime          xxx    Xx
    getTimestamp          xxx   x X
    getAsciiStream          xxXxxx   
    getUnicodeStream          xxXxxx   
    getBinaryStream             xxX   
    getObjectxxxxxxxxxxxxxxxxxxx

     

    相关链接

    方法将 Java object 类型转换为 JDBC 类型。8.6.2 节中的表所示。


    转载请注明本文地址: java.sql.Types,数据库字段类型,java数据类型的对应关系
    展开全文
  • 本章汇集了影响各种类和接口的数据类型的有关信息,并列出所有的对应关系表(这些表显示了 SQL 类型和 Java 类型之间的映射关系)以便于参考。 8.2 将 SQL 数据类型映射为 Java 类型 不幸的是 ,不同...

    以下转自:http://kummy.itpub.net/post/17165/172850 本文在原文基础上有增减。


    本概述是从《JDBCTM Database Access from JavaTM: A Tutorial and Annotated Reference》这本书中摘引来的。JavaSoft 目前正在准备这本书。这本书是一本教程,同时也是 JDBC 的重要参考手册,它将作为 Java 系列的组成部份,在 1997 年春季由 Addison-Wesley 出版公司出版。

    8.1 概述

    由于 SQL 数据类型和 Java 数据类型是不同的,因此需要某种机制在使用 Java 类型的应用程序和使用 SQL 类型的数据库之间来读写数据。

    为此,JDBC 提供了 getXXX 和 setXXX 方法集、方法 registerOutParameter 和类 Types

    本章汇集了影响各种类和接口的数据类型的有关信息,并列出所有的对应关系表(这些表显示了 SQL 类型和 Java 类型之间的映射关系)以便于参考。

    8.2 将 SQL 数据类型映射为 Java 类型

    不幸的是,不同数据库产品所支持的 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 类型名称的主要地方是在用 SQL 的 CREATE TABLE 语句创建新的数据库表时。这种情况下,程序员必须注意应该使用目标数据库所支持的 SQL 类型名称。如果需要知道各种 SQL 类型在某个特定的数据库中的行为的确切定义,我们建议查阅一下数据库文档。

    如果想要编写一种可在各种数据库上创建表的可移植 JDBC 程序,用户主要有两个选择。第一个选择是:限制自己只使用那些被广为接受的 SQL 类型名称(例如 INTEGERNUMERIC 或VARCHAR)。这些类型有可能能适应所有的数据库。第二个选择是:用 java.sql.DatabaseMetaData.getTypeInfo 方法来找出给定的数据库实际上支持哪些 SQL 类型,然后选择与给定 JDBC 类型相匹配的特定于数据库的 SQL 类型名。

    JDBC 定义了一个从 JDBC 数据库类型到 Java 类型的标准映射。例如,JDBC 的 INTEGER 类型通常映射为 Java 的 int 类型。这可支持简单的接口,将 JDBC 值读写为简单的 Java 类型。

    Java 类型不必与 JDBC 类型完全形同;它们只须能够用足够的类型信息来代表 JDBC 类型,从而能正确地存储和取出参数和从 SQL 语句恢复结果就可以了。例如,Java String 对象可能并不能精确地与任何 JDBC CHAR 类型匹配,但它却可给出足够的类型信息来成功地表示 CHAR、 VARCHAR 或 LONGVARCHAR 类型。

    8.3 JDBC 类型

    本节描述各种 JDBC 数据类型及其与标准 SQL 类型和 Java 类型的关联方式。

    8.3.1 CHAR、 VARCHAR 和 LONGVARCHAR

    JDBC 类型 CHARVARCHAR 和 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 程序员不必区分 CHARVARCHAR 和 LONGVARCHAR 这三种类型的 JDBC 字符串。它们都可表示为 Java String,并且在不知道所需要的确切数据类型时也可正确读写 SQL 语句。

    CHARVARCHAR 和 LONGVARCHAR 可映射为 String 或 char[],但 String 更适合于一般用法。同时, String 类能使 String 和 char[] 之间的转换更为容易:它有一个用于将 String对象转换为 char[] 的方法,还有一个将 char[] 转换为 String 对象的构造函数。

    必须提及的一个问题是:如何处理类型为 CHAR(n) 的固定长度的 SQL 字符串。答案是 JDBC 驱动程序(或 DBMS)将用适当的空格来进行填补。因此,当从数据库中检索 CHAR(n) 域时,驱动程序将把它转换为长度为 n 的 Java String 对象,对象末尾可能含有一些填补空格。反之,当把 String 对象送到某个 CHAR(n) 域时,驱动程序和/或数据库将在字符串的末尾填上一些必要的空格,使字符串的长度达到 n

    方法 ResultSet.getString 用于分配和返回新的 String 对象。我们建议用它来从 CHARVARCHAR 和LONGVARCHAR 域中检索数据。它适用于检索普通的数据,但如果用 JDBC 类型LONGVARCHAR 来储存多个兆字节的字符串时,用它进行检索将显得十分笨拙。为此,ResultSet 接口中有两个方法可供程序员将 LONGVARCHAR 值作为 Java 输入流进行检索,之后可从该流中以任意大小的块来读取数据。这两个方法是:getAsciiStream 和 getUnicodeStream,它们将把储存在 LONGVARCHAR 列的数据作为 Ascii 或 Unicode 字符流来传送。

    8.3.2 BINARY、VARBINARY 和 LONGVARBINARY

    JDBC 类型 BINARYVARBINARY 和 LONGVARBINARY 密切相关。BINARY 表示固定长度的小二进制值, VARBINARY 表示长度可变化的小二进制值,而 LONGVARBINARY 表示长度可变化的大二进制值。

    不幸的是,这些不同 BINARY 类型的使用还未被标准化,因而在各种主要数据库提供的支持有很大的不同。

    对应于 JDBC BINARY 类型的 SQL BINARY 类型,是一种非标准的 SQL 扩展,只在某些数据库上才实现。它接受用于指定二进制字节数的参数。例如,BINARY(12) 即定义了一个长度为 12 个字节的 binary 类型。通常,BINARY 值被限定在 254 个字节以内。

    对应于 JDBC VARBINARY 类型的 SQL VARBINARY 类型,是一种非标准的 SQL 扩展,只在某些数据库上才实现。它接受用于指定二进制字节最大数的参数。例如,VARBINARY(12) 即定义了一个长度最大可为 12 个字节的二进制类型。通常,VARBINARY 的值被限定在 254 个字节以内。当把二进制的值赋给 VARBINARY 变量时,数据库就记住这个所赋值的长度,调用 SELECT时,它返回准确的原始值。

    遗憾的是,目前还没有一致的 SQL 类型名称与 JDBC LONGVARBINARY 类型相对应。所有主要数据库都支持某种类型的长度可变的大二进制类型,它可支持高达十亿个字节的数据,但 SQL 类型名称却变化多样。

    在 Java 中,BINARYVARBINARY 和 LONGVARBINARY 都可用同一 byte数组来表示。由于可在不知道所需的确切 BINARY 数据类型的情况下正确地读写 SQL 语句,因此,Java 程序员无需区分它们。

    检索 BINARY 和 VARBINARY 值时,我们建议使用 ResultSet.getBytes。然而,如果类型为 JDBC LONGVARBINARY 的某列储存的是几兆字节长度的字节数组,则建议用方法getBinaryStream 来检索。与 LONGVARCHAR 的情形类似,该方法可以使 Java 程序员将 LONGVARBINARY 值作为 Java 输入流检索,然后可从该流中以更小的块来读取。

    8.3.3 BIT

    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 BIT 类型的 Java 映射的推荐类型是 Java 布尔型。

    8.3.4 TINYINT

    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 值。

    8.3.5 SMALLINT

    JDBC 类型 SMALLINT 代表一个 16 位的有符号整数,其值在 -32768 和 32767 之间。

    对应的 SQL 类型 SMALLINT,其定义由 SQL- 92 给出,并为所有主流数据库所支持。SQL-92 标准将 SMALLINT 的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 16 位。

    JDBC SMALLINT 类型的 Java 映射的推荐类型是 Java short 类型。

    8.3.6 INTEGER

    JDBC 类型 INTEGER 代表一个 32 位的有符号整数,其值在 - 2147483648 和 2147483647 之间。

    对应的 SQL 类型 INTEGER,其定义由 SQL- 92 给出,并为所有主流数据库所广为支持。SQL-92 标准将 INTEGER 的精度留给实现去决定。但事实上,所有的主流数据库都至少支持 32 位。

    INTEGER 类型 Java 映射的推荐类型是 Java int 类型。

    8.3.7 BIGINT

    JDBC 类型 BIGINT 代表一个 64 位的有符号整数,其值在 -9223372036854775808 和 9223372036854775807 之间。

    对应的 SQL 类型 BIGINT 是 SQL 的一个非标准扩展。事实上,目前还没有任何数据库实现 SQL BIGINT 类型。我们建议在可移植的代码中避免使用该类型。

    BIGINT 类型的 Java 映射的推荐类型是 Java long 类型。

    8.3.8 REAL

    JDBC 类型 REAL 代表一个有 7 位尾数的“单精度”浮点数。

    对应的 SQL 类型 REAL,其定义由 SQL- 92 给出。虽然未得到普遍支持,但在主流数据库中却已得到广泛支持。SQL-92 标准将 REAL 的精度留给实现去决定。但事实上,所有的支持 REAL类型的主流数据库都支持至少 7 位数的尾数精度。

    REAL 类型的 Java 映射的推荐类型为 Java float 类型。

    8.3.9 DOUBLE

    JDBC 类型 DOUBLE 代表一个有 15 位尾数的“双精度”浮点数。

    对应的 SQL 类型是 DOUBLE PRECISION,其定义由 SQL- 92 给出,并为主流数据库所广为支持。SQL-92 标准将 DOUBLE PRECISION 的精度留给实现去决定。但事实上,所有支持 DOUBLEPRECISION 类型的主流数据库都支持至少 15 位数的尾数精度。

    DOUBLE 类型的 Java 映射的推荐类型为 Java double 类型。

    8.3.10 FLOAT

    JDBC 类型 FLOAT 基本上与 JDBC 类型 DOUBLE 相同。我们同时提供了 FLOAT 和 DOUBLE,其目的是与以前的 API 实现一致。但这却有可能产生误导。FLOAT 代表一个有 15 位尾数的“双精度”浮点数。

    对应的 SQL 类型 FLOAT,其定义由 SQL-92 给出。SQL-92 标准将 FLOAT 的精度留给实现去决定。但事实上,所有支持 FLOAT 类型的主流数据库都支持至少 15 位数的尾数精度。

    FLOAT 类型的 Java 映射的推荐类型为 Java double 类型。然而,由于 SQL FLOAT 和单精度的 Java float类型间可能产生混淆,因此建议 JDBC 程序员通常选用 JDBC DOUBLE 类型而不选用 FLOAT

    8.3.11 DECIMAL 和 NUMERIC

    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 数值型类型来检索。

    8.3.12 DATE、TIME 和 TIMESTAMP

    有三种 JDBC 类型与时间有关:

    • JDBC DATE 类型表示一个由年、月、日组成的日期。对应的是 SQL DATE 类型,其定义由 SQL-92 给出,但只有一部份主流数据库实现它。某些数据库提供了另外一些支持类似语义的 SQL 类型。
    • JDBC TIME 类型表示一个由小时、分钟和秒组成的时间。对应的是 SQL TIME 类型,其定义由 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,对应于 SQL DATE 信息。java.util.Date 基本类中的小时、分钟和秒都设为 0。
    • java.sql.Time,对应于 SQL TIME 信息。java.util.Date 基本类中的年、月、日域设为 1970 年 1 月 1 日。这是 Java 纪元的“零”日期。
    • java.sql.Timestamp,对应于 SQL TIMESTAMP 信息。该类扩展了 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));
    

    8.4 映射示例

    任何情况下,当 Java 程序要从数据库中检索数据时,必须存在某种形式的映射和数据转换。大多数时候, JDBC 程序员将在知道其目标数据库机制的情况下进行编程。例如,他们将知道数据库含有哪些表、表中每一列的数据类型。因此,他们可使用 ResultSet、 PreparedStatement和 CallableStatement 接口中那些与类型有关的存取方法。本节给出三个示例,描述各种情形中所要求的数据映射和转换。

    8.4.1 简单的 SQL 语句

    在最常见的情形中,用户将执行简单的 SQL 语句,然后取回含有结果的 ResultSet 对象。由数据库返回并存放在 ResultSet 列的值,其类型为 JDBC 数据类型。调用ResultSet.getXXX 方法将把该值检索为 Java 数据类型。例如,如果某个 ResultSet 列含有一个 JDBC FLOAT 值,则方法 getDouble 将把它检索为 Java double 类型。8.6.6 节所示的表显示了哪些 getXXX 方法可检索哪些 JDBC 类型(如果用户不知道某个 ResultSet 列的类型,可通过调用 ResultSet.getMetaData 方法来获得有关信息,然后再调用ResultSetMetaData 的 getColumnType 或 getColumnTypeName 方法)。以下代码段示范了如何获得结果中各列的类型名称:

        String query = "select * from Table1";
        ResultSet rs = stmt.executeQuery(query);
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        for (int i = 1; i <= columnCount; i++)  {
          String s = rsmd.getColumnTypeName(i);
          System.out.println ("Column " + i + " is type " + s);
        }
    

    8.4.2 带 IN 参数的 SQL 语句

    在另一个可能的情况中,用户将发送带输入参数的 SQL 语句。这种情况下,用户通过调用 PreparedStatement.setXXX 方法为每个输入参数赋值。例如,PreparedStatement.setLong(1, 2345678) 将把值 2345678 作为 Java 的 long 类型赋给第一个参数。为了将 2345678 到数据库中,驱动程序将把它转换为 JDBC BIGINT。驱动程序将把哪种 JDBC 类型送到数据库中是由 Java 类型到 JDBC 类型的标准映射所决定的

    8.4.3 带 OUT 参数的 SQL 语句

    还有一个情况是,用户要调用已存储过程,将值赋给其 INOUT 参数,从结果中检索值,然后从参数中检索值。这种情形极为少见且相当复杂,但它却不失为映射和数据转换的好范例。

    这种情况下,首先要做的是用 PreparedStatement.setXXX 方法对 INOUT 参数赋值。此外,由于这些参数同时也用于输出,因此程序员必须为每个参数注册 JDBC 类型,该类型是数据库所要返回给该参数的值的 JDBC 类型。这可用 CallableStatement.registerOutParameter 方法来完成,后者接受在类 Types 中所定义的 JDBC 类型作为其变量。程序员可以用ResultSet.getXXX 方法系列来检索返回给ResultSet 对象的结果,用 CallableStatement.getXXX 方法系列来检索存放在输出参数中的值。

    用于 ResultSet.getXXX 方法的 XXX 类型在某些情况下非常灵活。8.6.6 节中所示的表显示了哪些 ResultSet.getXXX 方法可用于检索哪些 JDBC 类型。

    用于 CallableStatement.getXXX 方法的 XXX 类型必须映射为那个参数所注册的 JDBC 类型。例如,如果数据库应返回类型为 JDBC REAL 的输出值,则该参数应被注册为java.sql.Types.REAL。因此,要检索该 JDBC REAL 值,必须调用 CallableStatement.getFloat 方法(从 JDBC 类型到 Java 类型的映射在 8.6.1 节中的表中给出)。方法 getFloat先把储存在输出参数中的值从 JDBC REAL 类型转换为 Java float 类型,然后将它返回。为了适应各种数据库和使应用程序具有更高的可移植性,建议先检索 ResultSet 对象中的值,再检索输出参数中的值。

    下述代码示范的是调用名为 getTestData 的已存储过程。它有两个参数,且都是 INOUT 参数。首先, Connection 对象 con 将创建 CallableStatement 对象 cstmt。然后,方法setByte 把第一个参数设置为 Java byte 类型,其值为 25。驱动程序将把 25 转换为 JDBC TINYINT 类型并将之送到数据库中。方法 setBigDecimal 用输入值 83.75 来设置第二个参数。驱动程序将把这个 java.math.BigDecimal 对象转换为 JDBC NUMERIC 值。接下来将这两个参数注册为 OUT 参数,第一个参数注册为 JDBC TINYINT 类型,第二个参数注册为小数点后面带两位数字的 JDBC DECIMAL 类型。执行 cstmt 后,就用 ResultSet.getXXX 方法将值从 ResultSet 对象中检索出来。方法 getString 将第一列中的值作为 Java String 对象获取,getInt 将第二列中的值作为 Java int 获取,getInt 将第三列中的值作为 Java int 获取。

    之后, CallableStatement.getXXX 方法检索存放在输出参数中的值。方法 getByte 将 JDBC TINYINT 检索为 Java bytegetBigDecimal 将 JDBC DECIMAL 检索为小数点后面带有两位数字的 java.math.BigDecimal 对象。注意,当参数既是输入参数同时又是输出参数时,setXXX 方法所用的 Java 类型与 getXXX 方法所用的相同(正如 setByte 和 getByte 中一样)。registerOutParameter 方法将它注册成由 Java 类型映射来的 JDBC 类型(Java byte 类型映射为 JDBC TINYINT,如 8.6.2 节中的表所示)。

        CallableStatement cstmt = con.prepareCall(
              "{call getTestData(?, ?)}");
        cstmt.setByte(1, 25);
        cstmt.setBigDecimal(2, 83.75);
        // 将第一个参数注册为 JDBC TINYINT,第二个
        // 参数注册为小数点后面带有两位数字的 JDBC DECIMAL 类型
        cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
        cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 2);
        ResultSet rs = cstmt.executeUpdate();
        // 检索并打印结果中的值。
        while(rs.next()) {
          String name = rs.getString(1);
          int score = rs.getInt(2);
          int percentile = rs.getInt(3);
          System.out.print("name = " + name + ", score = " + score + ", "
          System.out.println("percentile = " + percentile);
        // 检索输出参数中的值 
        byte x = cstmt.getByte(1);
        java.math.BigDecimal n = cstmt.getBigDecimal(2, 2);
    

    总之,CallableStatement.getXXX 和 PreparedStatement.setXXX 方法系列中的 XXX 是 Java 类型。对于 setXXX 方法,驱动程序先把 Java 类型转换为 JDBC 类型,再把它送到数据库中(使用 8.6.2 节中的表所示的标准映射)。对于 getXXX 方法, 驱动程序先把数据库返回的 JDBC 类型转换为 Java 类型(用 8.6.1 节表中所示的标准映射),再把它返回给 getXXX 方法。

    registerOutParameter 方法只接受 JDBC 类型的变量,而 setObject 方法却可接受 JDBC 类型的变量。

    注意,如果在可选的第三个变量的位置上提供了 JDBC 类型,则 setObject 方法将把参数值从 Java 类型显式地转换为所指定的 JDBC 类型。如果没有为 setObject 提供目标 JDBC 类型,则将把参数值转换为 Java 类型的标准映射 JDBC 类型(如 8.6.2 节的表中所示)。在将参数送到数据库中之前,驱动程序都要进行显式或隐式转换。

    8.5 动态数据存取

    大多数时候,用户要存取的结果和参数其数据类型在编译时是已知的。然而,有些应用程序(例如普通的浏览器或查询工具)在编译时对它们所要存取的数据库的机制并不知晓。因此,JDBC 除了支持静态数据类型存取外,还支持类型完全动态确定的数据存取。

    有三种方法和一个常量可用于访问那些在编译时其数据类型尚属未知的值:

    • ResultSet.getObject 
    • PreparedStatement.setObject 
    • CallableStatement.getObject 
    • java.sql.Types.OTHER (用作 CallableStatement.registerOutParameter 的一个变量)  

    例如,如果应用程序想要接受多种类型作为其 ResultSet 对象中的结果,它可以使用 ResultSet.getObject 方法。

    ResultSet.getObject 和 CallableStatement.getObject 方法将值检索为 Java Object。由于 Object 是所有 Java 对象的基本类,因此可将任何 Java 类的实例检索为 Object 的实例。然而,以下 Java 类型是内置的“基本”类型,因此,它们不是类 Object 的实例: booleancharbyteshortintlong、 float 和 double。因此,不能用 getObject 方法来检索它们。然而,这些基本类型每种都有相应的可用作 wrapper 的类。这些类的实例是对象,这意味着可用 ResultSet.getObject 和 CallableStatement.getObject 方法来检索它们。第 67 页中的表 8.6.3 显示了从 JDBC 类型到 Java Object 类型的映射。该表与 JDBC 类型到 Java 类型的标准映射不同:在该表中,除了 JDBC TINYINT 和 JDBC SMALLINT 类型映射为 Java 类Integer 之外,每一个基本的 Java 类型都被替换为它们的 wrapper 类。

    方法 getObject 还可用于检索用户定义的 Java 类型。随着抽象数据类型(ADT)和其它用户定义的类型在某些数据库系统中的出现,一些提供者可能会发现用 getObject 来检索这些类型将更方便。

    8.6 数据类型映射表

    本节含有以下表,它们是 JDBC 类型 和 Java 数据类型之间的映射关系表:

    8.6.1 节 — 从 JDBC 类型映射到 Java 类型

    8.6.2 节 — 从 Java 类型映射到 JDBC 类型

    8.6.3 节 ─ 从 JDBC 类型映射到 Java Object 类型

    8.6.4 节 ─ 从 Java Object 类型映射到 JDBC 类型

    8.6.5 节 ─ 由 setObject 所进行的转换

    8.6.6 节 — 由 ResultSet.getXXX 方法所检索的 JDBC 类型

    8.6.1 从 JDBC 类型映射到 Java 类型

    JDBC 类型 Java 类型
    CHAR String
    VARCHAR String
    LONGVARCHAR String
    NUMERIC java.math.BigDecimal
    DECIMAL java.math.BigDecimal
    BIT boolean
    TINYINT byte
    SMALLINT short
    INTEGER int
    BIGINT long
    REAL float
    FLOAT double
    DOUBLE double
    BINARY byte[]
    VARBINARY byte[]
    LONGVARBINARY byte[]
    DATE java.sql.Date
    TIME java.sql.Time
    TIMESTAMP java.sql.Timestamp


     

    8.6.2 从 Java 类型映射到 JDBC 类型

    该表显示的是表 8.6.1 的反映射:Java 类型到 JDBC 类型的映射。

    Java 类型 JDBC 类型
    String VARCHAR 或 LONGVARCHAR
    java.math.BigDecimal NUMERIC
    boolean BIT
    byte TINYINT
    short SMALLINT
    int INTEGER
    long BIGINT
    float REAL
    double DOUBLE
    byte[] VARBINARY 或 LONGVARBINARY
    java.sql.Date DATE
    java.sql.Time TIME
    java.sql.Timestamp TIMESTAMP


     
    String 类型的映射通常是 VARCHAR,但如果所给的值超出了驱动程序对 VARCHAR 值所限定的极限,则将转换为 LONGVARCHAR 类型。对 byte[]VARBINARY 及 LONGVARBINARY 值也一样。

    8.6.3 从 JDBC 类型到 Java Object 类型的映射

    由于 Java 内置类型(例如 boolean 和 int)不是 Object 的子类型,因此对于 getObject/setObject 方法,从 JDBC 类型到 Java object 类型的映射稍有不同。此种映射如下表所示:

     

    JDBC 类型 Java Object 类型
    CHAR String
    VARCHAR String
    LONGVARCHAR String
    NUMERIC java.math.BigDecimal
    DECIMAL java.math.BigDecimal
    BIT Boolean
    TINYINT Integer
    SMALLINT Integer
    INTEGER Integer
    BIGINT Long
    REAL Float
    FLOAT Double
    DOUBLE Double
    BINARY byte[]
    VARBINARY byte[]
    LONGVARBINARY byte[]
    DATE java.sql.Date
    TIME java.sql.Time
    TIMESTAMP java.sql.Timestamp


     
     

    8.6.4 Java Object 类型映射到 JDBC 类型

    Java Object 类型 JDBC 类型
    String VARCHAR 或 LONGVARCHAR
    java.math.BigDecimal NUMERIC
    Boolean BIT
    Integer INTEGER
    Long BIGINT
    Float REAL
    Double DOUBLE
    byte[] VARBINARY 或 LONGVARBINARY
    java.sql.Date DATE
    java.sql.Time TIME
    java.sql.Timestamp TIMESTAMP


     
    注意,String 的映射通常为 VARCHAR,但如果所给的值超出了驱动程序对 VARCHAR 值所限定的极限值,则将转换为 LONGVARCHAR。对 byte[]VARBINARY 和 LONGVARBINARY 值也一样。

     

    8.6.5 由 setObject 所进行的转换

    setObject

     

      T
    I
    N
    Y
    I
    N
    T
    S
    M
    A
    L
    L
    I
    N
    T
    I
    N
    T
    E
    G
    E
    R
    B
    I
    G
    I
    N
    T
    R
    E
    A
    L
    F
    L
    O
    A
    T
    D
    O
    U
    B
    L
    E
    D
    E
    C
    I
    M
    A
    L
    N
    U
    M
    E
    R
    I
    C
    B
    I
    T
    C
    H
    A
    R
    V
    A
    R
    C
    H
    A
    R
    L
    O
    N
    G
    V
    A
    R
    C
    H
    A
    R
    B
    I
    N
    A
    R
    Y
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    L
    O
    N
    G
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    D
    A
    T
    E
    T
    I
    M
    E
    T
    I
    M
    E
    S
    T
    A
    M
    P
    String x x x x x x x x x x x x x x x x x x x
    java.math.BigDecimal x x x x x x x x x x x x x            
    Boolean x x x x x x x x x x x x x            
    Integer x x x x x x x x x x x x x            
    Long x x x x x x x x x x x x x            
    Float x x x x x x x x x x x x x            
    Double x x x x x x x x x x x x x            
    byte[]                           x x x      
    java.sql.Date                     x x x       x   x
    java.sql.Time                     x x x         x  
    java.sql.Time- stamp                     x x x       x x x


     
    从 Java object 类型到 JDBC 类型的转换。

     

    8.6.6 由 ResultSet.getXXX 方法检索的 JDBC 类型

    "x" 表示该方法可以检索 JDBC 类型。"X" 表示建议使用该方法来检索该 JDBC 类型。

     

      T
    I
    N
    Y
    I
    N
    T
    S
    M
    A
    L
    L
    I
    N
    T
    I
    N
    T
    E
    G
    E
    R
    B
    I
    G
    I
    N
    T
    R
    E
    A
    L
    F
    L
    O
    A
    T
    D
    O
    U
    B
    L
    E
    D
    E
    C
    I
    M
    A
    L
    N
    U
    M
    E
    R
    I
    C
    B
    I
    T
    C
    H
    A
    R
    V
    A
    R
    C
    H
    A
    R
    L
    O
    N
    G
    V
    A
    R
    C
    H
    A
    R
    B
    I
    N
    A
    R
    Y
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    L
    O
    N
    G
    V
    A
    R
    B
    I
    N
    A
    R
    Y
    D
    A
    T
    E
    T
    I
    M
    E
    T
    I
    M
    E
    S
    T
    A
    M
    P
    getByte X x x x x x x x x x x x x            
    getShort x X x x x x x x x x x x x            
    getInt x x X x x x x x x x x x x            
    getLong x x x X x x x x x x x x x            
    getFloat x x x x X x x x x x x x x            
    getDouble x x x x x X X x x x x x x            
    getBigDecimal x x x x x x x X X x x x x            
    getBoolean x x x x x x x x x X x x x            
    getString x x x x x x x x x x X X x x x x x x x
    getBytes                           X X x      
    getDate                     x x x       X   x
    getTime                     x x x         X x
    getTimestamp                     x x x       x   X
    getAsciiStream                     x x X x x x      
    getUnicodeStream                     x x X x x x      
    getBinaryStream                           x x X      
    getObject x x x x x x x x x x x x x x x x x x x

     

    相关链接

    方法将 Java object 类型转换为 JDBC 类型。8.6.2 节中的表所示。

    展开全文
  • 不可能有影响吧,三元操作符的条件都为真了,只返回第一个值嘛,与第二个值有一毛钱的关系吗?貌似有道理。 果真如此吗?我们通过结果来验证一下,运行结果是:“两者是否相等:false”,什么? 不相等,Why? ...

    三元操作符是if-else的简化写法,我们在项目经常能用到他,但是有时候也容易出现问题,我们先看看下面这段代码:

        int i = 80;
        String str1 = String.valueOf(i < 100 ? 90 : 100);
        String str2 = String.valueOf(i < 100 ? 90 : 100.0);
    
        System.out.println("俩者相等:" + str1.equals(str2));

    分析一下这段代码:i是80,那它当然小于100,两者的返回值肯定都是90,再转成 String类型,其值也绝对相等,毋庸置疑的。恩,分析得有点道理,但是变量str1中三元操作表达式中的第二个操作数是100,而str2的第二个操作数是100.0,难道没有影响吗?不可能有影响吧,三元操作符的条件都为真了,只返回第一个值嘛,与第二个值有一毛钱的关系吗?貌似有道理。

    果真如此吗?我们通过结果来验证一下,运行结果是:“两者是否相等:false”,什么? 不相等,Why?

    问题就出在100和100.0这两个数字上,在变量str1中,三元操作符中的第一个操作数 (90)和第二个操作数(100)都是int类型,类型相同,返回的结果也就是int类型的90, 而变str2的情况就有点不同了,第一个操作数是90(int类型),第二个操作数却是100.0(float类型),两个操作数的类型不一致。可三元操作符必须要返回一个数据。而且类型要确定,不可能条件为真时返回int类型,条件为假时返回float类型,编译器是不允许如此的,所以它就会进行类型转换了,int型转换为浮点数90.0,导致最终返回值是浮点数90.0。那这当然与整型的90不相等了。

    那么,为什么是整型转为浮点,而不是浮点转为整型呢,这就涉及三元操作符类型的转换规則:

    • 若两个操作数不可转换,则不做转换,返回值为Object类型
    • 若两个操作数是明确类型的表达式(比如变量),則按照正常的二进制数字来转换,int 类型转换为long类型,long类型转换为float类型等
    • 若两个操作数中有一个是数字S,另外一个是表达式,且其类型为T,那么,若数字S在T的范围内,則转换为T类型;若S超出了T类型的范围,则T转换为S类
    • 若两个操作数都是直接量数字(Literal) 则返回值类型为范围较大者。
    展开全文
  • 关系数据库——关系数据语言

    千次阅读 多人点赞 2019-10-22 19:52:51
    域:一组具有相同数据类型的值的集合(即取值范围) 笛卡尔积:域上的一种集合运算。结果为一个集合,集合的每一个元素是一个元组,元组的每一个分量来自不同的域。 基数:一个域允许的不同取值个数。 ...

    关系

    1. 域:一组具有相同数据类型的值的集合(即取值范围)

    2. 笛卡尔积:域上的一种集合运算。结果为一个集合,集合的每一个元素是一个元组,元组的每一个分量来自不同的域。

    3. 基数:一个域允许的不同取值个数。

    4. 笛卡尔积的基数:每个域不同取值的个数的乘积,或者说元组的个数

    5. 关系:域的笛卡尔积的子集叫做在域上的关系,域的个数叫做关系的目或度。(即列数,属性的数目),注意广义上的笛卡尔积一般不能称为关系,因为存在无效的数据。

    6. 关系:表

      列:属性

      行:元组

    7. 候选码:某一属性组的值能唯一地标示一个元组,而其子集不能,则称该属性组为候选码

    8. 主属性:候选码中的属性都称为主属性,注意:主属性非空。

    9. 非主属性:候选码之外的属性称为非主属性

    10. 全码:关系模式的所有属性是这个关系模式的候选码

    11. 主码:从候选码中选取一组能唯一确定一个元组的属性组作为主码。

    12. 三类关系:

      1)基本关系:实际存在的表,是实际存储数据的逻辑表示

      2)查询表:查询结果对应的表

      3)视图表:由基本表或其他视图表导出的表,是虚表,不对应实际存储的数据。

      注意:关系数据模型中的关系必须是有限集合。

      关系的每一个列必须附加一个属性名,属性名不能重名,这种方法取消了关系属性的有序性。

    13. ① 列是同质的(Homogeneous):每一列中的分量来自同一个域,是同一类型的数据

      ② 不同的列可出自同一个域

      • 其中的每一列称为一个属性

      • 不同的属性要给予不同的属性名

      ③ 列的顺序无所谓, 列的次序可以任意交换

      ④ 任意两个元组的候选码不能相同:相同就不是候选码了

      ⑤ 行的顺序无所谓,行的次序可以任意交换

      ⑥ 分量必须取原子值(不允许表中套表)

    关系模式

     

    1. 关系模式:对关系的描述,是静态的、稳定的

    2. 关系:是关系模式在某一时刻的状态或内容,是动态的、随时间不断变化的,指后边的那个关系

    3. 关系模式的形式化表示:

    //关系模式
    R(U, D, DOM, F)
    R       关系名
    U       组成该关系的属性名集合
    D       属性组U中属性所来自的域
    DOM  	属性向域的映象集合
    F       属性间的数据依赖关系集合
    
    //可以简记为
    R (U)    或    R (A1,A2,…,An)
    R: 关系名
    A1,A2,…,An  : 属性名
    注:域名及属性向域的映象常常直接说明为属性的类型、长度

    关系数据库

    1. 在一个给定的应用领域中,所有关系的集合构成一个关系数据库

    2. 关系数据库的型与值,不是关系的型与值

      1)关系数据库的型也称关系数据库模式,是对关系数据库的描述

      2)关系数据库的值是关系模式在某一时刻对应的关系的集合,简称为关系数据库

    基本的关系操作

    1. 常用的基本操作:

      **查询:**选择、投影、连接、除、并、交、差

      **数据更新:**插入、删除、修改

    2. **5种基本操作:**选择、投影、并、差、笛卡尔积 注意:不算交

    3. 关系操作的特点:

      集合操作方式:操作的对象和结果都是集合,一次一集合的方式,操作对象是集合,操作结果亦为集合。

     

    关系的完整性

    实体完整性(即主属性非空)

    1. 若属性A是基本关系R的主属性,则属性A不能取空值

    参照完整性

    1. 关系间的引用:关系与关系之间存在着联系

    2. 外码:设F是基本关系R的一个或一组属性,但不是关系R的主码Ks是基本关系S的主码。如果F与Ks相对应,则称F是基本关系R的外码,外码所在的基本关系叫做参照关系,Ks所在的关系叫做被参照关系。

      注:

      1)R、S不一定是不同的关系。

      2)目标关系S的主码Ks 和参照关系的外码F必须定义在同一个(或一组)域上

      3)外码并不一定要与相应的主码同名,当外码与相应的主码属于不同关系时,往往取相同的名字,以便于识别

      4)外码的取值:如果外码是参照关系的主属性,则不能为空(实体完整性),只能为被参照关系中主码的取值。如果外码不是参照关系的主属性,则可以取空或者被参照关系主码的取值

    3. 两个不变性:指实体完整性和参照完整性

    用户定义完整性

    1. 针对某一具体关系数据库的约束条件,反映某一具体应用所涉及的数据必须满足的语义要求

    2. 关系模型应提供定义和检验这类完整性的机制,以便用统一的系统的方法处理它们,而不要由应用程序承担这一功能

    关系代数

    传统的集合运算

    1. 传统的关系运算:

      并、交、差、笛卡尔积

    1. 操作对象关系:

      操作方式:同数学中的并、交、差、笛卡尔积。只不过操作对象的元素是元组。另外需要注意能进行运算所需要满足的条件。

      对于并、交、差需要满足的关系:1)属性的数目相同;2)相应的属性取自同一个域

    专门的关系运算

    常见的关系运算有选择、投影、连接、除

    选择:

    在关系R中选择满足给定条件的诸元组。

    表达式:$\sigma_F(R) = {t | t \in R \and F(t) = ''true''}$

    F:为选择条件,是一个逻辑表达式,基本形式为:$X_1 \theta Y_1$,其中$\theta$为大于、小于、等于、不等于等。

    举例:

    选择:$\sigma_{Sdept = "IS"}(Student)$

    ​​​​​​​

    投影:

    从R中选择出若干属性列组成新的关系

    表达式:$\prod_{A} (R)= {t[A] | t\in R}$

    A为属性列,即从R中选择A中属性列的元组,当然选择之后可能会删掉一些元组,因为避免重复。

    举例:还是上方的关系,经过投影$\prod_{Sname, Sdept}(Student)$,结果如下:

     1

    连接

     

    1)**一般连接:**从两个关系的笛卡尔积中选取属性间满足一定条件的元组

    (1)表达式:$R\bowtie_ {A \theta B} S = {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] \theta t_s[B] }$

    (2)A和B:分别为R和S上度数相等且可比的属性组

    (3)$\theta$表示比较运算符,

    (4)连接运算从R和S的广义笛卡尔积R×S中选取(R关系)在A属性组上的值与(S关系)在B属性组上值满足比较关系θ的元组

    2)**等值连接:**当上述的运算符为等于号的时候

    (1)含义:从关系R与S的广义笛卡尔积中选取A、B属性值相等的那些元组,即等值连接为:

    (2)表达式:$R\bowtie_ {A = B} S = {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] = t_s[B] }$

    (3)仍然是从行的角度进行运算,而不涉及列

    (4)属性组可以不同

    3)**自然连接:**一种特殊的等值连接

    (1)与等值连接的不同:两个关系R和S必须具有相同的属性组

    (2)将结果中相同的属性列去掉

    (3)表达式:$R\bowtie S = {t_r^ \frown t_s | t_r \in R \and t_s \in S \and t_r[A] = t_s[B] }$

    4)由自然连接所引发的一系列问题:

    (1)悬浮元组:在做自然连接的时候被舍弃的元组

    (2)外连接:如果把舍弃的元组也保存在结果关系中,而在其他属性上填空值(Null),这种连接就叫做外连接,外连接 = 左外连接 + 右外连接

    (3)左外连接:如果只把左边关系R中要舍弃的元组保留就叫做左外连接

    (4)右外连接:如果只把右边关系S中要舍弃的元组保留就叫做右外连接

    1)除运算的意义:

    (1)假设关系R,S,RS,R关系拥有的属性是姓名,S关系拥有的属性是课程,RS关系拥有的属性是姓名和课程的联系,则RS/S表示选出所有至少选了表S中所列课程的学生的元组。

    (2)如下图:

    注:RS/S得到的关系:张三和李四构成的表,表示选修了全部课程的同学的集合。

    举例:

    R:

    ABC
    a1b1c2
    a2b3c7
    a3b4c6
    a1b2c3
    a4b6c6
    a2b2c3
    a1b2c1

    S:

    BCD
    b1c2d1
    b2c1d1
    b2c3d2

    R÷S

    A
    a1

    (1) 找S与R的共同属性,即公式中的Y属性

    (2)计算R中每个X属性的象集,如果某个象集包含S在Y属性上的投影,则该属为R/S结果中的一个值。

    解答如下:

    在关系R中,A可以取四个值{a1,a2,a3,a4},其中:

    a1的象集为:{(b1,c2),(b2,c3),(b2,c1)}

    a2的象集为:{(b3,c7),(b2,c3)}

    a3的象集为:{(b4,c6)}

    a4的象集为:{(b6,c6)}

    S在(B,C)上的投影为{(b1,c2),(b2,c3),(b2,c1)}。

    显然只有R的象集a1包含S在(B,C)属性组上的投影,所以R÷S={a1}。

    展开全文
  • 一、关系数据结构及形式化定义 1、关系 ... 域是一组具有相同数据类型值的集合。 1.2笛卡儿积 笛卡儿积是域上的一种集合运算。 定义:给定一组域D1,D2,...,Dn,允许其中某些域是相同的,D...
  • 关系操作及alpha语言学习

    千次阅读 2019-06-27 17:20:14
    本文将介绍关系数据库的相关理论。 文章目录前备知识关系代数传统的集合运算并交差笛卡尔积专门的关系运算选择投影连接除运算alpha语言检索简单检索(不带条件的检索)限定的检索(带条件的检索)带排序的查询指定返回的...
  • 今天我们一起来探讨一下有关Hibernate四种关系映射,大家可能会有疑惑,关系...这些关系映射实际上就是对应着关系型数据库中的几种关系类型。我们都知道Hibernate的作用是将面向关系数据操作,转换成面向对象的操作,
  • 区块3是工程代码结构,展示出项目中所有的文件及文件间的关系。 区块4是代码区域,开发主要在这个区域进行编码。 每一个微信小程序,都会有三个公共入口文件: app.json:配置文件,配置路由列表、程序信息...
  • 类型强转和地址强转

    千次阅读 2014-10-19 19:41:46
    所以在将一个整数表示成浮点数的时候,我们需要先将整数表示成以2为底的科学计数型,然后按照下面的格式入相应值即可。 符号 阶码 尾数 如果是单精度(float)类型,上述...
  • SQL Server 数据类型

    千次阅读 2018-04-04 16:48:15
    SQL Server 2014数据类型(1)在SQL Server中,数据类型是创建表的基础。在创建表时,必须为表中的每列指派一种数据类型。本节将介绍SQL Server中最常用的一些数据类型。即使创建自定义数据类型,也必须基于一种标准...
  • redis非关系型数据库详解

    万次阅读 2021-02-26 17:03:34
    Redis 是以key-value形式存储,和传统的关系型数据库不一样。不一定遵循传统数据库的一些基本要求,比如说,不遵循sql标准,事务,表结构等等,redis严格上不是一种数据库,应该是一种数据结构化存储方法的集合。 ...
  • 微信公众号开发

    千次阅读 2020-03-05 23:51:04
    # 基础知识坑 ...一个邮箱只能绑定一个服务。 二、个人订阅号每天只能发布一次内容,...Token认证:公众号-基本配置-Token,这里的Token和access_token没有任何关系,这里的Token自己随便 官方demo中 urls = ( ...
  • 域是一组具有相同数据类型的值的集合。例: 整数、实数、介于某个取值范围的整数、指定长度的字符串集合、{‘男’,‘女’} 1.2 笛卡尔积(Cartesian Product) 笛卡尔积: 给定一组域D1,D2,…,Dn,允许其中某些域...
  • MSSQLServer数据类型详解

    千次阅读 2014-02-27 10:21:38
    在计算机中数据有两种特征:类型和长度。所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类。在SQL Server 中每个变量、参数、表达式等都有数据类型。系统提供的数据类型分为几大类。 其中,BIGINT、...
  • SQL Server 2008数据类型

    千次阅读 2018-08-27 09:56:09
    在创建表时,必须为表中的每列指派一种数据类型。本节将介绍SQL Server中最常用的一些数据类型。即使创建自定义数据类型,它也必须基于一种标准的SQL Server数据类型。例如,可以使用如下语法创
  • MySql索引类型

    万次阅读 2018-07-04 22:15:19
    一旦按照这个顺序的方式加载,主键页就会近似于被顺序的记录满,这也正是所期望的结果(然而,二级索引页可能是不一样的)。 对比一下看看UUID举措索引的插入表数据,看看有什么不同: 因为 新行的主键值不一定比...
  • 抽象数据类型定义(ADT)

    万次阅读 多人点赞 2014-03-16 16:03:56
    一、抽象数据类型定义(ADT) 作用:抽象数据类型可以使我们更容易描述现实世界。...例:线性表这样的抽象数据类型,其数学模型是:数据元素的集合,该集合内的元素有这样的关系:除第一个和最后一
  • MySQL中数据类型介绍

    万次阅读 2015-02-10 10:55:34
    一、MySQL的数据类型 主要包括以下五大类: 整数类型:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT 浮点数类型:FLOAT、DOUBLE、DECIMAL 字符串类型:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM ...
  • JNI中的数组分为基本类型数组和对象数组,它们的处理方式...阅读此文假设已经了解JNI与Java数据类型的映射关系,如果还不了解的童鞋,请移步《JNI/NDK开发指南(三)——JNI数据类型及与Java数据类型的映射关系》阅读。
  • 关系模式的分解与范式

    万次阅读 多人点赞 2017-05-08 16:40:26
    1. 为什么要研究数据库关系模式的分解? 答:因为现有的模式可能会存在一些数据增删改的弊端,比如说:数据冗余太大,更新异常,插入异常,删除异常。因此为了完善数据库的增删改查的功能,需要寻找一种等价的关系...
  • 数组与指针关系

    千次阅读 2013-09-15 20:25:43
    编译器可以自动计算偏移的实际步长,这就是为什么指针总是有类型限制。 有一种说法,在编写数组算法时,使用指针比使用数组更有效率,这个颇为人们所接受的说法在通常情况下时错误的,在现代的产品质量优化的...
  • 最近项目组让整理一个我们项目的表结构设计说明书,就是梳理每张表的字段、描述、是否为空、字段类型等,理论上完成上面的就可以交差了,但我觉得要是能将所有的表之间的关联关系图(EER)画出来就更好了,逼格一下...
  • java基础篇(2)深入解析基本类型

    万次阅读 2019-05-02 08:12:15
    一、基本类型的简介 基本类型的两条准则: Java中,如果对整数不指定类型,默认时int类型,对小数不指定类型,默认是double类型。 基本类型由小到大,可以自动转换,但是由大到小,则需要强制类型转换。 所占的...
  • SpringMvc类型转换器

    千次阅读 2018-01-05 17:59:14
    Spring MVC类型转换器 类型转换器引入 为什么页面上输入”12”,可以赋值给Handler方法对应的参数? 这是因为框架内部帮我们做了类型转换的工作。将String转换成int  但默认类型转换器并不是可以将用户提交的...
  • 文章目录数值类型:整数类型:浮点型:日期类型:字符串类型:枚举类型与集合类型: 数值类型: 整数类型: tinyint 默认有符号,[unsigned]代表无符号,超出范围显示最大范围。 语法: tinyint[(m)] ...
  • 转载博客:...这个项目将介绍共现在关系中的提取,使用python编写代码实现对《釜山行》文本的人物关系提取,最终利用Gephi软件对提取的人物关系绘制人物关系图...
  • GC类型以及不同类型GC的搭配

    千次阅读 2017-05-27 17:42:05
    也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被满了再进行收集,需要预留一部分空间提供并发收集时的程序...
  • 关系模型的基本概念

    千次阅读 2020-12-06 11:39:02
    一、关系模型简述 1.1 关系模型的提出 最早由E.F.Codd在1970年提出 是从表(Table)及表的处理方式中抽象出来的,是在对传统表及其操作进行数学化严格定义基础上,引入集合理论与逻辑学理论提出的 是数据库的三大...
  • 关系数据库设计理论

    万次阅读 多人点赞 2018-04-21 15:26:35
    一、关系数据库模型关系模型是一种基于表的数据模型,以下为关系学生信息,该表有很多不足之处,本文研究内容就是如何改进它:下面是一些重要术语:1.属性(attribute):列的名字,上图有学号、姓名、班级、兴趣...
  • ORM:对象关系映射 一:MTV开发模式 把数据存取逻辑、业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的Model-View-Controller(MVC)模式。 在这个模式中,Model 代表数据存取层,View 代表的是系统中选择...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 102,281
精华内容 40,912
关键字:

关系类型怎么填