本文將學習幾個基本的數據庫概念,包括模式、表、列數據類型以及結構化查詢語言(SQL)的簡單介紹。這篇文章 —— 側重于數據庫開發人員的角色 —— 介紹可以用來在 Apache Derby 數據庫中保存數據的基本數據類型,然后用它們在 Apache Derby 中創建一個帶有兩個表的簡單模式,供一個虛擬的商店使用。要查看數據庫的模式內容,可以使用 Apache Derby 的工具 —— dblook,導出數據庫的內容。文章結束時簡單討論了如何刪除表。
在開發數據庫應用程序之前,需要理解它的基本概念。這一節介紹在 Apache Derby 中可以使用的數據類型,以及對設計和創建有用的 Derby 數據庫應用程序的能力有影響的規則。
關系數據庫容納數據。數據可以是不同類型的,例如數值型、字符型或日期型。在數據庫中,數據被組織到叫做表 的邏輯單元中。表就像工作簿一樣,因為它包含數據行。每行由許多列組成。列容納特定數據類型的數據,例如整型值或字符串。在多數情況下,一個數據庫有多個表。為了將表關聯在一起,數據庫設計師利用表之間的自然(或人為)鏈接。在工作簿中,可以通過單元格的值鏈接不同工作簿中的行。同樣的概念在關系數據庫中也存在,用來進行鏈接的列叫做鍵列(key column)。
為了讓表或列的用途更容易理解,應當選擇合適的名稱。對于不同的數據庫,命名約定可能不同。對于 Apache Derby 數據庫系統,名稱應當:
- 不區分大小。
- 最長 128 個字符。
- 必須以字母開頭。
- 必須只包含 Unicode 字母、下劃線和 Unicode 數字。
通過把名稱放在雙引號中,可以避開 這些規則,使用雙引號允許名稱區分大小寫以及包含附加字符(包括空格)。但是,這么做通常是不好的做法:它要求名稱總被括在雙引號中,很容易把維護代碼的其他人弄糊涂。
![]() |
|
關聯的表通常組織在一起,形成一個模式(schema)。可以把模式當成特定數據庫中所有相關結構定義的容器。在指定模式中,表的名稱必須惟一。所以,通過使用模式,可以在不同模式的范圍內擁有名稱相同的對象(例如表)。在使用 Apache Derby 數據庫時,表總在模式中。如果沒有顯式地指定模式,Derby 就會隱式地使用內置的 apps
模式。叫做 sys
的第二個內置模式用來隔離系統表。
可以用模式名對名稱進行限定(qualify)。要做這件事,可以在模式名后加圓點,然后加表名。例如,bigdog.products
表示 bigdog
模式中的 products
表。沒有相應的模式名,表名就被認為是未限定的(unqualified),例如 products
。當模式名和表名都完全指定的時候,就像 bigdog.products
,名稱被稱為完全限定的(fully qualified)。
從抽象意義上來說,這些數據庫概念看起來可能讓人混淆。但在實踐上,它們相當簡單。例如,假設有一個商店,叫做 Bigdog's Surf Shop,這家店銷售各種商品,例如太陽鏡、襯衫等等。如果想贏利,就必須管理庫存,以便可以容易地訂購額外的商品或改變供應商,從而把開支控制在最小。跟蹤這些信息的一個簡單方法,就是用表格式編寫條目,如 圖 1 所示。
圖 1. Bigdog's Surf Shop 的示例模式

