# 设置表

> 原文： [https://docs.oracle.com/javase/tutorial/jdbc/basics/tables.html](https://docs.oracle.com/javase/tutorial/jdbc/basics/tables.html)

此页面描述了 JDBC 教程中使用的所有表以及如何创建它们：

*   [咖啡表](#coffees)
*   [供应商表](#suppliers)
*   [COF_INVENTORY 表](#cof_inventory)
*   [MERCH_INVENTORY 表](#merch_inventory)
*   [COFFEE_HOUSES 表](#coffee_houses)
*   [DATA_REPOSITORY 表](#data_repository)
*   [创建表格](#create)
*   [填充表](#populate)

`COFFEES`表存储有关咖啡休息时间可供销售的咖啡的信息：

| `COF_NAME` | `SUP_ID` | `PRICE` | `SALES` | `TOTAL` |
| --- | --- | --- | --- | --- |
| 哥伦比亚 | 101 | 7.99 | 0 | 0 |
| French_Roast | 49 | 8.99 | 0 | 0 |
| 浓咖啡 | 150 | 9.99 | 0 | 0 |
| Colombian_Decaf | 101 | 8.99 | 0 | 0 |
| French_Roast_Decaf | 49 | 9.99 | 0 | 0 |

以下描述了`COFFEES`表中的每一列：

*   `COF_NAME`：存储咖啡名称。保存 SQL 类型为`VARCHAR`且最大长度为 32 个字符的值。因为每种类型的咖啡的名称都不同，所以该名称唯一地标识特定的咖啡并且用作主键。
*   `SUP_ID`：存储识别咖啡供应商的编号。保存 SQL 类型为`INTEGER`的值。它被定义为引用`SUPPLIERS`表中的`SUP_ID`列的外键。因此，DBMS 将强制执行此列中的每个值与`SUPPLIERS`表中相应列中的某个值匹配。
*   `PRICE`：存储每磅咖啡的成本。保存 SQL 类型为`FLOAT`的值，因为它需要保存带小数点的值。 （请注意，货币值通常存储在 SQL 类型`DECIMAL`或`NUMERIC`中，但由于 DBMS 之间存在差异并且为了避免与早期版本的 JDBC 不兼容，本教程使用更标准的类型`FLOAT`。）
*   `SALES`：存储本周销售的咖啡磅数。保存 SQL 类型为`INTEGER`的值。
*   `TOTAL`：存储迄今为止销售的咖啡磅数。保存 SQL 类型为`INTEGER`的值。

`SUPPLIERS`存储有关每个供应商的信息：

| `SUP_ID` | `SUP_NAME` | `STREET` | `CITY` | `STATE` | `ZIP` |
| --- | --- | --- | --- | --- | --- |
| 101 | Acme，Inc。 | 市场街 99 号 | Groundsville | CA | 95199 |
| 49 | 高级咖啡 | 1 个派对地点 | 门多西诺 | CA | 95460 |
| 150 | 高地 | 100 咖啡巷 | 梅多斯 | CA | 93966 |

以下描述了`SUPPLIERS`表中的每一列：

*   `SUP_ID`：存储识别咖啡供应商的编号。保存 SQL 类型为`INTEGER`的值。它是此表中的主键。
*   `SUP_NAME`：存储咖啡供应商的名称。
*   `STREET`，`CITY`，`STATE`和`ZIP`：这些列存储咖啡供应商的地址。

表`COF_INVENTORY`存储有关每个仓库中存储的咖啡量的信息：

| `WAREHOUSE_ID` | `COF_NAME` | `SUP_ID` | `QUAN` | `DATE_VAL` |
| --- | --- | --- | --- | --- |
| 1234 | House_Blend | 49 | 0 | 2006_04_01 |
| 1234 | House_Blend_Decaf | 49 | 0 | 2006_04_01 |
| 1234 | 哥伦比亚 | 101 | 0 | 2006_04_01 |
| 1234 | French_Roast | 49 | 0 | 2006_04_01 |
| 1234 | 浓咖啡 | 150 | 0 | 2006_04_01 |
| 1234 | Colombian_Decaf | 101 | 0 | 2006_04_01 |

以下描述了`COF_INVENTORY`表中的每一列：

*   `WAREHOUSE_ID`：存储标识仓库的编号。
*   `COF_NAME`：存储特定类型咖啡的名称。
*   `SUP_ID`：存储标识供应商的编号。
*   `QUAN`：存储一个表示可用商品数量的数字。
*   `DATE`：存储时间戳值，指示上次更新行的时间。

表`MERCH_INVENTORY`存储有关库存中非咖啡商品数量的信息：

| `ITEM_ID` | `ITEM_NAME` | `SUP_ID` | `QUAN` | `DATE` |
| --- | --- | --- | --- | --- |
| 00001234 | Cup_Large | 00456 | 28 | 2006_04_01 |
| 00001235 | Cup_Small | 00456 | 36 | 2006_04_01 |
| 00001236 | 茶托 | 00456 | 64 | 2006_04_01 |
| 00001287 | 玻璃水瓶 | 00456 | 12 | 2006_04_01 |
| 00006931 | 玻璃水瓶 | 00927 | 3 | 2006_04_01 |
| 00006935 | 隔热垫 | 00927 | 88 | 2006_04_01 |
| 00006977 | 餐巾 | 00927 | 108 | 2006_04_01 |
| 00006979 | 毛巾 | 00927 | 24 | 2006_04_01 |
| 00004488 | CofMaker | 08732 | 五 | 2006_04_01 |
| 00004490 | CofGrinder | 08732 | 9 | 2006_04_01 |
| 00004495 | EspMaker | 08732 | 4 | 2006_04_01 |
| 00006914 | 菜谱 | 00927 | 12 | 2006_04_01 |

以下描述了`MERCH_INVENTORY`表中的每一列：

*   `ITEM_ID`：存储标识项目的编号。
*   `ITEM_NAME`：存储项目的名称。
*   `SUP_ID`：存储标识供应商的编号。
*   `QUAN`：存储一个数字，表示该项目的可用数量。
*   `DATE`：存储时间戳值，指示上次更新行的时间。

表`COFFEE_HOUSES`存储咖啡馆的位置：

| `STORE_ID` | `CITY` | `COFFEE` | `MERCH` | `TOTAL` |
| --- | --- | --- | --- | --- |
| 10023 | 门多西诺 | 3450 | 2005 年 | 5455 |
| 33002 | 西雅图 | 4699 | 3109 | 7808 |
| 10040 | SF | 5386 | 2841 | 8227 |
| 32001 | 波特兰 | 3147 | 3579 | 6726 |
| 10042 | SF | 2863 | 1874 年 | 4710 |
| 10024 | 萨克拉门托 | 1987 年 | 2341 | 4328 |
| 10039 | 卡梅尔 | 2691 | 1121 | 3812 |
| 10041 | LA | 1533 | 1007 | 2540 |
| 33005 | 奥林匹亚 | 2733 | 1550 | 4283 |
| 33010 | 西雅图 | 3210 | 2177 | 5387 |
| 10035 | SF | 1922 年 | 1056 | 2978 |
| 10037 | LA | 2143 | 1876 年 | 4019 |
| 10034 | 圣荷西 | 1234 | 1032 | 2266 |
| 32004 | 尤金 | 1356 | 1112 | 2468 |

以下描述了`COFFEE_HOUSES`表中的每一列：

*   `STORE_ID`：存储识别咖啡馆的号码。除其他外，它表示咖啡馆所处的状态。例如，以 10 开头的值表示该州是加利福尼亚州。以 CO 开头的`STORE_ID`值表示俄勒冈州，而以 33 开头的值表示华盛顿州。
*   `CITY`：存储咖啡馆所在城市的名称。
*   `COFFEE`：存储一个表示已售咖啡量的数字。
*   `MERCH`：存储一个表示销售商品数量的数字。
*   `TOTAL`：存储一个数字，表示已售出的咖啡和商品的总量。

表 DATA_REPOSITORY 存储引用 The Coffee Break 感兴趣的文档和其他数据的 URL。脚本`populate_tables.sql`不会向此表添加任何数据。以下描述了此表中的每个列：

*   `DOCUMENT_NAME`：存储标识 URL 的字符串。
*   `URL`：存储 URL。

您可以使用 Apache Ant 或 JDBC API 创建表。

### 使用 Apache Ant 创建表

要创建与教程示例代码一起使用的表，请在目录 `_&lt; JDBC 教程目录&gt;中运行以下命令。_`：

```
ant setup

```

此命令运行多个 Ant 目标，包括以下`build-tables`（来自`build.xml`文件）：

```
<target name="build-tables"
  description="Create database tables">
  <sql
    driver="${DB.DRIVER}"
    url="${DB.URL}"
    userid="${DB.USER}"
    password="${DB.PASSWORD}"
    classpathref="CLASSPATH"
    delimiter="${DB.DELIMITER}"
    autocommit="false" onerror="abort">
    <transaction src=
  "./sql/${DB.VENDOR}/create-tables.sql"/>
  </sql>
</target>

```

该示例指定以下`sql` Ant 任务参数的值：

| 参数 | 描述 |
| --- | --- |
| `driver` | JDBC 驱动程序的完全限定类名。此示例使用`org.apache.derby.jdbc.EmbeddedDriver`表示 Java DB，`com.mysql.jdbc.Driver`表示 MySQL Connector / J. |
| `url` | DBMS JDBC 驱动程序用于连接数据库的数据库连接 URL。 |
| `userid` | DBMS 中有效用户的名称。 |
| `password` | `userid`中指定的用户密码 |
| `classpathref` | 包含`driver`中指定的类的 JAR 文件的完整路径名 |
| `delimiter` | 用于分隔 SQL 语句的字符串或字符。此示例使用分号（`;`）。 |
| `autocommit` | 布尔值;如果设置为`false`，则所有 SQL 语句都作为一个事务执行。 |
| `onerror` | 语句失败时要执行的操作;可能的值为`continue`，`stop`和`abort`。值`abort`指定如果发生错误，则中止事务。 |

该示例将这些参数的值存储在单独的文件中。构建文件`build.xml`使用`import`任务检索这些值：

```
<import file="${ANTPROPERTIES}"/>

```

`transaction`元素指定包含要执行的 SQL 语句的文件。文件`create-tables.sql`包含创建此页面上描述的所有表的 SQL 语句。例如，以下摘录自此文件创建表`SUPPLIERS`和`COFFEES`：

```
create table SUPPLIERS
    (SUP_ID integer NOT NULL,
    SUP_NAME varchar(40) NOT NULL,
    STREET varchar(40) NOT NULL,
    CITY varchar(20) NOT NULL,
    STATE char(2) NOT NULL,
    ZIP char(5),
    PRIMARY KEY (SUP_ID));

create table COFFEES
    (COF_NAME varchar(32) NOT NULL,
    SUP_ID int NOT NULL,
    PRICE numeric(10,2) NOT NULL,
    SALES integer NOT NULL,
    TOTAL integer NOT NULL,
    PRIMARY KEY (COF_NAME),
    FOREIGN KEY (SUP_ID)
        REFERENCES SUPPLIERS (SUP_ID));

```

**注**：文件`build.xml`包含另一个名为`drop-tables`的目标，用于删除本教程使用的表。 `setup`目标在运行`build-tables`目标之前运行`drop-tables`。

### 使用 JDBC API 创建表

以下方法 `[SuppliersTable.createTable](gettingstarted.html)`创建`SUPPLIERS`表：

```
public void createTable() throws SQLException {
    String createString =
        "create table " + dbName +
        ".SUPPLIERS " +
        "(SUP_ID integer NOT NULL, " +
        "SUP_NAME varchar(40) NOT NULL, " +
        "STREET varchar(40) NOT NULL, " +
        "CITY varchar(20) NOT NULL, " +
        "STATE char(2) NOT NULL, " +
        "ZIP char(5), " +
        "PRIMARY KEY (SUP_ID))";

    Statement stmt = null;
    try {
        stmt = con.createStatement();
        stmt.executeUpdate(createString);
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) { stmt.close(); }
    }
}

```

以下方法 `[CoffeesTable.createTable](gettingstarted.html)`创建`COFFEES`表：

```
  public void createTable() throws SQLException {
    String createString =
        "create table " + dbName +
        ".COFFEES " +
        "(COF_NAME varchar(32) NOT NULL, " +
        "SUP_ID int NOT NULL, " +
        "PRICE float NOT NULL, " +
        "SALES integer NOT NULL, " +
        "TOTAL integer NOT NULL, " +
        "PRIMARY KEY (COF_NAME), " +
        "FOREIGN KEY (SUP_ID) REFERENCES " +
        dbName + ".SUPPLIERS (SUP_ID))";

    Statement stmt = null;
    try {
        stmt = con.createStatement();
        stmt.executeUpdate(createString);
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) { stmt.close(); }
    }
}

```

在这两种方法中，`con`是`Connection`对象，`dbName`是要在其中创建表的数据库的名称。

要执行 SQL 查询（例如`String` `createString`指定的查询），请使用`Statement`对象。要创建`Statement`对象，请从现有`Connection`对象调用方法`Connection.createStatement`。要执行 SQL 查询，请调用方法`Statement.executeUpdate`。

关闭创建它们的连接时，将关闭所有`Statement`对象。但是，一旦完成它们，就明确关闭`Statement`对象是一种很好的编码实践。这允许立即释放语句正在使用的任何外部资源。通过调用方法`Statement.close`关闭语句。将此语句放在`finally`中以确保即使正常程序流因为抛出异常（例如`SQLException`）而中断也会关闭。

**注**：必须在`COFFEES`之前创建`SUPPLIERS`表，因为`COFFEES`包含一个外键，`SUP_ID`引用`SUPPLIERS`。

同样，您可以使用 Apache Ant 或 JDBC API 将数据插入表中。

### 使用 Apache Ant 填充表

除了创建本教程使用的表之外，命令`ant setup`还会填充这些表。此命令运行 Ant 目标`populate-tables`，它运行 SQL 脚本`populate-tables.sql`。

以下是填充表`SUPPLIERS`和`COFFEES`的`populate-tables.sql`的摘录：

```
insert into SUPPLIERS values(
    49, 'Superior Coffee', '1 Party Place',
    'Mendocino', 'CA', '95460');
insert into SUPPLIERS values(
    101, 'Acme, Inc.', '99 Market Street',
    'Groundsville', 'CA', '95199');
insert into SUPPLIERS values(
    150, 'The High Ground',
    '100 Coffee Lane', 'Meadows', 'CA', '93966');
insert into COFFEES values(
    'Colombian', 00101, 7.99, 0, 0);
insert into COFFEES values(
    'French_Roast', 00049, 8.99, 0, 0);
insert into COFFEES values(
    'Espresso', 00150, 9.99, 0, 0);
insert into COFFEES values(
    'Colombian_Decaf', 00101, 8.99, 0, 0);
insert into COFFEES values(
    'French_Roast_Decaf', 00049, 9.99, 0, 0);

```

### 使用 JDBC API 填充表

以下方法`SuppliersTable.populateTable`将数据插入表中：

```
public void populateTable() throws SQLException {

    Statement stmt = null;
    try {
        stmt = con.createStatement();
        stmt.executeUpdate(
            "insert into " + dbName +
            ".SUPPLIERS " +
            "values(49, 'Superior Coffee', " +
            "'1 Party Place', " +
            "'Mendocino', 'CA', '95460')");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".SUPPLIERS " +
            "values(101, 'Acme, Inc.', " +
            "'99 Market Street', " +
            "'Groundsville', 'CA', '95199')");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".SUPPLIERS " +
            "values(150, " +
            "'The High Ground', " +
            "'100 Coffee Lane', " +
            "'Meadows', 'CA', '93966')");
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) { stmt.close(); }
    }
}

```

以下方法`CoffeesTable.populateTable`将数据插入表中：

```
public void populateTable() throws SQLException {

    Statement stmt = null;
    try {
        stmt = con.createStatement();
        stmt.executeUpdate(
            "insert into " + dbName +
            ".COFFEES " +
            "values('Colombian', 00101, " +
            "7.99, 0, 0)");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".COFFEES " +
            "values('French_Roast', " +
            "00049, 8.99, 0, 0)");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".COFFEES " +
            "values('Espresso', 00150, 9.99, 0, 0)");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".COFFEES " +
            "values('Colombian_Decaf', " +
            "00101, 8.99, 0, 0)");

        stmt.executeUpdate(
            "insert into " + dbName +
            ".COFFEES " +
            "values('French_Roast_Decaf', " +
            "00049, 9.99, 0, 0)");
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) {
          stmt.close();
        }
    }
}

```