首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle LONG 數據類型深度解析:特性、限制與現代替代方案

     編輯:Oracle 資料庫基礎

LONG 類型核心特性檔案

屬性規格
數據類別變長字符串
最大長度2 GB (2^31 - 1 字節)
存儲方式行內存儲 (小於 ~4KB) 或行外 LOB 段 (大於 ~4KB),與表數據同段
字符集數據庫字符集 (NLS_CHARACTERSET)
主要用途歷史原因存儲超長文本 (數據字典視圖定義、舊應用大文本)
狀態已棄用,Oracle 8.0+ 引入 LOB (CLOB/NCLOB) 替代,**新開發嚴禁使用**

LONG 類型「十大限制」 — 開發與遷移必讀

  1. 單表單列:一張表**最多只能有一個 LONG 列**。
  2. 不可索引:無法創建任何類型索引 (B-tree, Bitmap, Function-based, Domain),全文搜索無能為力。
  3. 不可分區/聚簇:含 LONG 列的表**不能**進行範圍/哈希/列表分區,也不能加入聚簇。
  4. SQL*Plus 直接操作受限:
    • `INSERT INTO t2 SELECT * FROM t1` (含 LONG) → **報錯 ORA-00997**
    • `CREATE TABLE t2 AS SELECT * FROM t1` (含 LONG) → **報錯 ORA-00997**
  5. 約束極少:僅支持 `NULL` / `NOT NULL` / `DEFAULT`,**不能** 定義 PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY。
  6. 查詢子句禁用:LONG 列**不能**出現在 `WHERE`, `GROUP BY`, `ORDER BY`, `DISTINCT`, `CONNECT BY`, `START WITH` 子句中。
  7. 分布式查詢禁用:`SELECT long_col FROM table@dblink` → **報錯 ORA-00997**。
  8. PL/SQL 變量不支持:`DECLARE v_long LONG;` → **編譯錯誤 PLS-00382**。PL/SQL 僅能通過 `LONG` 類型的游標隱式處理,無法賦值給變量。
  9. SQL 函數不支持:`SUBSTR(long_col,1,10)`, `INSTR(long_col,'x')`, `LENGTH(long_col)`, `UPPER(long_col)` 等**全部報錯 ORA-00932**。
  10. 觸發器 :NEW/:OLD 不支持:行級觸發器中引用 `:NEW.long_col` 或 `:OLD.long_col` → **報錯 ORA-04082**。

僅支持的三類 SQL 操作

  1. `SELECT long_col FROM table` — 返回數據 (受客戶端工具緩衝區限制,如 SQL*Plus `SET LONG 2000000000`)。
  2. `UPDATE table SET long_col = 'new value' WHERE pk = :id` — `SET` 子句賦值字面量或綁定變量。
  3. `INSERT INTO table (pk, long_col) VALUES (:id, :long_val)` — `VALUES` 子句插入字面量或綁定變量。

數據字典中的 LONG 遺產

Oracle 內部數據字典視圖 (如 `ALL_VIEWS.TEXT`, `ALL_TRIGGERS.TRIGGER_BODY`, `ALL_SOURCE.TEXT`, `ALL_CONSTRAINTS.SEARCH_CONDITION`) 歷史使用 LONG 存儲定義文本。12c+ 逐步遷移至 CLOB (如 `DBA_VIEWS.TEXT_VC` CLOB 版本),但為兼容性保留 LONG 列。

現代替代方案:CLOB / NCLOB 全面優勢

能力LONGCLOB / NCLOB
最大長度2 GB4 GB ~ 128 TB (取決於塊大小)
每表列數1無限制
索引支持無Oracle Text (Context/CTXCAT/CTXRULE)、Function-based 索引、JSON 索引 (21c+)
分區/聚簇不支持完全支持
SQL 函數無SUBSTR, INSTR, LENGTH, UPPER/LOWER, REPLACE, REGEXP_*, JSON_* 等全支持
PL/SQL 變量不支持原生支持 `CLOB` 變量、DBMS_LOB 操作
分布式查詢不支持支持 (DBLink 讀寫)
觸發器引用不支持支持 `:NEW.clob_col`, `:OLD.clob_col`
存儲選項行內/行外固定ENABLE STORAGE IN ROW / DISABLE STORAGE IN ROW、SECUREFILE / BASICFILE、壓縮/去重/加密
並行 DML不支持支持
工具兼容性極差優秀 (JDBC/ODP.NET/ODBC/SQL*Plus/Data Pump/Expdp/Impdp/GoldenGate 完美支持)

