2007年5月31日 星期四

SQL*Plus 使用環境的一些限制

項目

限制

filename length system dependent
username length 30 bytes
user variable name length 30 bytes
user variable value length 240 characters
command-line length 2500 characters
length of a LONG value entered through SQL*Plus LINESIZE value
LINESIZE system dependent
LONGCHUNKSIZE value system dependent
output line size system dependent
line size after variable substitution 3,000 characters (internal only)
number of characters in a COMPUTE command label 500 characters
number of lines per SQL command 500 (assuming 80 characters per line)
maximum PAGESIZE 50,000 lines
total row width

60,000 characters for VMS;

otherwise, 32,767 characters

maximum ARRAYSIZE 5000 rows
maximum number of nested scripts

20 for VMS, CMS, Unix;

otherwise, 5

maximum page number 99,999
maximum PL/SQL error message size 2K
maximum ACCEPT character string length 240 Bytes
maximum number of DEFINE variables 2048

SQL*Plus COPY 命令筆記

透過 SQL*Plus(9iR2) COPY 命令可以直接在不同資料庫間複製表格內容,支援模式如下:

  1. 由本地資料庫至遠端資料庫 (預設)
  2. 由遠端資料庫至本地資料庫
  3. 由遠端資料庫至遠端資料庫

來源表格欄位支援以下資料型態:CHAR、DATE、LONG、NUMBER、VARCHAR2,但不支援 LOB 這類資料型態。

SQL*Plus COPY 語法

COPY {FROM database | TO database | FROM database TO database} {APPEND|CREATE|INSERT|REPLACE} destination_table [(column, column, column, ...)] USING query

參數說明:

FROM database 指定資料來源資料庫
TO database 指定目標資料庫
database 以 username[/password] @connect_identifier 格式指定
APPEND 會直接將複製資料INSERT至指定目的表格,如果指定目的表格不存在會先建立指定目的表格。
CREATE 複製資料前會先建立指定目的表格,如果指定目的表格已經存在會傳回錯誤訊息。
INSERT 如果指定目的表格已經存在會傳回錯誤訊息,使用這個選項必須指定欄位名稱。
REPLACE 如果指定目的表格已經存在會刪除舊有的表格,如果不存在則複製資料前會建立表格。
destination_table 指定目的表格名稱。
(column, column, column, ...) 以逗點隔開的目的表格的資料欄別名。
USING query 任何有效的 SQL SELECT 敘述句。

通常 COPY 指令是用於 Oracle 和 non-Oracle 資料庫間的表格複製,因此如果同樣是在 ORACLE,應該使用 SQL 指令 (CREATE TABLE AS 和 INSERT) 。

Usage:
To enable the copying of data between Oracle and non-Oracle databases, NUMBER columns are changed to DECIMAL columns in the destination table. Hence, if you are copying between Oracle databases, a NUMBER column with no precision will be changed to a DECIMAL(38) column. When copying between Oracle databases, you should use SQL commands (CREATE TABLE AS and INSERT) or you should ensure that your columns have a precision specified.

The SQL*Plus SET LONG variable limits the length of LONG columns that you copy. If any LONG columns contain data longer than the value of LONG, COPY truncates the data.

SQL*Plus performs a commit at the end of each successful COPY. If you set the SQL*Plus SET COPYCOMMIT variable to a positive value n, SQL*Plus performs a commit after copying every n batches of records. The SQL*Plus SET ARRAYSIZE variable determines the size of a batch.

Some operating environments require that service names be placed in double quotes.

範例:

COPY FROM HR/your_password@HQ TO JOHN/your_password@WEST REPLACE WESTEMPLOYEES USING SELECT * FROM EMPLOYEES

參考文件:

SQL*Plus User's Guide and Reference Release 9.2:Part Number A90842-01:APPEND B:SQL*Plus COPY Command

2007年5月29日 星期二

將 Oracle 9i export 出的 dump file 匯入指定帳號、指定表格空間

如何將 Oracle 9i export 工具(exp) 輸出的 Oracle binary-format dump file 匯入指定帳號、並指定表格空間?

網路上有不少人提出了這樣奇怪的問題,這個問題很重要嗎?為什麼會有這樣的需求?在我看來有這樣的問題是一件很奇怪的事。

如果是客戶對軟體公司的產品或修補發生這樣的需求,可以推測很可能是軟體公司的開發人員直接將開發平台上的資料庫匯出來給客戶,而不是採用執行SQL Script的方式來更新資料庫中物件的Schema或資料,對很多公司有重要 Oracle 資料庫的 DBA,大概都很難接受這樣的事情,因為根本不曉得匯入的物件是不是有問題,也很難確定匯出的資料,轉到匯入的平台版本是否不會有問題(是否上了相同的修補檔)。萬一不幸匯入中的物件與原資料庫中有相同的物件名稱,又沒注意到一不小心可能就造成大災難了。如果資料庫大的話匯入的工程浩大又費時,當然匯入前要先作完整備份、匯入後要馬上作完整備份比較安全,如果是Archive Log Mode,那一堆的Archive Log 就要思考一下,匯入時是不是要暫時停止 Archive Log 的運作。

Oracle export 及 import 工具是用來轉移 Oracle Database 到另一個平台的工具,如果僅僅是想透過這個工具在不同的帳號和指定的表格空間中轉移,可能會很失望,因為他們不是為這個目的被設計出來的,不信邪,試到鬍鬚白了又打結也一樣。

以下是 Oracle Database Administration Fundamentals II 教材對 export 及 import 工具的說明:

The Export utility provides a simple way for you to transfer data objects between Oracle database, even if they reside on platforms with different hardware and software configurations.

When you run Export against an Oracle database, objects(such as tables) are extracted, followed by their related objects(such as indexes, comments, and grants), if any. The extracted data is written to an Export file, which is an Oracle binary-format dump file that is typically located on disk or tape.

The Import utility reads the object definitions and table data from an Export dump file. It inserts the data objects into an Oracle database.

Import 工具的執行順序過程:

  1. 建立新表格。
  2. 資料匯入表格。
  3. 建立索引。
  4. 匯入Trigger。
  5. 設定新表格上的 constraints。
  6. 建立其它 bimap,function,domain index。

首先使用 Oracle 9i export 和 import 工具有幾個觀念要釐清:

  1. 用來執行 import 工具的版本不能低於 export 版本。
  2. Oracle Export 及 Import 工具沒有任何選項、參數可以指定匯入的表格空間 (Tablespace)。
  3. Import 時會在目的 "資料庫帳號下的表格空間(Tablespace)" 中建立物件,而不是在目的 "帳號預設的表格空間(Tablespace)" 中建立物件。匯入時 import 程式在建立表格時會指定使用的表格空間,而表格空間名稱就是原匯出時的名稱,大部份情況在指定的表格空間不存在時,會改用匯入帳號預設的表格空間,但當表格中有比較特別的資料型態時,則無法使用匯入帳號預設的表格空間建立表格,而造成匯入失敗,這也是最多人搞不清楚的一點。
  4. 表格在表格空間裡並不是不可以被移動的,可以透過簡單的指令移動。
  5. 索引在表格空間裡雖然無法被移動的,但是可以透過簡單的指令重建。

觀念釐清後我們可以利用 export 及 import 工具先將資料庫物件轉移到目標資料庫,再作一些工作來達成目標(指定帳號、並指定表格空間),以下是簡單的步驟:

  1. 建立所需表格空間及調整表格空間的存取權限讓 Oracle Import 工具能正確無誤的執行,匯入到指定的帳號下。imp 中加入INDEXES=N參數、INDEXFILE=index.sql,產生建立索引指令的檔案 index.sql,索引等到表格都搬到正確表格空間再重建。
  2. 若由較低版本資料庫匯出的檔案,可能需要執行一些修正檔(略,自行處理)。
  3. 使用 ALL_TABLES View 查詢那些表格需要被移動。
  4. 使用 表格在表格空間移動的指令。移動指令:ALTER TABLE <table name> MOVE TABLESPACE <tablespace name>
  5. 如果表格中有 LOB 這類資料類型的欄位,則還需將這些欄位的資料移至新的表格空間。查詢 ALL_TAB_COLUMNS View;
  6. 移動LOB 這類資料類型的欄位資移至新的表格空間。移動指令:ALTER TABLE <table name> MOVE LOB(lobseg name) STORE AS (TABLESPACE <>tablespace name);
  7. 編輯 index.sql 檔案中 tablespace 的設定。
  8. 執行 index.sql 重建索引,或自行下指令重建需要移動表格空間的索引。重建索引的指令:ALTER INDEX <index name> REBUILD TABLESPACE <tablespace name>。

步驟 3、4,5、6,7、8 是可以寫成一個PL/SQL程序來執行的(略)。

其它參考資訊-Oracle 10g 如何變更 TABLESPACE NAME:

  1. Oracle 10g 新增指令,可以透過指令變更 TABLESPACE NAME,這和之前的版本比較,舊版本要變更 TABLESPACE NAME 是件浩大的工程。
  2. 指令:ALTER TABLESPACE <tablespace old name> RENAME TO <tablespace new name>;
  3. 資料庫 compatibility level 最低必須設為 10.0.1。
  4. 不能更改 SYSTEM、SYSAUX tablespace 表格名稱。
  5. 不能更改 offline tablespace。
  6. 不能更改 含有 offline datafiles 的 tablespace 名稱。
  7. 更改 tablespace 名稱,不會變更 tablespace identifier。
  8. 更改 tablespace 名稱,不會變更 tablespace 中 datafile 的名稱。

2007年5月23日 星期三

Linux 使用 USB 裝置筆記

USB規格簡介

USB Univeral Serial Bus (通用串列匯流排),常見的外部匯流排,支援熱插拔 (hot plugable),一個 USB 最多可以連接127個裝置。

目前規格包括:
  1. USB 1.1 支援二種傳輸速率:Low speed - 1.5 Mbps 及 Full Speed - 12 Mbps。
  2. USB 2.0 傳輸速率 480 Mbps 並支援 USB 1.1。

USB 採用 Single-Master (單主控) 設計,線路架構就像多個點對點的樹狀結構,具 USB 介面的 PC 至少有一個 "root hub",並提供二個外接孔供 USB 設備或另一個 USB hub。在電腦中的 USB 主控器會去 poll USB 匯流排上的各個裝置,每個 USB 設備連接到主機時,USB 主控器會分配一個代碼給該裝置,並讀取該裝置的描述表 (Device Descriptor) 以獲知裝置的硬體資訊。

USB 主控器(USB hoot Controller) 分為三種規格:

  1. OHCI (Open Host Controller Interface):USB 1.1 規格,Compaq(康柏)公司主導, 使用廠商包括 Compaq、iMacs、OPTi、SIS、ALi,採用 Memory-mapped 的 I/O 方式 (CPU 使用記憶體指令來存取 USB 主控器)。
  2. UHCI (Universal Host Controller Interface) :USB 1.1 規格,Intel公司提倡, 線路比 OHCI 線路簡單,但是需要比較複雜的驅動程式,對CPU負擔也微重了些,使用廠商包括 Intel、VIA,採用 I/O-mapped 的 I/O 方式 (CPU 使用 I/O 指令來存取 USB 主控器)。
  3. EHCI (Enhanced Host Controller Interface):USB 2.0 規格,速度較快 (480 Mbps),支援 USB 1.1,相容於 OHCI 和 UHCI。

Linux 對 USB的支援

Linux 從 kernel 2.2.7 版本便開始支援 USB,USB 2.0 是從 2.4.19 開始, Linux 以三層式架構來支援 USB 系統,這三層是內核層 (Core) 、主控層 (Controller)、裝置層 (Device)。內核層指的是 kernel 對 USB 系統的支援,主控層對應到不同規格的 USB 主控器,連接 USB 設備時不必考慮主控器的規格,裝置層的設定,依裝置類型會有所不同。

Linux USB 驅動程式共有三種不同的 USB 主控制器選項,因為在主板和 PCI 卡上有三種不同類型的 USB 控制晶片。

  1. EHCI (ehci-hcd.o) :USB 2.0 協定的晶片。
  2. OHCI (usb-ohci.o) :非 PC 系統上的(以及帶有 SiS 和 ALi 晶片組的 PC 主板上的)USB 晶片。
  3. UHCI (usb-uhci.o) :大部份 PC 主機板(包括 Intel 和 Via)。

在 Linux 下可查詢 /proc/pci 所記錄的 PCI 子系統資源配置情況,或指令 lspci,從中分辦出 USB 主控器屬於那種規格,只需載入 USB 類型對應的 ?HCI 驅動程式即可,若單獨載入 EHCI 不行,則根據主板類型載入UHCI 或 OHCI 後,再載入EHCI。

使用 usbmodules 指令可查詢己連接至系統的 USB 裝置有那些可以使用的核心驅動模組,在載入/卸載核心模組會利用到 usbmodules 程式,利用 hotplug 或 usbmgr 程式可以在 USB 裝置與電腦連接/移除時,自動載入/卸載核心模組、執行相關 Scripts。

Linux 相關的指令和檔案:

mount none /proc/bus/usb -t usbdevfs
usbmodules
hotplug
usbmgr
/etc/usbmgr/
/etc/hotplug/

Linux 對應USB設備一些常用必要的驅動程式模組:
usbcore.o:支援usb所需要的最基礎模組。
usb-uhci.o / usb-ohci.o / ehci-hcd.o:USB 控制晶片驅動程式。
uhci.o :另一個uhci驅動程式,一般不需載入,可能會當機。
hid.o:USB人機界面設備,如滑鼠、鍵盤。
usbmouse.o:USB滑鼠(還需再載入mousedev.o)。
usbkbd.o:USB鍵盤(還需再載入keybdev.o)。
usb-storage.o:USB 存儲設備,Flash Disk 等。
usbnet.o:USB並聯線,讓兩部電腦資料透過USB傳輸。


Linux 相關驅動程式模組:

ide-disk.o :IDE硬碟。
ide-scsi.o :把IDE設備類比SCSI介面。
scsi_mod.o:SCSI 裝置。
sd_mod.o:SCSI硬碟。
sr_mod.o:SCSI光碟機。
sg.o:SCSI 一般裝置,在某些 Flash Disk、SCSI裝置偵測中會使用到。


Linux 使用 Flash Disk 需要載入的模組:

1.usbcore
2.usb-uhci / usb-ohci / ehci-hcd
3.scsi_mod
4.sd_mod
5.usb-storage

2007年5月18日 星期五

建置 uClibc 開發環境

uClibc是嵌入式Linux作業系統系統的C語言程式庫,可以在標準的 Linux 或沒有記憶體管理單元的Linux系統,如uCLinux。uClibc比GNU的C語言程式庫小的多,幾乎所有被glibc支援的應用程式都可以順利的移植過去,由 glibc 移植到 uClibc 只需重新編譯程式碼,目前處理器平台有 i386、i960、h8300、m68k、mips/mipsel、PowerPC、SH、SPARC及v850處理機。

安裝及設定 uClibc 的環境有點麻煩,好在uClibc 提供了root_fs image,如果不是很堅持一定要自己建置開發環境,可以由官方網站直接下載使用。

步驟如下:

1.Download root_fs_i386.bz2 from uclibc.org http://www.uclibc.org/downloads/
2.bunzip2 root_fs_i386.bz2
3.mkdir root_fs
4.su root
5.mount -o loop root_fs_i386 root_fs
6.chroot root_fs /bin/su -

2007年5月7日 星期一

如何解決 /var/spool/cilentmqueue 中有大量檔案無法刪除

/var/spool/clientmqueue 目錄是 smmsp:smmsp 使用者目錄,僅用於郵件的收受與傳遞,增加這個使用者是 sendmail 8.12 後新增,主要的目的在於提供更安全的 sendmail 使用環境。啟動Sendmail 程式之前,client 端寄出的信件會暫存到/var/spool/clientmqueue 中,因此如果系統沒有啟動 sendmail 時,/var/spool/clientmqueue 下所產生的檔案時間久了會灌爆系統的硬碟空間。

Unix系統預設有可用的MTA,將 sendmail完全停用而又不安裝其他 MTA 會導致非常多的問題,一些應用程式也會透過 email 傳送程式執行結果或通知,例如 crond。

出現這個問題主要在於系統沒有可用的 MTA,最大的原因是把系統的 MTA (例如:sendmail) 關閉了,卻沒有作適當的設定。如果是為了安全上的考量關閉 sendmail,可以使用限制連線的設定,而不要關閉 sendmail 比較好。

刪除 /var/spool/cilentmqueue 目錄中檔案的方法,可以使用

rm -rf /var/spool/cilentmqueue/*

有時因為 /var/spool/cilentmqueue 下檔案數量太多,而造成無法刪除,可以使用先刪除整個目錄再重建目錄

rm -rf /var/spool/cilentmqueue

mkdir /var/spool/cilentmqueue

chown smmsp.smmsp /var/spool/cilentmqueue

若是想保留之前應用程式發送的email訊息,可以將sendmail 啟動,sendmail 會自動處理/var/spool/cilentmqueue 未送出的email,處理完後/var/spool/cilentmqueue 自然清空。

2007年5月1日 星期二

Mysql 函式 current_user() 及 USER()、SYSTEM_USER()、SESSION_USER() 差異

Mysql 函式 current_user() 及 USER()、SYSTEM_USER()、SESSION_USER() 有何差異,以下是文件的定義說明:

  1. USER()、SYSTEM_USER()、SESSION_USER() 傳回目前 MySQL 使用者名稱,在 MySQL 3.22.11 或更新的版本中,傳回值包含使用者名稱和客戶機的主機名稱。
  2. CURRENT_USER() 傳回目前連線帳號被驗証的使用者名稱。


使用下面的範例就可以很快的瞭解之間的差異
1.先建立一個測試用的帳號
CREATE USER 'user'@ '%' IDENTIFIED BY 'user';

2.使用建立的帳號由不同的機器連線

由本機連線結果

由另一部機器連線結果

由以上實驗結果可以發現current_user() 不會因為不同連線機器的結果而不同,USER()、SYSTEM_USER()、SESSION_USER() 會因不同連線機器有所差異。


應用:

Q1.取出目前連線的使用者帳號?

A1.SELECT SUBSTRING_INDEX(USER(),"@",1); 或 SELECT SUBSTRING_INDEX(CURRENT_USER(),"@",1);

Q2.取出目前連線的主機名稱?

A2.SELECT SUBSTRING_INDEX(USER(),"@",-1);