在 Oracle 中實作自動遞增欄位 (Oracle AUTO_INCREMENT)

在 MySQL 的資料庫中,有一種方便的欄位型態 AUTO_INCREMENT,有自動遞增的功能,多半使用於 ID 欄位,作為 PRIMARY KEY。類似自動遞增的功能,在 MSSQL 有 Identity,甚至連 MS Access 都有個 AutoNumber 都可以很方便的去宣告使用。

人沒有完美的,資料庫同樣也是。功能強大的 Oracle 卻沒有內建這樣方便的功能欄位,從我開始接觸 Oracle 以來,一直覺得遺憾與不解的,幾年下來,看起來原廠是沒去 implement 這樣的功能欄位的打算,是令人有些扼脕。但是,我們還是有機會用拼拼湊湊的方式,搞一個那樣子的欄位出來。

Step1. 建立 Table:

CREATE TABLE tbl (
  id  NUMBER PRIMARY KEY,
  val VARCHAR2(30)
);

Step2. 建立 Sequence:
CREATE SEQUENCE tbl_id_seq;
完成這兩步,我們就已經有了 INCREMENT (遞增)的功能了!
  1. -- 新增紀錄
  2. INSERT INTO tbl (id, val) VALUES (tbl_id_seq.nextval, 'row1_value');
  3. INSERT INTO tbl (id, val) VALUES (tbl_id_seq.nextval, 'row2_value');
  4. -- 撈出資料
  5. SELECT * FROM tbl;
  6. /**
  7. 輸出結果為:
  8. ID VAL
  9. ---------- ------------------------------
  10. 1 row1_value
  11. 2 row2_value
  12. */
那,怎麼做到 AUTO (自動)呢?是的,就是用 Trigger! Step3. 建立 Trigger:
  1. CREATE OR REPLACE TRIGGER tbl_trg
  2. BEFORE INSERT ON tbl
  3. FOR EACH ROW
  4. BEGIN
  5. IF :new.id IS NULL THEN
  6. SELECT tbl_id_seq.nextval INTO :new.id FROM dual;
  7. END IF;
  8. END;
這樣,AUTO_INCREMENT 都具備了,大功告成了!
  1. -- 新增紀錄
  2. INSERT INTO tbl (val) VALUES ('row3_value');
  3. INSERT INTO tbl (id, val) VALUES (null, 'row4_value');
  4. -- 撈出資料
  5. SELECT * FROM tbl;
  6. /**
  7. 輸出結果為:
  8. ID VAL
  9. ---------- ------------------------------
  10. 1 row1_value
  11. 2 row2_value
  12. 3 row3_value
  13. 4 row4_value
  14. */
但是,如果就這樣結束,那本篇介紹的,不過是台兩光的三輪拼裝車。 這種欄位,有極大機率 在實作情況下,需要即時取回剛剛新增那筆紀錄的 id 資料。在 MySQL 中有個 LAST_INSERT_ID() 來取得同一個連線 Session 中 AUTO_INCREMENT 所得到的 ID。那 Oracle 怎麼實作這功能?直接跟 Sequence 要它當時的值?如果在多人存取的環境下,這樣的做法能保證跟 Sequence 要到的那個數字,是你的還是後面又有人塞資料時候拿到的!? INSERT ... RETURNING ... 是我們要的解答:
  1. DECLARE
  2. i NUMBER;
  3. BEGIN
  4. INSERT INTO tbl (val) VALUES ('row5_value') RETURNING id INTO i;
  5. DBMS_OUTPUT.put_line('id : ' || i);
  6. FOR rec IN (SELECT id, val FROM tbl)
  7. LOOP
  8. DBMS_OUTPUT.put_line('rec.id = '  || rec.id ||
  9. '; rec.val = ' || rec.val);
  10. END LOOP;
  11. /**
  12. 輸出結果為:
  13. id : 5
  14. rec.id = 1; rec.val = row1_value
  15. rec.id = 2; rec.val = row2_value
  16. rec.id = 3; rec.val = row3_value
  17. rec.id = 4; rec.val = row4_value
  18. rec.id = 5; rec.val = row5_value
  19. */
  20. INSERT INTO tbl (id, val) VALUES (NULL, 'row6_value') RETURNING id INTO i;
  21. DBMS_OUTPUT.put_line('id : ' || i);
  22. FOR rec IN (SELECT id, val FROM tbl)
  23. LOOP
  24. DBMS_OUTPUT.put_line('rec.id = '  || rec.id ||
  25. '; rec.val = ' || rec.val);
  26. END LOOP;
  27. /**
  28. 輸出結果為:
  29. id : 6
  30. rec.id = 1; rec.val = row1_value
  31. rec.id = 2; rec.val = row2_value
  32. rec.id = 3; rec.val = row3_value
  33. rec.id = 4; rec.val = row4_value
  34. rec.id = 5; rec.val = row5_value
  35. rec.id = 6; rec.val = row6_value
  36. */
  37. END;
這做法雖然是輛拼裝車的,但是還不是太難使,倒也堪用。 不過,如果有機會能官方內建,總比建這建那拼拼湊湊的好! 難道,像人生一樣,就是要有那麼點遺憾,才是人生嗎?XD 原文出處: http://abu.tw/2008/06/oracle-autoincrement.html

發表迴響

jax-ws幾個常用註解的參數

QueryParam–url ? 后面表示的参数  .  get post 通用.
PathParam—url中的一部分,例如用{}表示的url中的一部分。get post 通用。
FormParam—post提交的form表单参数。     用于 post

原文節錄自:

http://blog.csdn.net/heihei0923/archive/2009/11/09/4791910.aspx

發表迴響

使用 Jersey + Tomcat 輕鬆開發 RESTful Web Service

這是一篇簡易教學文章, 可以簡單帶出 Restful WebService使用概念.

 

附帶一提,必須run在Tomcat 6.0才行,5.5版本會有Exception出現:

Caused by: java.lang.ClassNotFoundException: javax.persistence.PersistenceUnit

至於原因,若有哪位高手願意指教,十分感謝。  ^^

 

底下簡單列一下目前所使用的版本:

  • Eclipse 3.5
  • Tomcat 6.0.22
  • Jersey 1.1.2

這裡提供Jersey套件官網下載連結: 點此下載

 

 

首先建立一個Dynamic Web Project,假設我這邊命名RestfulDemo

 

將底下四個Jersey的jar檔放到classpath下,也就是WEB-INF/lib/下,在下試過,缺一不可,會有Exception

asm-3.1.jar

jersey-core-1.1.2-ea.jar

jersey-server-1.1.2-ea.jar

jsr311-api-1.1.jar

 

設定web.xml,加上下面設定

 

<servlet>

<servlet-name>ServletAdaptor</servlet-name>

<servlet-class>com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>ServletAdaptor</servlet-name>

