2014年4月12日 星期六

Java 資料庫存取 : 使用 Derby

完成 ACCESS 資料庫函式庫從 Javascript 版改寫為 Java 版後, 本來整個常用函式庫移植工作就告一段落, 可以應用在公司主機系統的資料自動擷取與分析了, 但今日陪姐姐去南二中考試時, 看完幾乎半本 "Java 網路程式設計 (學貫, 謝兆賢)", 裡面有一章介紹 JavaDB (Derby), 看完覺得還不錯用, 因為 Derby 是在安裝完 JDK 時就已內建了, 所以可以當成內嵌的資料庫來用, 如果伺服器有裝 JDK, 對於小型使用量而言, 那就可以直接使用, 不需安裝其他資料庫了.

其實吸引我興趣的是, Derby 沒有 2GB 限制! 這正是我目前使用的 ACCESS 的最大缺憾, 例如公司的工作日誌系統資料庫大約兩三年左右就會到達 2G 的天險而爆掉, 每次都耗掉我一整天的時間去搞升版. ACCESS 的好處是單一檔案, 離線處理後上傳伺服器很方便, 而且有 GUI 介面, 比較親民些. 關於 Derby 與 ACCESS 的比較, 參見 :

# Derby vs. ACCESS

關於 Derby 的限制, 參見 :

# Limitations for database values in Derby

Derby 也是英國中部的一個城市 (英格蘭), 在英文則是一種禮帽.


Apache 取之作為資料庫名稱 (Apache DB Project), 官網參見 :

# http://db.apache.org/derby/

使用方法 :

# Derby Tutorial
# ij Basics
# https://builds.apache.org/job/Derby-docs/lastSuccessfulBuild/artifact/trunk/out/getstart/index.html

Java 將 Derby 納入作為內建資料庫, 安裝 JDK 時一併安裝, 位置在 JDK 目錄的 db 資料夾下面, 以我的 XP 電腦的 JDK 1.7.0 來說, 其路徑為 :

C:\Program Files\Java\jdk1.7.0\db

整個目錄僅 4.8M, 比起 ACCESS 簡直是小巫見大巫, 但功能卻絲毫不遜色. 不過 Derby 沒有 GUI 介面, 完全必須利用命令行下指令, 故最好設定 PATH, 以便在任意路徑下都能方便使用. 以我的電腦來說, 是在 "控制台/系統/進階/環境變數", 在 PATH 變數尾端加入 :

C:\Program Files\Java\jdk1.7.0\db\bin;

確定後打開命令提示字元視窗, 輸入 ij 就可以進入 Derby 了 :


要跳出 Derby 可按 Ctrl+C, 回答 Y 即離開 Derby 命令行.

在 Derby 中建立資料庫需使用 connect 指令 :

connect 'jdbc:derby:testdb;create=true';

注意, 不可以用雙引號, 必須用單引號, 否則無法建立資料庫連線 :


如果在目前目錄下是第一次連線此資料庫, 那麼上面的連線指令實際上是建立一個空白資料庫, 並建立連線; 如果已經建立過同名資料庫, 那麼就只是建立連線而已 :

ij> connect 'jdbc:derby:testdb;create=true';
警告 01J01:未建立資料庫 'testdb',會改成建立現有資料庫的連線

資料庫連線建立成功後, 會在目前目錄下產生該資料庫之目錄, 由於上面我是在 D:\java 底下以 ij 指令進入 Derby, 因此 connect 指令會在 D:\java 下建立 testdb 目錄, 大小只有 1.75MB :


其架構請參考 :

http://db.apache.org/derby/docs/10.0/manuals/develop/develop13.html

注意喲, 在這篇文章中有一段提到 :

"There is no drop database command. To drop a database, delete the database directory with operating system commands. "

也就是 Derby 沒有 DROP DATABASE 的指令, 要刪除資料庫直接將其目錄刪除即可. 如果在 ij 介面用下列指令會顯示錯誤, 表示無法刪除資料庫目錄 :

