VARCHAR2(20) 與 VARCHAR2(20 BYTE) 是否相同,取決於資料庫參數 NLS_LENGTH_SEMANTICS:
參數值為 BYTE 時兩者相等;為 CHAR 時不相等。
-- 查詢目前設定
SHOW PARAMETER nls_length_semantics;
SHOW PARAMETER nls_language;
-- 範例輸出
-- 生產庫: NLS_LENGTH_SEMANTICS = BYTE, NLS_LANGUAGE = SIMPLIFIED CHINESE
-- 測試庫: NLS_LENGTH_SEMANTICS = BYTE, NLS_LANGUAGE = AMERICAN
注意: 參數修改僅影響後續建立的欄位,現有欄位定義不變。
PERSON VARCHAR2(32)
'二郎公交車站對面18355200098代簽' -- 21 字元 (含中文、數字)
SELECT PERSON
FROM temp_opt_order_trace
WHERE LENGTH(PERSON) = 21; -- LENGTH 回傳字元數
LENGTH() 回傳 21 → 字元長度 21 (中文、英文、數字各算 1)。VARCHAR2(32) 以字元為單位可存入,不受 NLS_LENGTH_SEMANTICS=BYTE 影響 (11.2.0.1 實測)。| 字元集 | 中文佔用 | 英數佔用 | 備註 |
|---|---|---|---|
| AL32UTF8 / UTF8 | 3 bytes | 1 byte | Unicode 標準,推薦 |
| ZHS16GBK / ZHT16MSWIN950 | 2 bytes | 1 byte | 傳統中文環境常見 |
| US7ASCII | 不支援 | 1 byte | 僅英數 |
VARCHAR2(20 CHAR) 或 VARCHAR2(20 BYTE),避免依賴參數預設值造成遷移差異。AL32UTF8,支援全語系、Emoji、補充字元。CHAR 語義給予 2~3 倍緩衝 (如身分證 20 CHAR、地址 200 CHAR)。DBMS_METADATA 保留明確語義,避免目標庫參數不同導致結構不一致。| 誤區 | 正確觀念 |
|---|---|
| VARCHAR2(n) 永遠是 n 個位元組 | 視 NLS_LENGTH_SEMANTICS 而定,預設 BYTE,可改 CHAR |
| NLS_LANGUAGE 決定字元長度 | NLS_LANGUAGE 只影響訊息語言、排序規則,不影響長度語義 |
| LENGTH() 回傳位元組數 | LENGTH() 回傳字元數,位元組數用 LENGTHB() |
| 修改參數即可縮減現有表空間 | 參數只影響新建欄位,既有資料不重組 |
-- 列出所有 VARCHAR2/CHAR 欄位的長度語義
SELECT owner, table_name, column_name, data_type, char_length, char_used
FROM all_tab_columns
WHERE data_type IN ('VARCHAR2','CHAR')
ORDER BY owner, table_name;
CHAR_USED = 'B' 表 BYTE,'C' 表 CHAR。