<url-pattern>/resource/*</url-pattern>

</servlet-mapping>

 

 

 

建立下面Rest程式

 

 

package demo.rest;

 

import javax.ws.rs.GET;

import javax.ws.rs.Path;

import javax.ws.rs.Produces;

 

@Path(“/helloworld") // sets the path for this service

public class HelloRS {

 

@GET

@Produces(“text/html") // content type to output

public String getClichedMessage() {

return “Hello World";

}

}

 

 

Delpoy到Tomcat,並用Browser到下列網址,Enjoy : )

http://127.0.0.1:8080/RestfulDemo/resource/helloworld

 

 

至於Restful程式撰寫教學,個人覺得,Sun寫的RESTful Web Services Developer’s Guide寫的蠻不錯的,簡單易懂,還蠻容易入門的。

 

原文章出處:

http://www.dotblogs.com.tw/rockywang/archive/2009/10/22/11224.aspx

發表迴響

ENCTYPE="multipart/form-data"

用于表单里有檔案或图片上传

<form name="userInfo" method="post" action="first_submit.jsp"   ENCTYPE="multipart/form-data">
表单标签中设置enctype="multipart/form-data"来确保匿名上载文件的正确编码
如下:
<tr>
<td height="30″ align="right">上传图片:</td>
<td><INPUT TYPE="FILE" NAME="uploadfile" SIZE="34″   onChange="checkimage()"></td>
</tr>
就得加ENCTYPE="multipart/form-data"。

表 单中enctype="multipart/form-data"的意思,是设置表单的MIME编码默认情况,这个编码格式是application /x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据,进行下 面的操作.
enctype=\"multipart/form-data\"是上传二进制数据; form里面的input的值以2进制的方式传过去。
form里面的input的值以2进制的方式传过去,所以request就得不到值了。 也就是说加了这段代码,用request就会传递不成功,
取表单值加入数据库时,用到下面的:
SmartUpload su = new SmartUpload();//新建一个SmartUpload对象
su.getRequest().getParameterValues();取数组值
su.getRequest().getParameter( );取单个参数单个值

發表迴響

getServletContext()和getServletConfig()的意思

getServletConfig()在servlet初始化时,容器传递进来一个ServletConfig对象并保存在servlet实例中,该对象允许访问两项内容:初始化参数和 ServletContext对象,前者通常由容器在文件中指定,允许在运行时向sevrlet传递有关调度信息,比如说getServletConfig().getInitParameter(“debug")后者为servlet提供有关容器的信息。此方法可以让servlet在任何时候获得该对象及配置信息。

 

getServletContext()
一个servlet可以使用getServletContext()方法得到web应用的servletContext
即而使用getServletContext的一些方法来获得一些值
比如说getServletContext().getRealPath(“/")来获得系统绝对路径
getServletContext().getResource(“WEB-INF/config.xml")来获得xml文件的内容
文章出處:
http://www.blogjava.net/shichengjun1984/articles/159935.html

發表迴響

ORACLE-XE物理備份

昨晚因為字元集不相符的關係, 無法從舊資料庫轉移到新的資料庫,

簡單的說呢, 就是有執行 imp指令, 但卻無法真正匯入.

推測應該是oracle內部轉換字元集那邊出了問題, 以後有時間再回來研究.

靈機一動, 上網查了oracle 的物理備份.

雖然這不是很好的解法(畢竟我還是沒弄懂字元集那邊的問題),

但至少可以把oracle的備份, 弄得像mysql 的備份機制吧!

假設要備份的主機為A,  目標主機為B, 我們就是要把A機器上的資料, 轉移到B機器上.

在A機器上:

1. 先尋找datafile位置

SQL> select name from v$datafile;
(那句select語法,把你的資料庫檔案放那裡給指出來了。)
NAME
——————————————————————————–
/u02/db/NICE/system01.dbf
/u02/db/NICE/UNDOTBS1.dbf
/u02/db/NICE/sysaux01.dbf
/u02/db/NICE/users01.dbf
/u02/db/NICE/ZGT.dbf
/u02/db/NICE/ZGTIDX.dbf
/u02/db/NICE/EIP.dbf

7 rows selected.

2. 尋找 controlfile 位置

SQL> select name from v$controlfile;

NAME
——————————————————————————–
/u02/db/NICE/control01.ctl
/u02/db/NICE/control02.ctl
/u02/db/NICE/control03.ctl

3. 尋找logfile 位置

SQL> select member from v$logfile;

MEMBER
——————————————————————————–
/u02/db/NICE/redo03.log
/u02/db/NICE/redo02.log
/u02/db/NICE/redo01.log

總上所述,你要想盡辦法,把那些.dbf,.ctl,.log的檔案備份下來就是了。
再加上$ORACLE_HOME裡頭所有的檔案好,那就是完整的資料庫物理備份了.

4. 開始進行物理備份

a. 建議先關閉整個資料庫, 以免因為時間差, 有些資料沒有備份到.

[oracle@macrodbbk oracle]$ sqlplus / as sysdba

SQL> shutdown immediate

Database closed.
Database dismounted.
ORACLE instance shut down.  (看到此三種訊息, 表示關閉沒有問題!)

b. 將剛剛所查詢的檔案, 通通備份出來.

c. 再把資料庫打開, 已確定沒有異常!

SQL> startup
ORACLE instance started.

Total System Global Area 1828716544 bytes
Fixed Size                  1219976 bytes
Variable Size             201327224 bytes
Database Buffers         1610612736 bytes
Redo Buffers               15556608 bytes
Database mounted.
Database opened.  (看到此兩種訊息, 表示打開沒有問題!)
SQL>

好滴~ 請別太興奮! 我知道那種字元集轉換失敗的感覺很痛苦XDDDD  (我奮戰了一晚呀~~~~)

在B機器上

1. 如上, 先關閉資料庫

2.將從A機器物理備份出來的檔案, 看是要覆寫還是如何的, 把資料蓋過去

(建議還是要物理備份一下B機器上面的資料)

如果是在linux主機上面, 要特別注意權限

兩邊的檔案權限與擁有者等的必須要一樣才行.

-bash-3.2$ pwd
/usr/lib/oracle/xe/oradata/XE
-rw-r—– 1 oracle dba    7061504 Nov 16 21:07 control.dbf
-rw-r—– 1 oracle dba  536879104 Nov 16 20:14  xxx.ora
-rw-r—– 1 oracle dba  471867392 Nov 16 20:58 sysaux.dbf
-rw-r—– 1 oracle dba  356524032 Nov 16 21:05 system.dbf
-rw-r—– 1 oracle dba   20979712 Nov 16 12:04 temp.dbf
-rw-r—– 1 oracle dba  183508992 Nov 16 20:58 undo.dbf
-rw-r—– 1 oracle dba  104865792 Nov 16 20:14 users.dbf

-bash-3.2$ pwd

/usr/lib/oracle/xe/app/oracle/flash_recovery_area/XE/onlinelog

-rw-r—– 1 oracle dba 52429312 Nov 16 20:14 xxxxxxxxxxxxxxxx.log
-rw-r—– 1 oracle dba 52429312 Nov 16 21:05 yyyyyyyyyyyyyyyy.log

3.把B資料庫重新打開. 如無異常, 恭喜妳~ 你可以去喝杯咖啡休息一下了!

 

原文出處:

http://tw.myblog.yahoo.com/bullock0425/article?mid=306&sc=1

發表迴響

查看數據庫字元狀況

SELECT * FROM NLS_DATABASE_PARAMETERS;

SELECT * FROM V$NLS_PARAMETERS;

發表迴響

如要開放web介面讓非本機可登入的話

如要開放web介面讓非本機可登入的話,需要進sqlplus執行下列指令:
EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);

測試:

http://192.168.6.167:8081/apex      (這邊的port 是 8081, 預設是8080)

原文出處:

http://blog.roodo.com/mywork/archives/6198547.html

發表迴響

vmware workstation 無法抓到DHCP

1.  問過MIS之後才知道, 這似乎是vmware的小bug

2. 先用root 登入

3. 執行  setup 指令

4.  Network configuration   –>  Edit Devices  –>

eth0(……)   –> 在 Use DHCP 按下空白

(也就是開關DHCP, 讓這功能重新reload)

5. 重開機

發表迴響

plsql developer installed with ORACLE-XE on Windows Platform

注意: 如果是裝在ORACLE-XE 是裝在VMWARE WorkStation上, 記得把 SELinux 先關掉!
1.先安裝 plsql developer http://www.allroundautomations.com/plsqldev.html

2.下載並解壓縮放置 Oracle Instant Client: instantclient-basic-win32-11.1.0.7.0 (假設是 C:\instantclient_11_1 )

3.下載並安裝oracle-xe client :  OracleXEClient.ex

e (如照預設, 應會建立 C:\XEClient  資料夾)

在 C:\XEClient 資 料夾下 (實際操作後, 發現應建立於此, 而非 C:\instantclient_11_1 )

建立一network目錄,目录下再建admin目錄,結構如下:

<客户端目錄>/network/admin

,在admin目录中建立tnsnames.ora文件,内容大致如下:

XE=
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)

4.

在PL/SQL developer中配置客户端信息。

打开PL/SQL developer,暂不登录,选择菜单tools->preferences->connection,设置如下两项:

Oracle Home:  XEClient       #客户端解压目录

OCI library: C:\XEClient\b

in\oci.dll      #oci库文件路径,oci.dll应该在客户端目录下。

保存,重启PL/SQL developer,

些时应可看到登录框中Database下

拉选项里有你刚刚配置的

远程服务器上的服务实例demo1了。

發表迴響

«新文章 · Older Posts »
Follow

Get every new post delivered to your Inbox.