ij> connect 'jdbc:derby:testdb;drop=true';
錯誤 XBM0I:無法移除 testdb 目錄。

但在下面這篇文章, 作者表示若資料庫建在 memory 下則可以刪除 memory 下的資料庫, 但 memory 仍存在 :

# You can drop a file-system database from a directory named "memory"

我實際測試結果卻還是一樣, 不會刪除 testdb 資料庫.

接下來第一個操作是建立資料表, 參考我們在 ACCESS 資料庫所用的 users 資料表 :

# Java 資料庫存取 : 使用 ACCESS
# Java 資料庫存取 : 使用 ACCESS (續)

我們要建立 users 資料表, 內有 id, name, 與 gender 三個欄位, 在 ACCESS 用的 SQL 是 :

create table users(id AUTOINCREMENT PRIMARY KEY, name varchar(20), gender varchar(5))

但這在 Derby 不能用, 主要是自動增量欄位 id 的宣告方式 :

D:\Java>ij
ij 版本 10.8
ij> connect 'jdbc:derby:testdb;create=true';
警告 01J01:未建立資料庫 'testdb',會改成建立現有資料庫的連線。
ij> create table users(id AUTOINCREMENT PRIMARY KEY, name varchar(20), gender va
rchar(5));
錯誤 42X94:TYPE 'AUTOINCREMENT' 不存在。

所以 Derby 不認得 AUTOINCREMENT. 參考下列文章 :

# http://www.binarytides.com/create-autoincrement-columnfield-in-apache-derby/

得知 SQL 要改為如下格式 :

ij> create table users(id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), name varchar(20), gender varchar(5), CONSTRAINT primary_key PRIMARY KEY (id));
已插入/更新/刪除 0 列

可見僅顯示 insert/update/delete 訊息, 新增資料表是否成功也看不出來, 反正沒有 error 就是成功啦.

第二個操作是新增紀錄到資料表中. SQL 格式與 ACCESS 是一樣的 :

ij> insert into users(name, gender) values('愛咪','女');
已插入/更新/刪除 1 列
ij> insert into users(name, gender) values('彼得','男');
已插入/更新/刪除 1 列
ij> insert into users(name, gender) values('凱莉','女');
已插入/更新/刪除 1 列

第三個操作是顯示資料表內容 :

ij> select * from users;
ID         |NAME                |GEND&
--------------------------------------
2          |愛咪                  |女
3          |彼得                  |男
4          |凱莉                  |女

已選取 3 列

可見欄位名稱最多顯示五個字元, 但很奇怪地, id 怎會從 2 開始編? why?  

第四個操作是更新記錄 :

ij> update users set name='湯尼' where id=2;
已插入/更新/刪除 1 列
ij> select * from users;
ID         |NAME                |GEND&
--------------------------------------
2          |湯尼                  |女
3          |彼得                  |男
4          |凱莉                  |女

第五個操作是刪除記錄 :

ij> delete from users where id=2;
已插入/更新/刪除 1 列
ij> select * from users;
ID         |NAME                |GEND&
--------------------------------------
3          |彼得                  |男
4          |凱莉                  |女

已選取 2 列

注意, 這裡跟 ACCESS 不同的是不需要 *.

如果沒有加 where 條件, 則全部紀錄會被刪除, 變成空資料表 :

ij> delete from users;
已插入/更新/刪除 2 列
ij> select * from users;
ID         |NAME                |GEND&
--------------------------------------

已選取 0 列

最後一個操作是刪除資料表 :

ij> drop table users;
已插入/更新/刪除 0 列

若要顯示目前的連線, 可用

ij> show connections;
CONNECTION0* -  jdbc:derby:testdb
* = 現行連線

其他指令可下 help 顯示 :

ij> help;

參考 Derby 文件 :

# https://builds.apache.org/job/Derby-docs/lastSuccessfulBuild/artifact/trunk/out/getstart/twwdactivity2.html
# Connect to Apache Derby (Java DB) via JDBC

沒有留言 :