ORA-01461: can bind a LONG value only for insert into a LONG column
SQL Error: 1461, SQLState: 72000
org.hibernate.QueryTimeoutException: Could not execute JDBC batch update
Caused by: java.sql.BatchUpdateException: ORA-01461...
表字段定義為 VARCHAR2(1024),但實際插入數據長度超過 4000 字節(VARCHAR2 最大 4000 bytes)。Oracle 內部嘗試將該值隱式轉換為 LONG 類型處理,但 JDBC 綁定機制不支持向非 LONG 列綁定 LONG 值,從而拋出異常。
關鍵點:
| 方案 | 適用場景 | 實施步驟 | 優缺點 |
|---|---|---|---|
| 1. 業務截斷/校驗 | 數據本不應超長(如日誌溢出、攻擊數據) | 入參校驗,超長截取或拋異常 | ✅ 簡單、無 schema 變更 ❌ 可能丟失數據 |
| 2. 遷移至 CLOB | 合法長文本(文章、JSON、XML、大字段) |
| ✅ 標準方案、支持 4GB、可索引(Oracle Text) ⚠️ 需遷移腳本、JDBC 讀取需流式處理 |
| 3. 文件存儲 + 路徑入庫 | 超大二進制/文檔(圖片、PDF、視頻) | 對象存儲(S3/OSS/MinIO)或文件系統,DB 存 URL/路徑 | ✅ DB 輕量、利用 CDN、備份靈活 ⚠️ 一致性需分佈式事務或補償 |
@Entity
public class Article {
@Id @GeneratedValue
private Long id;
@Lob
@Column(columnDefinition = "CLOB", length = 1000000) // 指定長度提示
private String content; // 對應 CLOB
@Lob
@Column(columnDefinition = "BLOB")
private byte[] attachment; // 對應 BLOB
}
clob.getCharacterStream() 或 clob.getSubString(1, (int) clob.length())clob.setString(1, hugeText) 或流式 clob.setCharacterStream(1)Connection closed 導致流失效@Transactional 保證事務範圍-- 1. 新增 CLOB 列
ALTER TABLE my_table ADD (content_clob CLOB);
-- 2. 數據遷移(分批提交避免 UNDO 爆滿)
BEGIN
FOR r IN (SELECT ROWID rid, content FROM my_table WHERE content IS NOT NULL) LOOP
UPDATE my_table SET content_clob = r.content WHERE ROWID = r.rid;
IF MOD(ROWNUM, 1000) = 0 THEN COMMIT; END IF;
END LOOP;
COMMIT;
END;
/
-- 3. 切換
ALTER TABLE my_table DROP COLUMN content;
ALTER TABLE my_table RENAME COLUMN content_clob TO content;
-- 4. 可選:建立 Oracle Text 索引支持全文搜索
CREATE INDEX idx_content ON my_table(content) INDEXTYPE IS CTXSYS.CONTEXT;
ORA-01461 本質是「數據超出 VARCHAR2 容量觸發隱式 LONG 轉換」。首選業務校驗截斷,合法長文本必遷移至 CLOB,超大二進制外部存儲。切勿嘗試將列改為 LONG(已棄用、功能受限、工具鏈不支持)。