從這個簡單的可視設計中,可以容易地把業務邏輯直接映射到數據庫表。有兩個表:Products 和 Vendors,它們自然地通過商品名稱鏈接在一起。列的數據類型很容易確定。這篇文章其余的部分將側重于在 Derby 數據庫中創建 Bigdog's Surf Shop 的示例模式 —— 模式中包含這兩個表。
![]() ![]() |
![]()
|
![]() |
|
數據庫系統會成為軟件中復雜的部分,特別是在規模擴大到支持企業級應用程序的時候。所以,可以想像每個數據庫都會有自己的應用程序編程接口(API),而這些 API 可能彼此不同。當關系數據庫剛開發出來的時候,情況就是這樣。但是,幸運的是,許多開發商同意開發一個標準的語言,用來訪問和操縱數據庫。這個語言稱作結構化查詢語言(或 SQL,發音是 sea-quill)。至今已經形成了多個官方標準版本,包括 1992 年的版本,這一版被稱為 SQL-92,還有 1999 年的版本被稱為 SQL-99。Apache Derby 數據庫為 SQL-92 標準提供了幾乎完整的實現,所以用 Deryby 開發的應用程序可以容易地移植到其他數據庫系統。
SQL 有兩個主要部分:數據定義語言(DDL)和數據操縱語言(DML)。DDL 命令用來創建、修改或刪除數據庫中的項目(例如表)。DML 命令用來在數據庫表中添加、修改、刪除或選擇數據。這篇文章后面的部分將提供對 SQL 的 DDL 部分的基本介紹。未來的文章將側重于 DML 命令和更高級的 DDL 命令。
SQL 作為一個編程語言,定義了豐富的數據類型層次結構。數據庫已經變得更強大了,所以這個類型層次結構也變得更復雜。但是最簡單的數據庫并不要求使用所有允許的類型,通常只需要保存數值型、字符型和日期(或時間)數據。為了簡單,表 1、2、3、4 顯示了 Derby 中實現的基本 SQL 數據類型。
如表 1 所示,Derby 提供了對三種整型數據類型的支持。這些類型由它們可以保存的整數的范圍區分,也就是由它們在數據庫中需要的存儲空間區分。在設計數據庫時要記住的一個關鍵問題就是,應當一直把表使用的空間控制在最小。一般來說,表越小,性能越高。但是必須能夠在生成的表中保存需要的數據。231 等于 2,147,483,648,263 等于 9,223,372,036,854,775,808,所以使用這些類型可以保存非常大的整數!
數據類型 | 最小值 | 最大值 | 示例 | 說明 |
---|---|---|---|---|
SMALLINT |
-32768 (-215) | 32767 (215 - 1) | itemNumber SMALLINT |
2 字節整數表示 |
INT |
-231 | 231 - 1 | itemNumber INT |
4 字節整數表示 |
BIGINT |
-263 | 263 - 1 | itemNumber BIGINT |
8 字節整數表示 |
多數數值型數據不能用整數表示。Derby 對實數提供了多種格式的支持:單精度浮點、雙精度浮點以及準確的算術表示,如表 2 所示。
數據類型 | 最小值 | 最大值 | 示例 | 說明 |
---|---|---|---|---|
REAL |
-3.402x10+38 | 3.402x10+38 | price REAL |
IEEE 浮點數(4 字節) |
DOUBLE |
-1.79769x10+308 | 1.79769x10+308 | price DOUBLE |
IEEE 浮點數(8 字節) |
DECIMAL |
31 (最大精度) | price DECIMAL(5,2) |
準確算術表示 |
如果從未遇到過準確精度數據類型,那么對算術類型和浮點類型可能有些迷惑。區別在于一個事實:計算機中使用的浮點數據類型無法包含每個實數。這看起來可能有些怪,但是想想實數的數量是無限的。大多數實數都無法保存在幾個字節的內存中。對于某些應用程序,精度的損失是可以接受的,而在許多情況下,則不可接受。例如,財務應用程序不能容忍僅僅因為某個數字不能保存在計算機中,就損失金錢。
這個問題的解決方案是使用 DECIMAL
數據類型,它可以控制計算機存儲的數字位數(精度)和小數點后的位數(刻度)。要創建算術類型,應當指定保存的數據的精度,并可選地指定數據的刻度。DECIMAL
數據類型需要的存儲空間通常要比浮點數據類型大得多。所以應當小心地使用這個類型,否則應用程序的性能會降低。默認情況下,DECIMAL
類型的刻度為 0,這意味著 DECIMAL
數據類型模擬了整數類型。
數值類型有多個同義詞。例如,DECIMAL
數據類型可以縮短為 DEC
或表示為 NUMERIC
。DOUBLE
類型也可以表示為 DOUBLE PRECISION
,雖然為什么在需要雙精度數字時要輸入額外的單詞,原因不明。更常用的同義詞是 FLOAT
類型,它擁有任意的浮點精度,可以在聲明數據類型時指定,例如 FLOAT(val)
。精度必須是小于 53 的正整數;如果不是,就會出錯。如果指定了小于等于 23 的精度值,FLOAT(val)
就等價于 REAL
;如果精度在 24 和 53 之間,那么 FLOAT(val)
等價于 DOUBLE
。
除了數值類型,數據庫中最常用的保存數據的另一個類型是字符數據。字符數據的示例包括產品說明、人名或地址信息。Derby 提供了保存字符數據的兩個簡單技術:CHAR
類型和 VARCHAR
類型,詳情如表 3 所示。對于這兩種類型,都可以指定 length
參數,如果沒指定,默認為 1。在這兩個字符數據類型之間有兩個主要區別。首先,CHAR
類型的最大長度是 254 個字符,而 VARCHAR
類型最多可以容納 32,672 個字符。第二個區別比較微妙:CHAR
類型的長度總是指定的長度。如果沒有指定足夠的字符,那么會插入額外的空白來填滿剩余位置。而使用 VARCHAR
時,字符的數量是可變的,不執行額外的填充。
數據類型 | 最大長度 | 示例 | 說明 |
---|---|---|---|
CHAR |
254 | description CHAR(128) |
定長字符串 |
VARCHAR |
32,672 | description VARCHAR(128) |
變長字符串 |
因為長度可變,所以 VARCHAR
類型在實際的存儲空間方面會更有效率,但在性能上效率就會更低。CHAR
數據類型有助于性能提高,因為數據庫確切地知道每個 CHAR
列有多大,所以在讀寫數據時就可以執行某種性能優化。VARCHAR
列的最大長度看起來可能足夠大了,但是 Derby 還提供了更大的字符數據類型,這個類型將在未來的文章中討論。
Derby 提供了最后一類簡單的數據類型來保存日期和時間,如表 4 所示。TIME
數據類型以 24 小時格式保存小時、分鐘和秒(HH:MM:SS
)。DATE
數據類型保存月、日和年,可以用不同的格式指定,包括以下格式:
yyyy-mm-dd
mm/dd/yyyy
dd.mm.yyyy
數據類型 | 最小值 | 最大值 | 示例 | 說明 |
---|---|---|---|---|
TIME |
00:00:00 | 24:00:00 | start TIME |
時間表示(精確到秒) |
DATE |
0001-01-01 | 9999-12-31 | stockDate DATE |
日期表示(精確到天) |
Derby 還提供了 TIMESTAMP
數據類型,把 TIME
和 DATE
數據類型組合到一個類型中,表示準確的時間。
![]() ![]() |
![]()
|
目前為止,已經學習了如何設計表,包括規劃表的列和定義每個列的數據類型。在正確地設計了表之后,用 SQL 創建表的方法就很簡單了。清單 1 顯示了在 Derby 中創建表的正式語法。
清單 1. Apache Derby 的 CREATE TABLE 語法
-- Comment describing the purpose and layout of the table CREATE TABLE [schemaName.]tableName ( { <columnDefinition> | <tableLevelConstraint> } [, { <columnDefinition> | <tableLevelConstraint> } ]* ) ; |
第一次看這個語法時,可能感覺到迷惑不解。但是有了基礎之后,接下來就容易了;而且如果想掌握 Derby,對正式語法的理解是必需的。方括號([
和 ]
)中的是可選參數。從正式語法中可以看出,模式名是可選的,在必需的頭一個列之后(創建連一個列都沒有的表是沒有意義的),其他列定義或表級約束都是可選的。
您可能理解列定義的含義,但是可能不理解約束 的意義。約束有兩種類型:表級約束和列約束。約束通過某種方式對列或表進行限制。例如,可以用約束要求列總要有實際的值(沒有 NULL
值),或者列中的每個項必須是惟一的,或者列被自動分配默認值。在未來的文章中將更詳細地介紹約束。
最后一個結束方括號之后的星號(*
)代表可以包含一個或多個包含項。這意味著表必須有一個或多個列級或表級約束。豎線(|
)表明 “可有可無” 條件。在這個語法示例中,必須定義一個新列或者定義一個表級約束。花括號({
和 }
)把相關項組織在一起,而圓括號((
和 )
)中是必需的元素 。最后,分號(;
)表示 SQL 語句的結束。
把這些規則投入使用則相當簡單。清單 2 顯示了如何用 Derby 提供的 ij
創建前面在 圖 1 中演示的表。
清單 2. 在 Apache Derby 中創建表
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
工具,在這個系列的第一篇文章 “用 Apache Derby 進行開發 —— 取得節節勝利:Apache Derby 介紹”(developerWorks,2006 年 2 月)中已經介紹過。如果按照 清單 2 中的步驟進行,就會創建一個新的數據庫,名為 test
。如果 test
數據庫已經存在,在發出 connect
語句時,會得到警告消息。可以安全地忽略這個警告。接下來,隱式地創建一個名為 bigdog
的新模式,并顯式地創建兩個新表 —— products
和 vendors
—— 這兩個表保存在 bigdog
模式中。模式的創建所以是隱式的,是因為沒有發出 CREATE SCHEMA
語句。
products
表有四個列:itemNumber
、price
、stockDate
和 description
。itemNumber
列提供了每個商品(或列)的惟一標識,它上面還有列級約束,強制要求提供正確的值(NOT NULL
)。如果沒有這個要求,itemNumber
列就無法保持惟一,因為多個行都可能被分配 NULL
值。price
列創建為 DECIMAL
數據類型,精度為 5,刻度為 2。這意味著每個商品的最高價格可以是 $999.99。最后兩個列很簡單:stockDate
列以 Date
類型保存,description
列以字符串類型保存,最長 128 個字符,使用的空間是實際的字符串長度。
vendors
表有三列:itemNumber
、 vendorNumber
和 vendorName
。在這個示例中,itemNumber
和 vendorNumber
列都有列級約束(NOT NULL
)。另外,vendorName
列以字符串類型保存,最大長度為 64。因為 vendorName
列用 CHAR
數據類型保存,所以總是保留 64 個字符空間。
在創建了各種項目之后,可能想知道是否有種簡單的方式可以查看數據庫中保存了什么項目。幸運的是,答案是肯定的,可以使用 dblook
工具。運行這個工具,如 清單 3 所示,提供了特定數據庫中已經創建的項目的詳細清單。
清單 3. 用 dblook 查看模式
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 類,可以用它方便地把數據庫的內容輸出到控制臺。在命令行上運行它,就像運行其他 Java 程序一樣;惟一增加的就是使用 -d jdbc:derby:test
參數,這個參數指定 dblook
工具應當查詢的數據庫。如果能運行 ij
工具,那么 dblook
類文件就已經存在于 CLASSPATH
中了。如果不是這樣,請參考這個系列中的 第一篇文章,獲得正確設置 CLASSPATH
的詳細說明。正如 dblook
工具的輸出所示,test
數據庫包含 bigdog
模式,這個模式包含 products
和 vendors
表。另外,對這兩個表的列也有詳細描述。
![]() ![]() |
![]()
|
沒有什么事情是完美的。當錯誤地創建了表或者表不再需要的時候,該怎么辦?簡單的答案是從數據庫中刪除表。而且,如果必要,再創建一個替代表。刪除表很容易,當然這意味著,在做這件事的時候應當非常小心 —— 不會彈出對話框要求您確認是否真的想刪除!
從數據庫中刪除(或者更正式地說,撤下(drop))一個表的完整語法是:
DROP TABLE [schemaName.]tableName ;
語法很簡單:把完全限定名稱和分號放在 DROP TABLE
SQL 命令后面,就完成了。清單 4 中在新創建的臨時表上演示了刪除表的過程。
清單 4. 從 Derby 數據庫刪除表
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 ; |
![]() ![]() |
![]()
|
現在您已經走上了操作 Apache Derby 數據庫的道路。目前您已經掌握了基本的數據庫概念,包括模式、表和列,還看到了使用名為 Bigdog's Surf Shop 的虛擬公司對這些概念的演示。要操作像 Derby 這樣的數據庫,需要學習 SQL,它是與數據庫進行交互的標準語言。這篇文章還介紹了可以用來在 Derby 數據庫中保存數據的基本數據類型。把這些概念融合在一起,您學習了如何用 Derby 創建和刪除表,還使用 Derby 的 dblook
工具輸出了數據庫的模式內容。