全部博文(247)
分类: Java
2014-03-20 13:23:09
COF_NAME | SUP_ID | PRICE | SALES | TOTAL |
Colombian | 101 | 7.99 | 0 | 0 |
French_Roast | 49 | 8.99 | 0 | 0 |
Espresso | 150 | 9.99 | 0 | 0 |
Colombian_Decaf | 101 | 8.99 | 0 | 0 |
French_Roast_Decaf | 49 | 9.99 | 0 | 0 |
存储咖啡名称的列是COF_NAME,可保存最大长 度为32个字符的VARCHAR SQL类型数值。由于销售的每种咖啡使用不同名称,因此它可作为主键,惟一标识一种特定咖啡。第二列(SUP_ID)保存一个数字,标识咖啡供应商;这个 数字是INTEGER SQL类型。第三列(PRICE)存储FLOAT SQL类型的数值,因为它需要保存带有小数点的数值(注意,货币一般存储在DECIMAL或NUMERIC SQL类型中,但是因为各DBMS间有区别,为避免与较老版本的JDBC不兼容,所以本教程使用更加标准的FLOAT类型)。SALES这一列存储 INTEGER SQL类型,表示本周销售量(磅)。最后一列(TOTAL)包含SQL INTEGER类型,表示迄今销售量(磅)。
数据库的第二张表SUPPLIERS给出了各个供应商的信息:
SUP_ID | SUP_NAME | STREET | CITY | STATE | ZIP |
101 | Acme, Inc. | 99 Market Street | Groundsville | CA | 95199 |
49 | Superior Coffee | 1 Party Place | Mendocino | CA | 95460 |
150 | The High Ground | 100 Coffee Lane | Meadows | CA | 93966 |
COFFEES表和SUPPLIERS表都包含 SUP_ID列,表明可在SELECT语句中关联这两张表的信息以检索数据。SUP_ID列是SUPPLIERS表的主键,它惟一标识了每个供应商。在 COFFEES表中,SUP_ID称为外键(就其是从另一张表引入的而言,外键可认为是外来的)。每个SUP_ID在SUPPLIERS表中只出现一次, 因为它是主键。但在COFFEES表中,它却是一个外键,完全有可能出现重复的SUP_ID,因为一个供应商可能销售多种咖啡。本讲后面会例示如何在 SELECT语句中使用主键和外键。
下面SQL语句创建了COFFEES表。外括号内的项由列名后 跟空格和该列要存储的SQL类型组成。逗号将各个列项(由列名和SQL类型组成)隔开。创建VARCHAR类型时要指定最大长度,因此它带有一个指出最大 长度的参数。参数要放在类型后面的括号中。例如,下面的SQL语句指出COF_NAME列中的名称最多只有32个字符:
CREATE TABLE COFFEES (COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, SALES INTEGER, TOTAL INTEGER)
这段代码没有DBMS语句结束符,各种DBMS的语句结束符各不相同。例如,Oracle用分号指出语句结束,Sybase用单词go结束语句。驱动程序会自动提供适当的语句结束符,您不必在JDBC代码中包含它们。
关于SQL语句另外应该指出的一点是它的形式。在 CREATE TABLE语句中,关键字都以大写字母输入,每项占一行。SQL不要求这样,这些规定只是让语句易于阅读。SQL的标准是关键字不区分大小写,因此下面的 语句可以用各种形式编写。就SQL而言,如下两个版本是等价的:
SELECT First_Name, Last_Name FROM Employees WHERE Last_Name LIKE "Washington" select First_Name, Last_Name from Employees where Last_Name like "Washington"
但引号内的字符区分大小写:在名称“Washington”中,“W”必须大写,其余字母必须小写。
在标识符名称使用上,DBMS间要求可能不一样。如有些 DBMS要求给出的列名和表名与在CREATE TABLE语句中创建时的名称完全相同,而另一些DBMS则无此要求。为安全起见,这里标识符(如COFFEES和SUPPLIERS)都用大写,因为定 义时就是用大写。
至此创建表COFFEES的SQL语句已写完。现在将它用引 号引起来(使之成为字串),然后赋予变量createTableCoffees,以在后面JDBC代码中使用该变量。如刚才所示,DBMS不关心分行位 置,但在Java编程语言中,超过一行的String对象将不能编译。因此,当使用字串时,要将每行放在引号中,再用一个加号(+)将其连接起来:
String createTableCoffees = "CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)";
CREATE TABLE语句中使用的数据类型是类java.sql.Types中定义的通用SQL类型(亦称JDBC类型)。DBMS一般使用这些标准数据类型,因此 要试验一些JDBC应用程序时,就可以使用包含CREATE TABLE语句的CreateCoffees.java应用程序。如果您的DBMS使用自己的局部类型名称,我们会为您提供另一应用程序(后面有完整解 释)。
在运行程序前,我们还是先来学习一下JDBC的基础知识。
创建JDBC语句
Statement对象可将SQL语句发送到DBMS。这只要 创建一个Statement对象,将想要执行的SQL语句传递给适当的执行方法,然后执行该Statement对象。对于SELECT语句,使用的方法是 executeQuery。对于创建或修改表的语句,使用的方法是executeUpdate。
Statement对象是用活动连接实例创建的。下面的例子使用Connection对象con来创建Stetement对象stmt:
Statement stmt = con.createStatement();
至此stmt对象已存在,但它没有要在DBMS上执行的SQL语句。您需供应用于执行stmt的方法。下面代码段中将上例的SQL语句传递给executeUpdate:
stmt.executeUpdate("CREATE TABLE COFFEES " + "(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, " + "SALES INTEGER, TOTAL INTEGER)");
由于SQL语句已转成字符串并赋给了变量createTableCoffees,因此可用如下代码替换:
stmt.executeUpdate(createTableCoffees);
执行语句
这里使用executeUpdate方法,因为 createTableCoffees中的SQL语句是一条DDL(数据描述语言)语句。创建、修改或删除表的语句都是DDL语句,要用 executeUpdate方法执行。顾名思义,executeUpdate方法也执行更新表的SQL语句。在实际应用中,executeUpdate方 法常用于更新表,而不是创建表,因为表只创建一次,但可能多次更新。
执行SQL语句最常用的方法是executeQuery。这个方法用于执行涵盖了大多数SQL语句的SELECT语句。您马上会看到这种方法的使用。
在表中插入数据
我们已经例示了通过指定列名及其数据类型创建COFFEES表,但这只是创建表结构。表中还没有任何数据。通过提供行中要存储的列信息,就可在表中每次添加一行数据。但插入到列中的数值要与创建表时声明的列顺序(默认顺序)一致。
下面代码插入了一行数据:COF_NAME列的值是 Colombian,SUP_ID列是101,PRICE列是7.99,SALES列是0,TOTAL列是0(由于Coffee Break刚开张,所有咖啡才开始销售,所以本周销售量和迄今销售量都为0)。如同创建COFFEESS表的代码所做的一样,我们将创建一个 Statement对象,然后用executeUpdate方法执行它。
因为SQL语句在页面的一行中放不下,所以要把它分成两个字符 串,再用加号(+)将它连起来,使得它可以编译。特别要注意的是,需要在COFFEES和VALUES间加一个空格。这个空格必须放在引号内,可位于 COFFEES之后或VALUES之前;没有这个空格,SQL语句将错误认为是“ INSERT INTO COFFEESVALUES . . .”,接着DBMS将查找COFFEESVALUES表。还要注意在咖啡名上用单引号,因为它嵌套在双引号中。对于多数DBMS,一般规则是切换双引号和 单引号以指明嵌套。
Statement stmt = con.createStatement(); stmt.executeUpdate( "INSERT INTO COFFEES " + "VALUES ('Colombian', 101, 7.99, 0, 0)");
下面代码在COFFEES表中插入第二行数据。您不必为每次执行创建新的Statement对象,完全可以重用Statement对象stmt。
stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast', 49, 8.99, 0, 0)");
插入的其他行数据如下:
stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Espresso', 150, 9.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('Colombian_Decaf', 101, 8.99, 0, 0)"); stmt.executeUpdate("INSERT INTO COFFEES " + "VALUES ('French_Roast_Decaf', 49, 9.99, 0, 0)");
从表中取数据
既然COFFEES表中有了数据,您就可以编写SELECT语句访问这些数据了。下面SQL语句中的星号(*)指出所有的列都应该选出。由于没有WHERE语句限制要选出的行,所以下面的SQL语句将检出整张表:
SELECT * FROM COFFEES
执行结果是检出整张表,如下所示:
COF_NAME SUP_ID PRICE SALES TOTAL --------------- ------ ----- ----- ----- Colombian 101 7.99 0 0 French_Roast 49 8.99 0 0 Espresso 150 9.99 0 0 Colombian_Decaf 101 8.99 0 0 French_Roast_Decaf 49 9.99 0 0
如果直接在数据库系统中输入上面的SQL查询,就可在屏幕上看到上面的结果。Java应用程序访问数据库时要先检出数据以便使用。下一节会看到如何实现。
下面是另一条SELECT语句;这条语句将检出咖啡价格表(每磅):
SELECT COF_NAME, PRICE FROM COFFEES
这个查询的结果如下:
COF_NAME PRICE
-------- ---------- -----
Colombian 7.99
French_Roast 8.99
Espresso 9.99
Colombian_Decaf 8.99
French_Roast_Decaf 9.99
上面SELECT语句列出所有咖啡的名称及价格。下面的SQL语句将列出每磅单价小于$9.00的咖啡:
SELECT COF_NAME, PRICE
FROM COFFEES
WHERE PRICE < 9.00
执行结果如下:
COF_NAME PRICE
-------- ------- -----
Colombian 7.99
French_Roast 8.99
Colombian Decaf 8.99