oracle中插入超长文本到clob字段必须分两步:①用empty_clob()占位并select...for update获取可写句柄;②用dbms_lob.writeappend分段写入(每段≤32767字节),或用dbms_lob.copy高效复制;临时clob需设cache=>true并显式调用freetemporary释放。
直接往 clob 字段里拼字符串或用 insert into t(clob_col) values ('...') 插入超长文本,大概率会报 ora-01704(字符串字面量太长)或 ora-22922(nonexistent lob value),根本原因是 oracle 不允许在 sql 语句中隐式构造超过 4000 字节的字符串,且未初始化的 lob 句柄无法写入。
PL/SQL 中插入/更新 CLOB 必须先占位再锁定
不能跳过初始化步骤。必须分两步走:先用 EMPTY_CLOB() 占位,再 SELECT ... FOR UPDATE 获取可写句柄。
INSERT INTO my_table(id, content) VALUES (123, EMPTY_CLOB());- 紧接着执行
SELECT content INTO :clob_var FROM my_table WHERE id = 123 FOR UPDATE;—— 缺少FOR UPDATE就会触发ORA-22920 -
:clob_var是声明为CLOB类型的 PL/SQL 变量,后续用DBMS_LOB.WRITEAPPEND往里追加
写入超长内容必须分段,每次 ≤32767 字节
DBMS_LOB.WRITEAPPEND 的第二个参数是长度,第三个是 VARCHAR2 值;而 PL/SQL 中 VARCHAR2 最大就是 32767 字节。超出就得切片。
- 别试图一次性传入 10MB 字符串 —— 会编译失败或运行时报
PLS-00172 - 推荐按 4000 或 8000 字节切片(避开多字节字符截断风险),用循环调用
DBMS_LOB.WRITEAPPEND - 如果源数据来自另一个
CLOB,优先用DBMS_LOB.COPY,比读-写更快更安全
用临时 CLOB 时 cache 参数和释放不能省
调用 DBMS_LOB.CREATETEMPORARY 创建的 CLOB 不在表中,只存在于 PGA 内存,必须显式管理生命周期。
-
cache => TRUE是硬性要求:设为FALSE会导致后续DBMS_LOB.READ读不到内容(返回空) - 写完必须调用
DBMS_LOB.FREETEMPORARY,否则内存不释放,长期运行会引发 PGA 耗尽、ORA-04030 - 临时 CLOB 不能传给
INSERT ... VALUES直接用,得先DBMS_LOB.COPY到表中已存在的 LOB 句柄里
跨数据库兼容时 CLOB 参数要降级处理
Oracle 存储过程支持 IN CLOB 参数,但 MySQL 根本不认这个类型,JDBC 层隐式转换也靠不住。
- 别在接口层声明
CLOB类型参数,改用IN VARCHAR2+ 长度校验(LENGTH(p_text) ) - 真要传超长内容,应用层拆成多行 INSERT 到辅助表,或改用外部存储(如文件系统 + 路径存 DB)
- JDBC 调用时,
setClob()在 Oracle 驱动下走原生流,在 MySQL 驱动下实际转成setString(),超长必截断 —— 这点容易被忽略
最常漏掉的是 FOR UPDATE 和 FREETEMPORARY,一个导致写失败,一个悄悄吃光内存。写完检查事务是否提交、临时资源是否释放,比优化写入逻辑更重要。











