??xml version="1.0" encoding="utf-8" standalone="yes"?>
修改Q-Q-1
dQ-Q-2
|
删除Q-Q-3
修改Q-Q-4
dQ-Q-5
……
理论上可以有Q个操作Q这取决于你用于储存用户权限值的数据cd了?/p>
q样Q如果用h权限Q添加AQ-Q?Q删除Q-Q?Q修改Q-Q?。那用户的权限?purview =2^2+2^3+2^4Q?8Q也是2的权的和了。化成二q制可以表示?1100。这P如果要验证用h否有删除Q的权限Q就可以通过位与q算来实现。在Qava里,位与q算q算W号为&Q即是:
int value = purview &((int)Math.pow(2,3));
你会发现Q当用户有操作权限时Q运出来的l果都会{于q个操作需要的权限|
原理Q?/p>
位与q算Q顾名思义是对位q行与运:
以上面的式子ZQpurview & 2^3 也就是 28&8
它们化成二q制?/p>
11100
Q?01000
-------------------
01000 == 8(十进? Q= 2^3
同理Q如果要验证是否有删除AQ-Q?的权?/p>
可以用:purview &((int)Math.pow(2,0));
卻I
11100
Q?00001
------------------------
00000 == 0(十进? Q= 2^0
q种法的一个优Ҏ速度快。可以同时处理N个权限。如果想验证是否同时有删除AQ-Q?和删除Q-Q?的权限,可以用purview&(2^0+2^3)==(2^0+2^3)?true:false;讄多角色用戗根据权限值判断用L角色?/p>
下面提供一个java的单操作权限判断的代码:
//userPurview是用户具有的L?br />
//optPurview是一个操作要求的权限Z个整敎ͼ没有l过权的Q)
public static boolean checkPower(int userPurview, int optPurview)
{
int purviewValue = (int)Math.pow(2, optPurview);
return (userPurview & purviewValue) == purviewValue;
}
当然Q多权限的验证只要扩展一下就可以了?/p>
几点注意事项Q首先,一个系l可能有很多的操作,因此Q请建立数据字典Q以便查阅,修改时用。其ơ,如果用数据库储存用户权限Q请注意数值的有效范围。操作权限D用唯一的整敎ͼ
?pd 的前几篇文章已经Q?/p>
ij
工具?
未介绍的一个重要Q务是如何修改现有数据。本文介l?SQL DELETE
?UPDATE
语句Q您可以使用它们有选择地删除或修改 Apache Derby 数据库中的现有数据?/p>
要进行本文的CZQ您需要:
ij
命o行工P本系列的 W二文?/a> 有介l?
SELECT
语句的基知识Q本pd?W五文?/a> 有介l?如果您还不具备这些条ӞL保在l箋下文之前完成上述步骤Q通过回顾本系列的前几文章可以很Ҏ地实现?/p>
![]() ![]() |
![]()
|
本文介l的W一个数据修Ҏ术是删除数据。要删除 Apache Derby 数据库中的数据,可以使用 SQL DELETE
语句Q它可以删除表中的所有行Q也可以删除特定的行子集。可以用?Apache Derby 数据库的 SQL DELETE
语句的正式语法相当简单,如下所C:
DELETE FROM tableName
[WHERE clause]
DELETE
语句从指定表中删除满_?WHERE
子句的所有行。如果没有包括Q?WHERE
子句Q则删除表中的所有行。ؓ了演C?DELETE
语句的这U用法,创徏一个时表Q插入几行,然后全部删除Q如 清单 1 所C?
ij> CREATE TABLE bigdog.temp (aValue INT) ; 0 rows inserted/updated/deleted ij> INSERT INTO bigdog.temp VALUES(0), (1), (2), (3) ; 4 rows inserted/updated/deleted ij> SELECT COUNT(*) AS COUNT FROM bigdog.temp ; COUNT ----------- 4 1 row selected ij> DELETE FROM bigdog.temp ; 4 rows inserted/updated/deleted ij> SELECT COUNT(*) AS COUNT FROM bigdog.temp ; COUNT ----------- 0 1 row selected ij> DROP TABLE bigdog.temp ; 0 rows inserted/updated/deleted |
本例创徏保存整数值的单列临时表。您四行插入数据库中,然后执行 SELECT
语句以验证新表包含四行。通过使用无约束的 DELETE
语句Q将删除临时表中的全部四行,q通过来自 Apache Derby 的消?4 rows inserted/updated/deleted
和第二个 SELECT
语句来验证,该语句指明时表包含 0 行。最后,DROP TABLE
语句删除模式中的I?
但是Q一般地Q您不希望删除表中的所有行Q而是有选择地删除行。ؓ此,创徏一个适当?WHERE
子句来标识所有相兌。与 DELETE
一起用的 WHERE
子句的语法与 W?4 部分 中讨论的语法一P该部分提供了完全?SQL SELECT
语句语法。在 WHERE
子句中构造布表辑ּ的基本构建块在那文章的?1 提供Qƈ在本文的 清单 2 中演C,在此您将删除臛_满两个条g之一的所有行?/p>
清单 2. 删除所选行
ij> DELETE FROM bigdog.products WHERE description LIKE '%towel%' OR itemNumber <= 3 ; 5 rows inserted/updated/deleted ij> SELECT itemNumber, description FROM bigdog.products ; ITEMNUMBER |DESCRIPTION ---------------------------------------------------- 4 |Male bathing suit, blue 5 |Female bathing suit, one piece, aqua 6 |Child sand toy set 9 |Flip-flop 10 |Open-toed sandal 5 rows selected |
在本例中Q?code>DELETE 语句包括了一个标?5 行的 WHERE
子句Q您可以通过 ij
工具?Apache Derby q回的帮助消?5 rows inserted/updated/deleted
中看到?code>WHERE 子句包含?OR
操作W联l的两个表达式,q意味着对于特定行,如果M表达式gؓ TRUE
Q则删除该行?
W一个表辑ּ查找产品描述中包含单?“towel” 的所有行。如果回忆本pd前几文章(或者在 DELETE
语句之前执行 SELECT
语句Q,?bigdog.products
表中有两?towelQ其 itemNumber
列gؓ 7 ?8。另一个表辑ּ选择 itemNumber
列值小于或{于 3 的所有行?code>bigdog.products 表的内容最l用一个简单的 SELECT
语句昄Q展CZ只有原来 10 行中?5 行保留在表中?
您还可以包括 W?5 部分 中讨论的 SQL 函数以获得对删除行的选择的更多控Ӟ但是本例中没有明演C些函数的使用。可用于 DELETE
语句?WHERE
子句中的相同函数和其他操作符q可以与 UPDATE
语句一起用,从而有选择C改表中行的|如下一节所q?
![]() ![]() |
![]()
|
您需要进行的处理数据的最后一?SQL d是更新表中选定行的特定列倹{在某种E度上,SQL UPDATE
语句?SQL INSERT
?DELETE
语句的联合,因ؓ您必选择要修改的行,q必L定如何修改它们。Ş式上Q?code>UPDATE 语句语法非常单,因ؓ您必L定要更新的行集合的新的列|?清单 3 所C?
UPDATE tableName SET columnName = Value [ , columnName = Value} ]* [WHERE clause] |
如该 SQL 语法所C,SQL UPDATE
语句必须臛_h一?SET
lg来更C列,以及一个或多个 SET
lg和一?WHERE
子句Q这些是可选的。如果没有包?WHERE
子句Q则 UPDATE
语句修改表中所有行的指定列?
执行 UPDATE
语句相当ҎQ如 清单 4 所C,其中修改了单个行的两列?
ij> SELECT itemNumber, price, stockDate FROM bigdog.products WHERE itemNumber = 6 ; ITEMNUMBER |PRICE |STOCKDATE ------------------------------- 6 |9.95 |2006-01-15 1 row selected ij> UPDATE bigdog.products SET price = price * 1.25, stockDate = CURRENT_DATE WHERE itemNumber = 6 ; 1 row inserted/updated/deleted ij> SELECT itemNumber, price, stockDate FROM bigdog.products WHERE itemNumber = 6 ; ITEMNUMBER |PRICE |STOCKDATE ------------------------------- 6 |12.43 |2006-06-20 1 row selected |
本示例在 UPDATE
语句的前后都使用?SELECT
语句Q以证实对目标行的更攏V?code>SELECT 语句?bigdog.products
表选择了单个行Q?code>itemNumber 列gؓ 6 的行Q的三列?code>UPDATE 语句修改该特定行?price
?stockDate
列?code>price 列中的值增?25%Q例如,可能׃货品很抢手)Q?code>stockDate 列被修改以保存当前日期,通过?SQL 查询中?CURRENT_DATE
内置函数Q可以在 Apache Derby 中很Ҏ获得该日期?
Apache Derby 包括一些内|函敎ͼ您可以用它们获得与当前数据库连接相关的数据。这些内|函数的完整列表??1 所C?/p>
?1. Apache Derby SQL 当前函数
函数 | 描述 |
---|---|
CURRENT_DATE |
以合适的 Apache Derby DATE 格式q回当前日期 |
CURRENT_ISOLATION |
以两字符字符串返回当前事务处理隔ȝ别,q将在后l文章中详细讨论 |
CURRENT_SCHEMA |
以最?128 个字W的字符串返回模式名Uͼ用于限定未限定的数据库对象名U?/td> |
CURRENT_TIME |
以合适的 Apache Derby TIME 格式q回当前旉 |
CURRENT_TIMESTAMP |
以合适的 Apache Derby TIMESTAMP 格式q回当前旉?/td>
|
CURRENT_USER |
以最?128 个字W的字符串返回当前用L授权标识W,如果没有当前用户Q则q回 APP |
上例演示了如何修改单个表中特定行的多个列倹{但是有时候,用于选择要更新的行的逻辑比较复杂。例如,假设您需要修?bigdog.products
表中?Quiet Beach Industries 中获得的所有对象的hQQuiet Beach Industries ?bigdog.vendors
表中 vendorNumber
列的gؓ 3。ؓ此,您需要用嵌入式查询Q如 清单 5 所C?
ij> UPDATE bigdog.products SET price = price * 1.10, description = 'NEW: ' || description WHERE itemNumber IN ( SELECT v.itemNumber FROM bigdog.products as p, bigdog.vendors as v WHERE p.itemNumber = v.itemNumber AND v.vendorNumber = 3 ) ; 2 rows inserted/updated/deleted ij> SELECT * FROM bigdog.products ; ITEMNUMBER |PRICE |STOCKDATE |DESCRIPTION ------------------------------------------------------------------------ 4 |29.95 |2006-02-10|Male bathing suit, blue 5 |49.95 |2006-02-20|Female bathing suit, one piece, aqua 6 |12.43 |2006-06-20|Child sand toy set 9 |14.24 |2006-03-12|NEW: Flip-flop 10 |38.44 |2006-01-24|NEW: Open-toed sandal 5 rows selected |
在本例中Q?code>UPDATE 语句修改?bigdog.vendors
表中 vendorNumber
列gؓ 3 的供应商获得的所有品的 price
?description
列。因Z能在 UPDATE
语句中进行简单联l,所以必d WHERE
子句中包括子查询Q以提取与来?Quiet Beach Industries 的品对应的 itemNumber
行?code>UPDATE 中的 WHERE
子句使用 IN
操作W选择 itemNumber
列值属于嵌入式子查询所选的值集合的那些行?
两种查询可以用于 UPDATE
语句?WHERE
子句中:标量子查?/em> ?em>表子查询。标量子查询是一U嵌入式查询Q返回包含单个列的单个行Q本质上是单个|该值称?em>标量。可以用标量子查询选择用?WHERE
子句的表辑ּ中的特定倹{例如,itemNumber = (标量子查?
更新 itemNumber
列g标量子查询结果匹配的M行?
另一斚wQ表子查询可以返回多个行Q这些行通常只有一列。在某些情况下,表子查询可以包含多个列。要使用表子查询Q需要?SQL 操作W将嵌入式查询与布尔表达式组合在一赗例如,如上一代码清单所C,IN
操作W选择 bigdog.products
表中?Quiet Beach Industries 生的所有行?code>IN 操作W是可以用于表子查询的四?SQL 操作W之一。全部四个操作符??2 所q?
操作W?/th> | CZ | 描述 |
---|---|---|
IN |
itemNumber INQ表子查询) |
如果表达式的值在表子查询中,则返?TRUE Q该表子查询只能q回单个列。可以包?NOT 操作W,?NOT IN Q以仅选择不在表查询中的行?/td>
|
EXISTS |
EXISTSQ表子查询) |
如果表子查询q回M行,则返?TRUE Q如果没有选择M行,则返?FALSE 。这意味着Q取决于表子查询选择的行敎ͼ修Ҏ有行或不修改M行。可以包?NOT 操作W以反{该规则?/td>
|
ALL |
itemNumber = ALLQ表子查询) |
UCؓ量化比较Q因?ALL 关键字修Ҏ较操作符Q?code>=?code><?code>>?code><=?code>>= ?<> 之一Q,所以仅当对所有行都ؓ真时Q结果才?TRUE 。该表子查询可以q回多个行,但它们必d有一个列?/td>
|
ANY |
itemNumber = ANY Q表子查询) |
另一个量化比较,但是在这个查询中Q如果它对于M行ؓ真,则结果ؓ TRUE ?code>SOME 可以用作 ANY 的同义词。该表子查询可以q回多个行,但它们必d有一个列?/td>
|
通过使用 ?2 中的信息Q应该看到如果您重新~写 清单 4 ?UPDATE
语句中的 WHERE
子句Q以使用量化比较和相同的表子查询 WHERE itemNumber = ANY (...)
Q您获得相同的l果。如果?ALL
操作W和相同的表子查询,则不更新M行,因ؓ bigdog.products
表中的所?itemNumber
g在表查询中。另一斚wQ如果?EXISTS
操作W,则将修改所有行Q因有一?itemNumber
值存在于表子查询中?
![]() ![]() |
![]()
|
上一节讨Z修改表中现有的数据。还可以修改数据库表的结构或模式。这可以采用d列、更改列的数据类型、添加约束或者甚臛_除列的方式来实现?该过Eƈ不简单,所以当您开始设计模式时一定要认真。如果不需要修改表的结构,则需要用时表Q如 清单 6 所C?
ij> CREATE TABLE bigdog.newProducts ( itemNumber INT NOT NULL, price DECIMAL(5, 2), stockDate DATE, count INT NOT NULL DEFAULT 0, description VARCHAR(40) ) ; 0 rows inserted/updated/deleted ij> INSERT INTO bigdog.newProducts(itemNumber, price, stockDate, description) SELECT itemNumber, price, stockDate, description FROM bigdog.products ; 5 rows inserted/updated/deleted ij> DROP TABLE bigdog.products ; 0 rows inserted/updated/deleted ij> RENAME TABLE bigdog.newProducts TO products ; 0 rows inserted/updated/deleted ij> SELECT * FROM bigdog.products ; ITEMNUMBER |PRICE |STOCKDATE |COUNT |DESCRIPTION ------------------------------------------------------------------------------------ 4 |29.95 |2006-02-10|0 |Male bathing suit, blue 5 |49.95 |2006-02-20|0 |Female bathing suit, one piece, aqua 6 |12.43 |2006-06-20|0 |Child sand toy set 9 |14.24 |2006-03-12|0 |NEW: Flip-flop 10 |38.44 |2006-01-24|0 |NEW: Open-toed sandal 5 rows selected |
如本例所C,要修改表Q在本例中是一个新?count
d?bigdog.products
表中Q首先要创徏一个具有需要的正确模式的表。本例需要包括列U束 NOT NULL
使之始终h有效的|q过使用列约?DEFAULT 0
?count
列分配默认?0。注意如何通过列序列出来合q多列约束?
下一步是现有数据从原始表复制到新表中。可以通过使用 SQL INSERT
语句来实玎ͼ该语句用一个子查询来获得要插入的倹{这是一U功能强大的技术,允许您很Ҏ地将现有表的全部或部分复制到W二个表中?
创徏新表q复制了合适的数据之后Q通过使用 SQL DROP TABLE
语句删除旧表Qƈ通过使用 SQL RENAME TABLE
语句新表重命名为原来的名称。重命名操作十分单:?oldTableName 重命名ؓ newTableNameQ但不ؓ新表名提供模式名Uͼ因ؓ RENAME
操作不能在不同的数据模式间移动表。本例最后执?SELECT
语句以显C新 bigdog.products
表的模式和内宏V可以看刎ͼ新表h 5 列,count
列始lؓ 0。这Ӟ真正的应用程序将通过执行必要?SQL UPDATE
语句来适当修改 count
列?
![]() ![]() |
![]()
|
本文专门介绍修改 Apache Derby 数据库中的数据。讨论的W一U数据修Ҏ术是数据删除Q这通过使用 SQL DELETE
语句来执行。然后?SQL UPDATE
语句来修改表中选定行的列倹{最后,使用临时表来修改现有数据表的l果。本文还演示了如何通过使用嵌入式子查询来修Ҏ较复杂的数据库模式。下一文章将介绍其他一些高U的数据库主题,之后本系列将开始讨论如何从 Java 应用E序q接?Apache Derby 数据库?/p>
INSERT
语句数据插入表中的基本原理Q其中包括查看用不同方式插?10 个新行的CZ。最后,本文展示了一个脚本,该脚本自动化?INSERT
操作q显C新插入的数据以供验证?/blockquote>
在本pd的上一文?“?Apache Derby q行数据库开发,W?2 部分Q模?/a>”Q?006 q?4 月)Q在 脚本文g不难使用Q如 清单 1 所C的W一?Derby SQL 脚本CZ?/p>
ij
工具的提C符处直接执?SQL 命o。通过使用 ij
工具Q可以简单地用不同的 SQL ?Derby 命oq行试验。但是,通常您将需要执行多个复杂的命o。ؓ了简化调试一l复杂的 SQL 命oQ将其写入文本文件中然后一ơ执行文本文件中的所有命令通常更加Ҏ。该操作被称?em>q行 SQL 脚本Q可以通过使用 Apache Derby 很容易地实现该操作。通过?SQL 命o攄在脚本文件中Q您获得能够根据需要多ơ执行命令的附加好处?/p>
清单 1. W一?Derby SQL 脚本
-- Ignore the database not created warning if present connect 'jdbc:derby:test;create=true' ; -- First delete the tables if they exist. -- Ignore the table does not exist error if present DROP TABLE bigdog.products ; DROP TABLE bigdog.vendors ; -- CREATE the products table for bigdog's Surf Shop CREATE TABLE bigdog.products ( itemNumber INT NOT NULL, price DECIMAL(5, 2), stockDate DATE, description VARCHAR(128) ) ; -- CREATE the products table for bigdog's Surf Shop CREATE TABLE bigdog.vendors ( itemNumber INT NOT NULL, vendornumber INT NOT NULL, vendorName CHAR(64) ) ; exit ; |
清单 1 所C的脚本重新创徏了本pd上一文章中演示?bigdog
模式和两个表Q?code>products ?vendors
Q。如果不清楚其中M一个概念,在l本文之前您应该q回q?阅读该文?/a>。因为本文将介绍数据插入表的基本原理,所以您首先需要创建准备接受新数据的表?
![]() |
|
无需用于创?SQL 命o直接输入?Derby ij
工具中,您可以将其放入文本文件中Qƈ?ij
工具直接q行文g中的命o。本文包括一?.zip 文gQ参?下蝲 一节以讉K该文ӞQ其中包含两个脚本文Ӟ一个是 derby.create.sqlQ如 清单 1 所C。因为本文将逐步介绍该脚本文件中的代码行Q所以您既可以参?清单 1 所C的代码Q也可以用您偏爱的文本编辑器打开该脚本文件?
该脚本文件包括了用两个破折号 (--
) 开头的几行。这些行?SQL 注释Q您应该使用它们来提供脚本文件中每个主要lg的用途的基本描述?脚本中的W一个实际命令是 Derby connect
命oQ它告诉 ij
工具q接 test
数据库,必要的话要先创徏数据库。下一个命令是 SQL DROP
语句Q它删除 bigdog
模式中的产品和供应商表。如果表不存在(当数据库刚创建时׃出现q种情况Q,显CZ条错误消息;但前面的 SQL 注释指明Q您可以安全地忽略这些消息?
如果存在的话Q首先放弃这些表Q以便您可以用所需的正的列定义创建新表。后两条 SQL 语句执行该操作Q在 bigdog
模式中创Z品和供应商表。脚本以 exit
命ol束Q终止了与数据库的连接,q允?ij
工具优雅地退出。下一步将学习如何执行 Derby 脚本文g?/p>
脚本文g仅在可用于执行文件中列出的命令时才有用。要执行 SQL 脚本文g中的命oQ最单的Ҏ是从 ij
工具中运行脚本文件。但是,在可以运行之前,需要创Z个测试目录ƈ展开 derby4.zip 文gQ该文g可在本文下蝲Q参?下蝲 一节)。该q程?清单 2 所C?
rb$ mkdir test rb$ cp derby4.zip test/ rb$ cd test/ rb$ unzip derby4.zip Archive: derby4.zip inflating: derby.create.sql inflating: derby.insert.sql rb$ ls derby.create.sql derby.insert.sql derby4.zip rb$ java org.apache.derby.tools.ij ij version 10.1 ij> run 'derby.create.sql' ; ij> -- Ignore the database not created warning if present connect 'jdbc:derby:test;create=true' ; ij> -- First delete the tables if they exist. -- Ignore the table does not exist error if present DROP TABLE bigdog.products ; ERROR 42Y07: Schema 'BIGDOG' does not exist ij> DROP TABLE bigdog.vendors ; ERROR 42Y07: Schema 'BIGDOG' does not exist ij> -- CREATE the products table for Bigdog's Surf Shop CREATE TABLE bigdog.products ( itemNumber INT NOT NULL, price DECIMAL(5, 2), stockDate DATE, description VARCHAR(128) ) ; 0 rows inserted/updated/deleted ij> -- CREATE the products table for Bigdog's Surf Shop CREATE TABLE bigdog.vendors ( itemNumber INT NOT NULL, vendornumber INT NOT NULL, vendorName CHAR(64) ) ; 0 rows inserted/updated/deleted ij> exit ; |
虽然 清单 2 g对于执行 Derby 脚本有些冗长Q但q程十分单。该CZ假设您具有开攄l端Q或Windows Command q程H口Q但要注意,本例中的一些步骤是特定?UNIX® 的)Qƈ且您已经更改C存包含本文提供的 两个脚本文g ?derby4.zip 文g的目录。要最化M错误的几率,首先创徏一个新目录Q将 derby4.zip 文g复制到新目录中,q更改到q个新目录。然后展开CZ .zip 文g。如目录清单所C,现在您在新目录中h三个文gQderby4.zip、derby.create.sql ?derby.insert.sql。现在,您将只?create 脚本文gQ?insert 脚本文g在本文的最后用?
![]() |
|
清单 2 的其余部分展C如何从 Derby 当该脚本执行Ӟ您可能会看到? 虽然? 本节介绍从命令行q行脚本的两U方法。第一U方法如 清单 3 所C?ij
工具中执?derby.create.sql 脚本文g?首先启动 ij
工具。如果启动时出现问题Q您可能需要回?本系列第一文?/a> 中提供的 Derby 安装验证步骤。看?ij>
提示之后Q就可以q行合适的脚本文g了。通过使用 run
命o可实现该操作Q该命o接受单个参数Q单引号括v的脚本文件名?/p>
ij>
提示、命令和警告或错误消息的l合。这U显C可能有些笨拙,?run
命o会执行您的脚本文Ӟ像您直接将命o键入 ij
工具中一栗最后,处理 exit
命oQ脚本完成,关闭 ij
工具。如果第一个脚本执行的输出?清单 2 所C的相匹配,那么恭喜您了。您现在已经有了一个带有两个可以保存数据的新表的新试数据库了?ij
工具中执行脚本十分有效,但是有时候进一步自动化该过E会更加Ҏ。下一节将讨论如何从命令行直接执行 Derby 脚本文g?
清单 3. 从命令行q行 SQL 脚本
rb$ java org.apache.derby.tools.ij derby.create.sql ij version 10.1 ij> -- Ignore the database not created warning if present connect 'jdbc:derby:test;create=true' ; WARNING 01J01: Database 'test' not created, connection made to existing database instead. ij> -- First delete the tables if they exist. -- Ignore the table does not exist error if present DROP TABLE bigdog.products ; 0 rows inserted/updated/deleted ij> DROP TABLE bigdog.vendors ; 0 rows inserted/updated/deleted ij> -- CREATE the products table for Bigdog's Surf Shop CREATE TABLE bigdog.products ( itemNumber INT NOT NULL, price DECIMAL(5, 2), stockDate DATE, description VARCHAR(128) ) ; 0 rows inserted/updated/deleted ij> -- CREATE the products table for Bigdog's Surf Shop CREATE TABLE bigdog.vendors ( itemNumber INT NOT NULL, vendornumber INT NOT NULL, vendorName CHAR(64) ) ; 0 rows inserted/updated/deleted ij> exit ; |
清单 3 展示了直接从命o行执行脚本文件的W一U方法。在q种情况下,提供脚本文g名作?ij
工具的命令行参数。脚本文件中的行像以前一栯取,q序处理。如果首先从 ij
工具中直接执?derby.create.sql 文gQ现在在命o行运行相同目录中的同一脚本文gQ您应该会看到类g 清单 3 中的输出Q一切都在清单中W一行之后)。如上所C,您收C条警告消息,指明试数据库未创徏Q因为它已经存在。但是,q次您不会收到指明不能放弃两个表的错误消息,因ؓ您已l创Z它们Q如 清单 2 所C)。在攑ּ产品和供应商表之后,您重新创建它们,脚本退出?
q有另一U方法来q行 Derby 脚本Q重定向 ij
工具的标准输入以从脚本文件中d。在Z UNIX 的操作系l中Q通过使用适合您的 shell ?STDIN 重定向字W最Ҏ实现了,比如?Bash shell 使用于?(<
)。这U方法在 清单 4 中展C,h减少屏幕上显C的输出量的好处?
rb$ java org.apache.derby.tools.ij < derby.create.sql
ij version 10.1
ij> WARNING 01J01: Database 'test' not created, connection made to existing database instead.
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
ij> 0 rows inserted/updated/deleted
ij> 0 rows inserted/updated/deleted
ij> 0 rows inserted/updated/deleted
ij> 0 rows inserted/updated/deleted
ij>
rb$
|
?清单 4 中可以看刎ͼ当您通过重定?ij
工具的标准输入执行脚本时Q惟一昄的文本是来自 ij
工具的消息,其中包括 0 rows inserted/updated/deleted
{信息消息或警告和错误消息。如果想要消除这些消息,可以重定?ij
工具的标准输出和标准错误。例如,如果正在 Bash shell 中工作,则可以?
java org.apache.derby.tools.ij < derby.create.sql > derby.create.out 2> derby.create.err
实现q一点,它运?derby.create.sql 脚本文gQ将输出消息保存?derby.create.out
中,q将所?ij
错误消息保存?derby.create.err
中?
现在您将x使用 Apache Derby 数据插入表的过E。要l箋q行Q您需要一?Derby 数据库,它必d有可用的产品表。如果您q未实现此步骤,您需要执?derby.create.sql 脚本文g?
![]() ![]() |
![]()
|
构徏数据库应用程序时最重要的Q务之一是将数据插入到数据库中。这与数据库软g的好坏无养I如果坏数据攑օ数据库中Q其他一切都不重要了。有许多Ҏ可以数据插入数据库中,但下文将主要使用 SQL INSERT
语句数据插?Apache Derby 数据库中?
在?SQL INSERT
语句数据插?Apache Derby 数据库中之前Q必ȝ道如果正地使用该语句?a >清单 5 提供?Apache Derby ?SQL INSERT
语句的完整语法?
INSERT INTO table-Name [ (Simple-column-Name [ , Simple-column-Name]* ) ] Expression |
该语法应该比较熟悉。如本系列的 上一文?/a> 所qͼҎ?( 其中Q最后两个超Z本文范围Q将在后l文章中详细介绍。前两个怼Q惟一的区别在于第一UŞ式将一行插入表中,而后一UŞ式将多行插入表中? 可以使用 SQL SQL [
]
) 包括可选参数。其用途不是立x楚的惟一lg?Expression
Q但q个单的短语能够有多复杂呢?当然Q外表可能会蒙蔽人;Expression
词可以扩展ؓ下列四个不同的结构之一Q?/p>
VALUES
列表
VALUES
列表
SELECT
表达?
UNION
表达?INSERT
语句的可选部分指定要插入到表中的值的列顺序。默认情况下Q数据插入到表中的列序与创时列的列出顺序相同。有时候您希望更改q种序或可能希望只为具?NOT NULL
U束的列指定倹{通过?SQL INSERT
语句中显式列出列Q您获得对操作的更多控Ӟq可以更Ҏ地处理这些特定的用例?VALUES
表达式的语法相当单,?清单 6 所C?
清单 6. SQL VALUES 语法
{ VALUES ( Value {, Value }* ) [ , ( Value {, Value }* ) ]* | VALUES Value [ , Value ]* } |
该语法首先显C多行格式,然后是单行格式(CQ竖U字W?|
表示或?/em>Q星号字W?*
表示一个或多个Q?code>value 词表C想要插入特定列的倹{要数据插入多列,必须一行的数据括在逗号分隔的括号内?
下面两节展示要实现的语法CZ?
?清单 7 所C,要将数据插入表中Q首先需要启?ij
工具q连接数据库。记住,要将数据插入表中Q表必须存在。如果还没有表的话,则执行本文之前所q的用于创徏表的脚本?/p>
清单 7. 插入单行
rb$ java org.apache.derby.tools.ij ij version 10.1 ij> connect 'jdbc:derby:test' ; ij> INSERT INTO bigdog.products VALUES(1, 19.95, '2006-03-31', 'Hooded sweatshirt') ; 1 row inserted/updated/deleted ij> INSERT INTO bigdog.products(itemNumber, price, stockDate, description) VALUES(2, 99.99, '2006-03-29', 'Beach umbrella') ; 1 row inserted/updated/deleted ij> INSERT INTO bigdog.products(itemNumber, price, stockDate) VALUES(3, 0.99, '2006-02-28') ; 1 row inserted/updated/deleted ij> exit ; |
本例展示了对 bigdog.products
表的三个单行插入。第一?SQL INSERT
语句没有提供列列表;它插?itemNumber
?code>price?code>stockDate ?description
。注意,插入?stockDate
?description
列的值括在单引号字符中?code>description 列是长度可变的字W串Q所以它预计是一个字W串Q通过字W数据括在单引号中指明)。另一斚wQ?code>stockDate 列是一个日期列Q它需要您日期括在单引号中以正确解析出正的日、月和年信息。(有关 SQL INSERT
操作期间数据cd格式的更多指南,请阅读联机文档或参阅本系列的 上一文?/a>。)
W二?SQL INSERT
语句昑ּ列出所有四列ƈ相应地插入新倹{最后一?SQL INSERT
语句只列Z列ƈ只插入三个倹{?code>description 列留为空白,q意味着它将h NULL
倹{?
虽然单行 SQL INSERT
语句可能有用Q但当您需要插入多行时Q直接插入多行可能更有效Q如 清单 8 所C?
rb$ java org.apache.derby.tools.ij ij version 10.1 ij> connect 'jdbc:derby:test' ; ij> INSERT INTO bigdog.products(itemNumber, price, stockDate, description) VALUES (4, 29.95, '2006-02-10', 'Male bathing suit, blue'), (5, 49.95, '2006-02-20', 'Female bathing suit, one piece, aqua'), (6, 9.95, '2006-01-15', 'Child sand toy set'), (7, 24.95, '2005-12-20', 'White beach towel'), (8, 32.95, '2005-12-22', 'Blue-striped beach towel'), (9, 12.95, '2006-03-12', 'Flip-flop'), (10, 34.95, '2006-01-24', 'Open-toed sandal') ; 7 rows inserted/updated/deleted ij> exit ; |
在本例中Q首先启?ij
工具q连接数据库。下一代码行通过昑ּ列出所有四列ƈ为每行提供新|?7 行插入数据库中。如前所qͼ多行插入每个新行的值包括在括号内,q些g间用逗号分隔。该 SQL INSERT
语句执行之后Q?code>ij 工具报告q?7 新行已经插入?
多行插入优于多个单行插入Q但更好的方法是?SQL INSERT
语句攑֜脚本文g中,q行脚本来插入数据。这U方法允许您更容易地修复错误或根据需要重新插入数据,而无需重新创徏必需?SQL INSERT
语句。如前所qͼ可以 随本文下?/a> ?.zip 文g包括两个 SQL 脚本文g。第二个脚本文g (derby.insert.sql) 上一节提供的 10 行插入到数据库中Qƈ执行单查询以昄l果Q从而验证插入操作。执行查询操作的机制在下一文章中详细讨论Q但您不必理解查询就能够q行插入脚本?
要执行脚本,可以选择本文开头展C的三个Ҏ之一。在 清单 9 中,通过重定?ij
工具的标准输入以从脚本文件中d的方式,来执行插入脚本。插?10 行,然后l果昄到屏q上?
$ java org.apache.derby.tools.ij < derby.insert.sql ij version 10.1 ij> ij> 10 rows inserted/updated/deleted ij> ITEMNUMBER |PRICE |STOCKDATE |DESCRIPTION ------------------------------------------------------------------------------- 1 |19.95 |2006-03-31|Hooded sweatshirt 2 |99.99 |2006-03-29|Beach umbrella 3 |0.99 |2006-02-28| 4 |29.95 |2006-02-10|Male bathing suit, blue 5 |49.95 |2006-02-20|Female bathing suit, one piece, aqua 6 |9.95 |2006-01-15|Child sand toy set 7 |24.95 |2005-12-20|White beach towel 8 |32.95 |2005-12-22|Blue-striped beach towel 9 |12.95 |2006-03-12|Flip-flop 10 |34.95 |2006-01-24|Open-toed sandal 10 rows selected ij> ij> rb$ |
![]() ![]() |
![]()
|
本文讨论了两个主要主题。首先向您介l了 SQL 脚本文g的概念,该脚本文件可用于以自动方式执行多?SQLQ或 DerbyQ命令。?Apache Derby ij
工具执行 SQL 脚本文g有三U方法:从工具中、?run
命o或直接从命o行用这两种Ҏ之一。然后,您回了 INSERT
语句?SQL 语法Qƈ查看了如何用该语句数据插?Derby 数据库中的示例。后l文章将在此基础上查询、更新和删除 Apache Derby 数据库中的数据?/p>
![]() ![]() |
![]()
|
描述 | 名字 | 大小 | 下蝲Ҏ |
---|---|---|---|
Derby SQL scripts for this article | derby4.zip | 1KB | HTTP |
![]() |
||||
![]() |
关于下蝲Ҏ的信?/a> | ![]() |
在开发数据库应用E序之前Q需要理解它的基本概c这一节介l在 Apache Derby 中可以用的数据cdQ以及对设计和创建有用的 Derby 数据库应用程序的能力有媄响的规则?
关系数据库容Ux据。数据可以是不同cd的,例如数值型、字W型或日期型。在数据库中Q数据被l织到叫?em>?/em> 的逻辑单元中。表像工作一P因ؓ它包含数据行。每行由许多列组成。列容纳特定数据cd的数据,例如整型值或字符丌Ӏ在多数情况下,一个数据库有多个表。ؓ了将表关联在一P数据库设计师利用表之间的自然Q或ZؓQ链接。在工作中Q可以通过单元格的值链接不同工作簿中的行。同L概念在关pL据库中也存在Q用来进行链接的列叫?em>键列Qkey columnQ?/em>?
Z让表或列的用途更Ҏ理解Q应当选择合适的名称。对于不同的数据库,命名U定可能不同。对?Apache Derby 数据库系l,名称应当Q?/p>
通过把名U放在双引号中,可以避开 q些规则Q用双引号允许名称区分大小写以及包含附加字W(包括I格Q。但是,q么做通常是不好的做法Q它要求名称总被括在双引号中Q很Ҏ把维护代码的其他人弄p涂?/p>
![]() |
|
兌的表通常l织在一P形成一?em>模式QschemaQ?/em>。可以把模式当成特定数据库中所有相关结构定义的容器。在指定模式中,表的名称必须惟一。所以,通过使用模式Q可以在不同模式的范围内拥有名称相同的对象(例如表)。在使用 Apache Derby 数据库时Q表d模式中。如果没有显式地指定模式QDerby ׃隐式C用内|的 apps
模式。叫?sys
的第二个内置模式用来隔离pȝ表?/p>
可以用模式名对名U进?em>限定QqualifyQ?/em>。要做这件事Q可以在模式名后加圆点,然后加表名。例如, 从抽象意义上来说Q这些数据库概念看v来可能让人淆。但在实践上Q它们相当简单。例如,假设有一个商店,叫做 Bigdog's Surf ShopQ这家店销售各U商品,例如太阳镜、衬衫等{。如果想赢利Q就必须理库存Q以便可以容易地订购额外的商品或改变供应商,从而把开支控制在最。跟t这些信息的一个简单方法,是用表格式~写条目Q如 ?1 所C? 从这个简单的可视设计中,可以Ҏ地把业务逻辑直接映射到数据库表。有两个表:Products ?VendorsQ它们自然地通过商品名称链接在一赗列的数据类型很Ҏ定。这文章其余的部分侧重于?Derby 数据库中创徏 Bigdog's Surf Shop 的示例模?—?模式中包含这两个表? 数据库系l会成ؓ软g中复杂的部分Q特别是在规模扩大到支持企业U应用程序的时候。所以,可以惛_每个数据库都会有自己的应用程序编E接口(APIQ,而这?API 可能彼此不同。当关系数据库刚开发出来的时候,情况是q样。但是,q运的是Q许多开发商同意开发一个标准的语言Q用来访问和操纵数据库。这个语aUCl构化查询语aQ或 SQLQ发x sea-quillQ。至今已lŞ成了多个官方标准版本Q包?1992 q的版本Q这一版被UCؓ SQL-92Q还?1999 q的版本被称?SQL-99。Apache Derby 数据库ؓ SQL-92 标准提供了几乎完整的实现Q所以用 Deryby 开发的应用E序可以Ҏ地移植到其他数据库系l?/p>
SQL 有两个主要部分:数据定义语言QDDLQ和数据操纵语言QDMLQ。DDL 命o用来创徏、修Ҏ删除数据库中的项目(例如表)。DML 命o用来在数据库表中d、修攏V删除或选择数据。这文章后面的部分提供对 SQL ?DDL 部分的基本介l。未来的文章侧重于 DML 命o和更高?DDL 命o?/p>
SQL 作ؓ一个编E语aQ定义了丰富的数据类型层ơ结构。数据库已经变得更强大了Q所以这个类型层ơ结构也变得更复杂。但是最单的数据库ƈ不要求用所有允许的cdQ通常只需要保存数值型、字W型和日期(或时_数据。ؓ了简单,?1??? 昄?Derby 中实现的基本 SQL 数据cd?/p>
如表 1 所C,Derby 提供了对三种整型数据cd的支持。这些类型由它们可以保存的整数的范围区分Q也是由它们在数据库中需要的存储I间区分。在设计数据库时要记住的一个关键问题就是,应当一直把表用的I间控制在最。一般来_表越,性能高。但是必能够在生成的表中保存需要的数据?31 {于 2,147,483,648Q?63 {于 9,223,372,036,854,775,808Q所以用这些类型可以保存非常大的整敎ͼ 多数数值型数据不能用整数表C。Derby 对实数提供了多种格式的支持:单精度Q炏V双_ֺ点以及准确的算术表C,如表 2 所C? 如果从未遇到q准精度数据类型,那么对算术类型和点cd可能有些qh。区别在于一个事实:计算Z使用的QҎ据类型无法包含每个实数。这看v来可能有些怪,但是x实数的数量是无限的。大多数实数都无法保存在几个字节的内存中。对于某些应用程序,_ֺ的损失是可以接受的,而在许多情况下,则不可接受。例如,财务应用E序不能容忍仅仅因ؓ某个数字不能保存在计机中,损失金钱? q个问题的解x案是使用 bigdog.products
表示 bigdog
模式中的 products
表。没有相应的模式名,表名p认ؓ?em>未限定的QunqualifiedQ?/em>Q例?products
。当模式名和表名都完全指定的时候,像 bigdog.products
Q名U被UCؓ完全限定的(fully qualifiedQ?/em>?/p>
?1. Bigdog's Surf Shop 的示例模?/strong>
回页?/strong>
SQL NULL cd
在开始创建数据库表之前,必须知道列没有指定值的时候要做什么。ؓ了理解这一点,h像一下填?Web 表单时的情况。如果某个具体列为空Q那么插到数据库中的是什么呢Q可以想像,如果必须跟踪无?/em> 标记Q问题会很麻烦。幸q的是,SQL 定义了一个特D|NULL
Q表C列没有倹{?
数据cd
最?/th>
最大?/th>
CZ
说明
SMALLINT
-32768 (-215)
32767 (215 - 1)
itemNumber SMALLINT
2 字节整数表示
INT
-231
231 - 1
itemNumber INT
4 字节整数表示
BIGINT
-263
263 - 1
itemNumber BIGINT
8 字节整数表示
数据cd
最?/th>
最大?/th>
CZ
说明
REAL
-3.402x10+38
3.402x10+38
price REAL
IEEE 点敎ͼ4 字节Q?/td>
DOUBLE
-1.79769x10+308
1.79769x10+308
price DOUBLE
IEEE 点敎ͼ8 字节Q?/td>
DECIMAL
31 Q最大精度)
price DECIMAL(5,2)
准确术表示
DECIMAL
数据cdQ它可以控制计算机存储的数字位数Q?em>_ֺDECIMAL
数据cd模拟了整数类型?
数值类型有多个同义词。例如,DECIMAL
数据cd可以~短?DEC
或表CZؓ NUMERIC
?code>DOUBLE cd也可以表CZؓ DOUBLE PRECISION
Q虽然ؓ什么在需要双_ֺ数字时要输入额外的单词,原因不明。更常用的同义词?FLOAT
cdQ它拥有L的Q点精度,可以在声明数据类型时指定Q例?FLOAT(val)
。精度必L于 53 的正整数Q如果不是,׃出错。如果指定了于{于 23 的精度|FLOAT(val)
q价于 REAL
Q如果精度在 24 ?53 之间Q那?FLOAT(val)
{h?DOUBLE
?
除了数值类型,数据库中最常用的保存数据的另一个类型是字符数据。字W数据的CZ包括产品说明、h名或地址信息。Derby 提供了保存字W数据的两个单技术:CHAR
cd?VARCHAR
cdQ详情如?3 所C。对于这两种cdQ都可以指定 length
参数Q如果没指定Q默认ؓ 1。在q两个字W数据类型之间有两个主要区别。首先,CHAR
cd的最大长度是 254 个字W,?VARCHAR
cd最多可以容U?32,672 个字W。第二个区别比较微妙Q?code>CHAR cd的长度L指定的长度。如果没有指定够的字符Q那么会插入额外的空白来填满剩余位置。而?VARCHAR
Ӟ字符的数量是可变的,不执行额外的填充?
数据cd | 最大长?/th> | CZ | 说明 |
---|---|---|---|
CHAR |
254 | description CHAR(128) |
定长字符?/td> |
VARCHAR |
32,672 | description VARCHAR(128) |
变长字符?/td> |
因ؓ长度可变Q所?VARCHAR
cd在实际的存储I间斚w会更有效率,但在性能上效率就会更低?code>CHAR 数据cd有助于性能提高Q因为数据库切地知道每?CHAR
列有多大Q所以在d数据时就可以执行某种性能优化?code>VARCHAR 列的最大长度看h可能_大了Q但?Derby q提供了更大的字W数据类型,q个cd在未来的文章中讨论?/p>
Derby 提供了最后一cȝ单的数据cd来保存日期和旉Q如?4 所C?code>TIME 数据cd?24 时格式保存时、分钟和U(HH:MM:SS
Q?code>DATE 数据cd保存月、日和年Q可以用不同的格式指定,包括以下格式Q?
yyyy-mm-dd
mm/dd/yyyy
dd.mm.yyyy
数据cd | 最?/th> | 最大?/th> | CZ | 说明 |
---|---|---|---|---|
TIME |
00:00:00 | 24:00:00 | start TIME |
旉表示Q精到U) |
DATE |
0001-01-01 | 9999-12-31 | stockDate DATE |
日期表示Q精到天) |
Derby q提供了 TIMESTAMP
数据cdQ把 TIME
?DATE
数据cdl合C个类型中Q表C准的旉?/p>
![]() ![]() |
![]()
|
目前为止Q已l学习了如何设计表,包括规划表的列和定义每个列的数据cd。在正确地设计了表之后,?SQL 创徏表的Ҏ很单了?a >清单 1 昄了在 Derby 中创的正式语法?
-- Comment describing the purpose and layout of the table CREATE TABLE [schemaName.]tableName ( { <columnDefinition> | <tableLevelConstraint> } [, { <columnDefinition> | <tableLevelConstraint> } ]* ) ; |
W一ơ看q个语法Ӟ可能感觉到迷惑不解。但是有了基之后Q接下来容易了Q而且如果x?DerbyQ对正式语法的理解是必需的。方括号Q?code>[ ?]
Q中的是可选参数。从正式语法中可以看出,模式名是可选的Q在必需的头一个列之后Q创一个列都没有的表是没有意义的)Q其他列定义或表U约束都是可选的?
您可能理解列定义的含义,但是可能不理?em>U束 的意义。约束有两种cdQ表U约束和列约束。约束通过某种方式对列或表q行限制。例如,可以用约束要求列总要有实际的|没有 NULL
|Q或者列中的每个必L惟一的,或者列被自动分配默认倹{在未来的文章中更详细Cl约束?/p>
最后一个结束方括号之后的星P*
Q代表可以包含一个或多个包含V这意味着表必L一个或多个列或表U约束。竖U(|
Q表?“可有可无” 条g。在q个语法CZ中,必须定义一个新列或者定义一个表U约束。花括号Q?code>{ ?}
Q把相关组l在一P而圆括号Q?code>( ?)
Q中是必需的元?。最后,分号Q?code>;Q表C?SQL 语句的结束?
把这些规则投入用则相当单?a >清单 2 昄了如何用 Derby 提供?ij
创徏前面??1 中演C的表?
rb$ java org.apache.derby.tools.ij ij version 10.1 ij> connect 'jdbc:derby:test;create=true' ; ij> CREATE TABLE bigdog.products ( itemNumber INT NOT NULL, price DECIMAL(5, 2), stockDate DATE, description VARCHAR(128) ) ; 0 rows inserted/updated/deleted ij> CREATE TABLE bigdog.vendors ( itemNumber INT NOT NULL, vendorNumber INT NOT NULL, vendorName CHAR(64) ) ; 0 rows inserted/updated/deleted ij> exit ; |
?Derby 数据库进行交互的最单方式是使用 ij
工具Q在q个pd的第一文?“?Apache Derby q行开?—?取得节节胜利QApache Derby 介绍”QdeveloperWorksQ?006 q?2 月)中已l介l过。如果按?清单 2 中的步骤q行Q就会创Z个新的数据库Q名?test
。如?test
数据库已l存在,在发?connect
语句Ӟ会得到警告消息。可以安全地忽略q个警告。接下来Q隐式地创徏一个名?bigdog
的新模式Qƈ昑ּ地创Z个新?—?products
?vendors
—?q两个表保存?bigdog
模式中。模式的创徏所以是隐式的,是因为没有发?CREATE SCHEMA
语句?/p>
products
表有四个列:itemNumber
?code>price?code>stockDate ?description
?code>itemNumber 列提供了每个商品Q或列)的惟一标识Q它上面q有列U束Q强制要求提供正的|NOT NULL
Q。如果没有这个要求,itemNumber
列就无法保持惟一Q因为多个行都可能被分配 NULL
倹{?code>price 列创Zؓ DECIMAL
数据cdQ精度ؓ 5Q刻度ؓ 2。这意味着每个商品的最高h格可以是 $999.99。最后两个列很简单:stockDate
列以 Date
cd保存Q?code>description 列以字符串类型保存,最?128 个字W,使用的空间是实际的字W串长度?
vendors
表有三列Q?code>itemNumber?vendorNumber
?vendorName
。在q个CZ中,itemNumber
?vendorNumber
列都有列U约束(NOT NULL
Q。另外,vendorName
列以字符串类型保存,最大长度ؓ 64。因?vendorName
列用 CHAR
数据cd保存Q所以L保留 64 个字W空间?
在创Z各种目之后Q可能想知道是否有种单的方式可以查看数据库中保存了什么项目。幸q的是,{案是肯定的Q可以?dblook
工具。运行这个工P?清单 3 所C,提供了特定数据库中已l创建的目的详l清单?
rb$ java org.apache.derby.tools.dblook -d jdbc:derby:test -- Timestamp: 2006-03-04 10:52:34.056 -- Source database is: test -- Connection URL is: jdbc:derby:test -- appendLogs: false -- ---------------------------------------------- -- DDL Statements for schemas -- ---------------------------------------------- CREATE SCHEMA "BIGDOG"; -- ---------------------------------------------- -- DDL Statements for tables -- ---------------------------------------------- CREATE TABLE "BIGDOG"."PRODUCTS" ( "ITEMNUMBER" INTEGER NOT NULL, "PRICE" DECIMAL(5,2), "STOCKDATE" DATE, "DESCRIPTION" VARCHAR(128)); CREATE TABLE "BIGDOG"."VENDORS" ( "ITEMNUMBER" INTEGER NOT NULL, "VENDORNUMBER" INTEGER NOT NULL, "VENDORNAME" CHAR(64)); |
dblook
工具是一?Java c,可以用它方便地把数据库的内容输出到控制台。在命o行上q行它,像q行其他 Java E序一P惟一增加的就是?-d jdbc:derby:test
参数Q这个参数指?dblook
工具应当查询的数据库。如果能q行 ij
工具Q那?dblook
cL件就已经存在?CLASSPATH
中了。如果不是这P请参考这个系列中?W一文?/a>Q获得正设|?CLASSPATH
的详l说明。正?dblook
工具的输出所C,test
数据库包?bigdog
模式Q这个模式包?products
?vendors
表。另外,对这两个表的列也有详l描q?
![]() ![]() |
![]()
|
没有什么事情是完美的。当错误地创Z表或者表不再需要的时候,该怎么办?单的{案是从数据库中删除表。而且Q如果必要,再创Z个替代表。删除表很容易,当然q意味着Q在做这件事的时候应当非常小?—?不会弹出对话框要求您认是否真的惛_除!
从数据库中删除(或者更正式地说Q?em>撤下QdropQ?/em>Q一个表的完整语法是Q?
DROP TABLE [schemaName.]tableName ;
语法很简单:把完全限定名U和分号攑֜ DROP TABLE
SQL 命o后面Q就完成了?a >清单 4 中在新创建的临时表上演示了删除表的过E?
rb$ java org.apache.derby.tools.ij ij version 10.1 ij> connect 'jdbc:derby:test' ; ij> CREATE TABLE temp ( aColumn INT ) ; 0 rows inserted/updated/deleted ij> DROP TABLE temp ; 0 rows inserted/updated/deleted ij> exit ; |
![]() ![]() |
![]()
|
现在您已l走上了操作 Apache Derby 数据库的道\。目前您已经掌握了基本的数据库概念,包括模式、表和列Q还看到了用名?Bigdog's Surf Shop 的虚拟公司对q些概念的演C。要操作?Derby q样的数据库Q需要学?SQLQ它是与数据库进行交互的标准语言。这文章还介绍了可以用来在 Derby 数据库中保存数据的基本数据类型。把q些概念融合在一P您学习了如何?Derby 创徏和删除表Q还使用 Derby ?dblook
工具输出了数据库的模式内宏V?/p>
Ethernet头部
|
ARP数据部分
|
|||||||||
Q?/span>
|
Q?/span>
|
Q?/span>
|
2
|
2
|
2
|
2
|
Q?/span>
|
Q?/span>
|
Q?/span>
|
Q?/span>
|
目标MAC地址
|
源地MAC地址
|
cd?/span>0x0800:ip
0x0806:ARP
|
局域网cd
以太|?/span>0x0001
|
|络协议cd
IP|络0x0800
|
MAC/IP地址长度Q恒?/span>0x06/04
|
ARP包类?/span>
REPLY
0x0002
|
ARP目标IP地址
|
ARP目标MAC 地址
|
ARP?/span>IP地址
|
ARP?/span>MAC地址
|
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1370905
然后做了一个ARP监听器,没想到被老师看上了,说是国内JPCAP研究的h不多Q可以考虑写一论文,老师l我推荐发表?/p>
于是有了q么一东ѝ不q现在还不知道老师发哪个刊物去了。。。老师_q没回音。?/p>
注:׃字数限制Q分?部分发?/p>
数据成员
|
|
NetworkInterfaceAddress[]
|
addresses
q个接口的网l地址。设定ؓ数组应该是考虑到有些设备同时连接多条线路,例如路由器。但我们的PC机的|卡一般只有一条线路,所以我们一般取addresses[0]够了?/span>
|
java.lang.String
|
datalink_description.
数据链\层的描述。描q所在的局域网是什么网。例如,以太|(EthernetQ、无ULAN|(wireless LANQ、o牌环|?token ring){等?/span>
|
java.lang.String
|
datalink_name
该网l设备所对应数据链\层的名称。具体来_例如Ethernet10M?span>100M?000M{等?/span>
|
java.lang.String
|
description
|卡是XXXX牌子XXXX型号之类的描q。例如我的网卡描qͼRealtek RTL8169/8110 Family Gigabit Ethernet NIC
|
boolean
|
Loopback
标志q个讑֤是否loopback讑֤?/span>
|
byte[]
|
mac_address
|卡的MAC地址Q?个字节?/span>
|
java.lang.String
|
Name
q个讑֤的名U。例如我的网卡名Uͼ\Device\NPF_{3CE5FDA5-E15D-4F87-B217-255BCB351CD5}
|
数据成员 |
|
int |
dropped_packets 抛弃的包的数目?/span>
|
protected int |
ID q个数据成员在官Ҏ档中q没有做M说明Q查?/span>JPCAP源代码可以发现这?/span>ID实际上在?/span>JNI?/span>C代码部分传进来的Q这cLwƈ没有做出定义Q所以是供其内部使用的。实际上在对JpcapCator实例的用中也没有办法调用此数据成员?/span> |
protected static boolean[] |
instanciatedFlag 同样在官Ҏ档中没有做Q何说明,估计其ؓ供内部用?/span>
|
protected static int |
MAX_NUMBER_OF_INSTANCE 同样在官Ҏ档中没有做Q何说明,估计其ؓ供内部用?/span>
|
int |
received_packets 收到的包的数?/span> |
Ҏ成员 |
|
static NetworkInterface[] |
getDeviceList () q回一个网l设备列表?/span> |
static JpcapCaptor |
openDevice (NetworkInterface interface, int snaplen, boolean promisc, int to_ms) 创徏一个与指定讑֤的连接ƈq回该连接。注意,以上两个Ҏ都是静态方法?/span> InterfaceQ要打开q接的设备的实例Q?/span>
SnaplenQ这个是比较Ҏ搞的一个参数。其实这个参C是限制只能捕捉多数据包Q而是限制每一ơ收C个数据包Q只提取该数据包中前多少字节Q?/span>
PromiscQ设|是否杂模式。处于杂模式将接收所有数据包Q若之后又调用了包过滤函?/span>setFilter()不起Q何作用;
To_msQ这个参C要用?/span>processPacket()ҎQ指定超时的旉Q?/span>
|
void |
Close ()关闭调用该方法的讑֤的连接,相对?/span>openDivece()打开q接?/span> |
JpcapSender |
getJpcapSenderInstance () 该返回一?/span>JpcapSender实例Q?/span>JpcapSendercL专门用于控制讑֤的发送数据包的功能的cR?/span> |
Packet |
getPacket () 捕捉q返回一个数据包。这?/span>JpcapCaptor实例中四U捕捉包的方法之一?/span> |
int |
loopPacket (int count, PacketReceiver handler) 捕捉指定数目的数据包Qƈ交由实现?/span>PacketReceiver接口的类的实例处理,q返回捕捉到的数据包数目。如?/span>count参数设ؓQ?/span>1Q那么无限@环地捕捉数据?/span> q个Ҏ不受时的媄响。还记得openDivice()中的to_ms参数么?那个参数对这个方法没有媄响,如果没有捕捉到指定数目数据包Q那么这个方法将一直阻塞等待?/span>
PacketReceiver中只有一个抽象方?/span>void receive(Packet p)?/span>
|
int |
processPacket (int count, PacketReceiver handler) ?/span> loopPacket () 功能一P唯一的区别是q个Ҏ受超时的影响Q超q指定时间自动返回捕捉到数据包的数目?/span> |
int |
dispatchPacket (int count, PacketReceiver handler) ?/span> processPacket () 功能一P区别是这个方法可以处?#8220;non-blocking”模式工作Q在q种模式下dispatchPacket()可能立即q回Q即使没有捕捉到M数据包?/span> |
void |
setFilter (java.lang.String condition, boolean optimize) . condition Q?/span> 讑֮要提取的包的关键字?/span>Optimize Q这个参数在说明文档以及源代码中都没有说明,只是说这个参数如果ؓ真,那么qo器将处于优化模式?/span> |
void |
setNonBlockingMode (boolean nonblocking) 如果gؓ“true”Q那么设定ؓ“non-blocking”模式?/span>
|
void |
breakLoop () 当调?/span>processPacket()?/span>loopPacket()后,再调用这个方法可以强制让processPacket()?/span>loopPacket()停止?/span>
|
Ҏ成员 |
|
void |
close () 强制关闭q个q接?/span> |
static JpcapSender |
openRawSocket () q个Ҏq回?/span>JpcapSender实例发送数据包时将自动填写数据链\层头部分?/span>
|
void |
sendPacket (Packet packet) JpcapSender最重要的功能,发送数据包。需要注意的是,如果调用q个Ҏ的实例是?/span>JpcapCaptor?/span> getJpcapSenderInstance () 得到的话Q需要自p定数据链路层的头Q而如果是׃面的openRawSocket() 得到的话Q那么无需也不能设|,数据链\层的头部由pȝ自动生成?/span> |
我们不可能列举所有可能的固Q我们会针对几种最常见的问题进行处理。当然了Q正如前面说到的Q如果我们自׃用java.net.HttpURLConnection来搞定这些问题是很恐怖的事情Q因此在开始之前我们先要介l一下一个开放源码的目Q这个项目就是Apache开源组l中的httpclientQ它隶属于Jakarta的commons目Q目前的版本?.0RC2。commons下本来已l有一个net的子目Q但是又把httpclient单独提出来,可见http服务器的讉Kl非易事?/font>
Commons-httpclient目是专门设计来简化HTTP客户端与服务器进行各U通讯~程。通过它可以让原来很头疼的事情现在L的解冻I例如你不再管是HTTP或者HTTPS的通讯方式Q告诉它你想使用HTTPS方式Q剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时l常到的几个问题进行分别介l如何用httpclient来解军_们,Z让读者更快的熟悉q个目我们最开始先l出一个简单的例子来读取一个网늚内容Q然后@序渐q解x前进中的所形侍?/font>
1Q?d|页(HTTP/HTTPS)内容 下面是我们给出的一个简单的例子用来讉K某个面 /* * Created on 2003-12-14 by Liudong */ package http.demo; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; /** * 最单的HTTP客户?用来演示通过GET或者POST方式讉K某个面 * @author Liudong */ public class SimpleClient { public static void main(String[] args) throws IOException { HttpClient client = new HttpClient(); //讄代理服务器地址和端?nbsp; //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port); //使用GETҎQ如果服务器需要通过HTTPSq接Q那只需要将下面URL中的http换成https HttpMethod method = new GetMethod("http://java.sun.com"); //使用POSTҎ //HttpMethod method = new PostMethod("http://java.sun.com"); client.executeMethod(method); //打印服务器返回的状?/font> System.out.println(method.getStatusLine()); //打印q回的信?/font> System.out.println(method.getResponseBodyAsString()); //释放q接 method.releaseConnection(); } 在这个例子中首先创徏一个HTTP客户?HttpClient)的实例,然后选择提交的方法是GET或者POSTQ最后在HttpClient实例上执行提交的ҎQ最后从所选择的提交方法中d服务器反馈回来的l果。这是使用HttpClient的基本流E。其实用一行代码也可以搞定整个请求的q程Q非常的单! 其实前面一个最单的CZ中我们已l介l了如何使用GET或者POST方式来请求一个页面,本小节与之不同的是多了提交时讑֮面所需的参敎ͼ我们知道如果是GET的请求方式,那么所有参数都直接攑ֈ面的URL后面用问号与面地址隔开Q每个参数用&隔开Q例如:http://java.sun.com?name=liudong&mobile=123456Q但是当使用POSTҎ时就会稍微有一点点ȝ。本节的例子演C向如何查询手机L所在的城市Q代码如下: /* * Created on 2003-12-7 by Liudong */ package http.demo; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; /** * 提交参数演示 * 该程序连接到一个用于查询手机号码所属地的页?/font> * 以便查询LD?330227所在的省䆾以及城市 * @author Liudong */ public class SimpleHttpClient { public static void main(String[] args) throws IOException { HttpClient client = new HttpClient(); client.getHostConfiguration().setHost("www.imobile.com.cn", 80, "http"); HttpMethod method = getPostMethod();//使用POST方式提交数据 client.executeMethod(method); //打印服务器返回的状?/font> System.out.println(method.getStatusLine()); //打印l果面 String response = new String(method.getResponseBodyAsString().getBytes("8859_1")); //打印q回的信?/font> System.out.println(response); method.releaseConnection(); } /** * 使用GET方式提交数据 * @return */ private static HttpMethod getGetMethod(){ return new GetMethod("/simcard.php?simcard=1330227"); } /** * 使用POST方式提交数据 * @return */ private static HttpMethod getPostMethod(){ PostMethod post = new PostMethod("/simcard.php"); NameValuePair simcard = new NameValuePair("simcard","1330227"); post.setRequestBody(new NameValuePair[] { simcard}); return post; } } 在上面的例子中页?/font>http://www.imobile.com.cn/simcard.php需要一个参数是simcardQ这个参数gؓ手机LD,x机号码的前七位,服务器会q回提交的手机号码对应的省䆾、城市以及其他详l信息。GET的提交方法只需要在URL后加入参C息,而POST则需要通过NameValuePaircL讄参数名称和它所对应的?/font> 3Q?处理面重定?/font> 在JSP/Servlet~程中response.sendRedirectҎ是使用HTTP协议中的重定向机制。它与JSP中的<jsp:forward …>的区别在于后者是在服务器中实现页面的跌{Q也是说应用容器加载了所要蟩转的面的内容ƈq回l客LQ而前者是q回一个状态码Q这些状态码的可能D下表Q然后客Ld需要蟩转到的页面的URLq新加载新的页面。就是这样一个过E,所以我们编E的时候就要通过HttpMethod.getStatusCode()Ҏ判断q回值是否ؓ下表中的某个值来判断是否需要蟩转。如果已l确认需要进行页面蟩转了Q那么可以通过dHTTP头中的location属性来获取新的地址?/font> 状态码 client.executeMethod(post); System.out.println(post.getStatusLine().toString()); post.releaseConnection(); //查是否重定向 int statuscode = post.getStatusCode(); if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) || (statuscode == HttpStatus.SC_SEE_OTHER) || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) { //d新的URL地址 Header header = post.getResponseHeader("location"); if (header != null) { String newuri = header.getValue(); if ((newuri == null) || (newuri.equals(""))) newuri = "/"; GetMethod redirect = new GetMethod(newuri); client.executeMethod(redirect); System.out.println("Redirect:"+ redirect.getStatusLine().toString()); redirect.releaseConnection(); } else System.out.println("Invalid redirect"); } 我们可以自行~写两个JSP面Q其中一个页面用response.sendRedirectҎ重定向到另外一个页面用来测试上面的例子?/font> 4Q?模拟输入用户名和口oq行d 本小节应该说是HTTP客户端编E中最常碰见的问题Q很多网站的内容都只是对注册用户可见的,q种情况下就必须要求使用正确的用户名和口令登录成功后Q方可浏览到惌的页面。因为HTTP协议是无状态的Q也是q接的有效期只限于当前请求,h内容l束后连接就关闭了。在q种情况下ؓ了保存用Ld信息必须使用到Cookie机制。以JSP/ServletZQ当览器请求一个JSP或者是Servlet的页面时Q应用服务器会返回一个参敎ͼ名ؓjsessionidQ因不同应用服务器而异Q,值是一个较长的唯一字符串的CookieQ这个字W串g是当前讉K该站点的会话标识。浏览器在每讉K该站点的其他面时候都要带上jsessionidq样的Cookie信息Q应用服务器Ҏdq个会话标识来获取对应的会话信息?/font> 对于需要用L录的|站Q一般在用户d成功后会用戯料保存在服务器的会话中,q样当访问到其他的页面时候,应用服务器根据浏览器送上的Cookie中读取当前请求对应的会话标识以获得对应的会话信息Q然后就可以判断用户资料是否存在于会话信息中Q如果存在则允许讉K面Q否则蟩转到d面中要求用戯入帐号和口oq行d。这是一般用JSP开发网站在处理用户d的比较通用的方法?/font> q样一来,对于HTTP的客L来讲Q如果要讉K一个受保护的页面时必L拟浏览器所做的工作Q首先就是请求登录页面,然后dCookie|再次hd面q加入登录页所需的每个参敎ͼ最后就是请求最l所需的页面。当然在除第一ơ请求外其他的请求都需要附带上Cookie信息以便服务器能判断当前h是否已经通过验证。说了这么多Q可是如果你使用httpclient的话Q你甚至q一行代码都无需增加Q你只需要先传递登录信息执行登录过E,然后直接讉K惌的页面,跟访问一个普通的面没有M区别Q因为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实Cq样一个访问的q程?/font> * Created on 2003-12-7 by Liudong */ package http.demo; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.cookie.*; import org.apache.commons.httpclient.methods.*; /** * 用来演示d表单的示?/font> * @author Liudong */ public class FormLoginDemo { static final String LOGON_SITE = "localhost"; static final int LOGON_PORT = 8080; public static void main(String[] args) throws Exception{ HttpClient client = new HttpClient(); client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT); //模拟d面login.jsp->main.jsp PostMethod post = new PostMethod("/main.jsp"); NameValuePair name = new NameValuePair("name", "ld"); NameValuePair pass = new NameValuePair("password", "ld"); post.setRequestBody(new NameValuePair[]{name,pass}); int status = client.executeMethod(post); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); //查看cookie信息 CookieSpec cookiespec = CookiePolicy.getDefaultSpec(); Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies()); if (cookies.length == 0) { System.out.println("None"); } else { for (int i = 0; i < cookies.length; i++) { System.out.println(cookies[i].toString()); } } //讉K所需的页面main2.jsp GetMethod get = new GetMethod("/main2.jsp"); client.executeMethod(get); System.out.println(get.getResponseBodyAsString()); get.releaseConnection(); } } 5Q?提交XML格式参数 提交XML格式的参数很单,仅仅是一个提交时候的ContentType问题Q下面的例子演示从文件文件中dXML信息q提交给服务器的q程Q该q程可以用来试Web服务?/font> import java.io.File; import java.io.FileInputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.PostMethod; /** * 用来演示提交XML格式数据的例?/font> */ public class PostXMLClient { public static void main(String[] args) throws Exception { File input = new File(“test.xml”); PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”); // 讄h的内容直接从文g中读?/font> post.setRequestBody(new FileInputStream(input)); if (input.length() < Integer.MAX_VALUE) post.setRequestContentLength(input.length()); else post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED); // 指定h内容的类?/font> post.setRequestHeader("Content-type", "text/xml; charset=GBK"); HttpClient httpclient = new HttpClient(); int result = httpclient.executeMethod(post); System.out.println("Response status code: " + result); System.out.println("Response body: "); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); } } 6Q?通过HTTP上传文g httpclient使用了单独的一个HttpMethod子类来处理文件的上传Q这个类是MultipartPostMethodQ该cdl封装了文g上传的细节,我们要做的仅仅是告诉它我们要上传文g的全路径卛_Q下面的代码片段演示如何使用q个cR?/font> MultipartPostMethod filePost = new MultipartPostMethod(targetURL); filePost.addParameter("fileName", targetFilePath); HttpClient client = new HttpClient(); //׃要上传的文g可能比较?因此在此讄最大的q接时旉 client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); int status = client.executeMethod(filePost); 7Q?讉K启用认证的页?/font> 我们l常会碰到这L面Q当讉K它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,q种用户认证的方式不同于我们在前面介l的Z表单的用戯n份验证。这是HTTP的认证策略,httpclient支持三种认证方式包括Q基本、摘要以及NTLM认证。其中基本认证最单、通用但也最不安全;摘要认证是在HTTP 1.1中加入的认证方式Q而NTLM则是微Y公司定义的而不是通用的规范,最新版本的NTLM是比摘要认证q要安全的一U方式?/font> 下面例子是从httpclient的CVS服务器中下蝲的,它简单演C如何访问一个认证保护的面Q?/font> import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.methods.GetMethod; public class BasicAuthenticationExample { public BasicAuthenticationExample() { } public static void main(String[] args) throws Exception { HttpClient client = new HttpClient(); client.getState().setCredentials( "realm", new UsernamePasswordCredentials("username", "password") ); GetMethod get = new GetMethod("https://www.verisign.com/products/index.html"); get.setDoAuthentication( true ); int status = client.executeMethod( get ); System.out.println(status+""+ get.getResponseBodyAsString()); get.releaseConnection(); } } 8Q?多线E模式下使用httpclient 多线E同时访问httpclientQ例如同时从一个站点上下蝲多个文g。对于同一个HttpConnection同一个时间只能有一个线E访问,Z保证多线E工作环境下不生冲H,httpclient使用了一个多U程q接理器的c:MultiThreadedHttpConnectionManagerQ要使用q个cd单,只需要在构造HttpClient实例的时候传入即可,代码如下Q?/font> MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpClient client = new HttpClient(connectionManager); 以后管讉Kclient实例卛_?/font> 参考资料: httpclient首页Q?nbsp; http://jakarta.apache.org/commons/httpclient/
}
2Q?以GET或者POST方式向网|交参?/font>
对应HttpServletResponse的常?br />
详细描述
301
SC_MOVED_PERMANENTLY
面已经怹Ud另外一个新地址
302
SC_MOVED_TEMPORARILY
面暂时Ud到另外一个新的地址
303
SC_SEE_OTHER
客户端请求的地址必须通过另外的URL来访?br />
307
SC_TEMPORARY_REDIRECT
同SC_MOVED_TEMPORARILY
下面的代码片D|C如何处理页面的重定?/font>
/*
上面代码中,targetFilePath即ؓ要上传的文g所在的路径?/font>
import org.apache.commons.httpclient.HttpClient;
关于NTLM是如何工作: http://davenport.sourceforge.net/ntlm.html