LONG → CLOB 遷移實戰方案

方案一:ALTER TABLE MODIFY (11g+ 推薦,在線、無鎖、秒級元數據變更)

-- 1. 確認表結構
DESC old_table_with_long;

-- 2. 執行轉換 (僅元數據操作,數據不移動,極快)
ALTER TABLE old_table_with_long MODIFY (long_col CLOB);

-- 3. 驗證
DESC old_table_with_long; -- 長列類型變為 CLOB
SELECT long_col FROM old_table_with_long WHERE ROWNUM=1; -- 可正常 SELECT
-- 4. 後續可選:啟用 SecureFile、壓縮、去重
ALTER TABLE old_table_with_long MODIFY LOB (long_col) (COMPRESS HIGH DEDUPLICATE ENCRYPT USING 'AES256');

注意:轉換後原有限制解除,但**現有索引/約束/觸發器/視圖/PL/SQL 依賴可能失效**,需重新編譯/重建。

方案二:TO_LOB 函數 + CTAS (10g/11g 通用,需鎖表、空間雙倍)

-- 1. 創建新表 (含 CLOB 列)
CREATE TABLE new_table AS
SELECT pk_col, other_cols, TO_LOB(long_col) AS clob_col
FROM old_table_with_long;

-- 2. 重建索引/約束/權限/觸發器/同義詞
-- 3. 切換表名 (RENAME + SYNONYM 或應用層切換)
RENAME old_table_with_long TO old_table_with_long_bak;
RENAME new_table TO old_table_with_long;

方案三:Data Pump 導出導入 (跨版本/跨平台/大表分區並行)

# 1. 導出 (含 LONG 表)
expdp system/pass directory=dp_dir dumpfile=long_tab.dmp logfile=exp.log tables=schema.old_table_with_long

# 2. 導入時自動轉換 (12c+ impdp 遇到 LONG 自動轉 CLOB)
# 或預先創建目標表含 CLOB 列,使用 TABLE_EXISTS_ACTION=TRUNCATE/REPLACE
impdp system/pass directory=dp_dir dumpfile=long_tab.dmp logfile=imp.log \
    table_exists_action=REPLACE \
    remap_table=schema.old_table_with_long:schema.new_table_clob \
    transform=segment_attributes:n:table  # 可選:去除存儲屬性

PL/SQL 處理 LONG 的歷史變通技巧 (僅供維護舊系統參考)

1. 使用 LONG 類型游標讀取 (無法賦值給變量)

DECLARE
    CURSOR c_long IS SELECT long_col FROM old_table WHERE pk = 1;
    l_long_val LONG; -- 僅用於 FETCH 目標,不可操作
BEGIN
    OPEN c_long;
    FETCH c_long INTO l_long_val; -- 僅能 FETCH,不能 DBMS_OUTPUT/SUBSTR
    CLOSE c_long;
END;
/

2. 利用 SQL*Plus / SQLcl 變量繫結 (腳本級導出)

-- SQL*Plus 腳本
SET LONG 2000000000
SET LONGCHUNKSIZE 32767
SET LINESIZE 32767
SET PAGESIZE 0
SET TRIMSPOOL ON
SPOOL long_data.txt
SELECT long_col FROM old_table WHERE pk = 1;
SPOOL OFF

3. Java / C# / Python 客戶端流式讀寫 (JDBC/ODP.NET/cx_Oracle)

現代驅動程序將 LONG 視為流 (Stream/Blob/Clob) 處理,可繞過 SQL 層限制直接讀寫大對象。但**強烈建議先遷移至 CLOB**。

總結

  • LONG 是 **Oracle 7 遺留產物**,Oracle 8.0 (1997) 即標記棄用,**新開發絕對禁止使用**。
  • 限制極多:單列、無索引、無函數、無 PL/SQL 變量、無分布式、無分區、工具支持差。
  • **現有 LONG 列必須遷移至 CLOB/NCLOB** (首選 `ALTER TABLE MODIFY`,11g+ 秒級在線)。
  • CLOB/NCLOB (特別是 SecureFile LOB) 提供完整 SQL/PL/SQL/索引/分區/壓縮/加密/去重/分布式能力,是大文本存儲唯一正解。
  • 數據字典視圖 LONG 列 (如 `ALL_VIEWS.TEXT`) 12c+ 提供 CLOB 對應列 (如 `TEXT_VC`),優先使用 CLOB 版本視圖。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved