Oracle、SQL Server、PostgreSQL处理LOB必须严格区分类型路径:Oracle需全程用CLOB变量并TO_CLOB()转换,SQL Server须分块.WRITE()避免隐式截断,PostgreSQL需用oid字段存LO OID且事务内操作。

直接用 VARCHAR2 或 varchar(max) 变量拼接、赋值、传参,基本都会 silently 截断或报错——这不是配置问题,是类型路径没走对。
Oracle 存储过程里必须全程用 CLOB 变量
哪怕字段已是 CLOB,只要中间变量声明成 VARCHAR2,就可能在拼接、EXECUTE IMMEDIATE、LISTAGG 返回值等环节被截断,且不报错。
- 声明变量时写
my_text CLOB;,别用my_text my_table.text_col%TYPE(可能继承旧VARCHAR2定义) - 字符串字面量拼接必须每个都套
TO_CLOB():my_text := TO_CLOB('a') || TO_CLOB('b') || TO_CLOB('c'); -
LISTAGG结果必须包TO_CLOB():SELECT TO_CLOB(LISTAGG(name, ',') WITHIN GROUP (ORDER BY id)) FROM t; - 动态 SQL 中插入 CLOB,不能拼字符串,要用绑定变量:
EXECUTE IMMEDIATE 'INSERT INTO t(c) VALUES (:1)' USING my_text;
SQL Server 存储过程别信 varchar(max) 能直赋
表面支持 SET @blob = @data,但协议层、隐式转换、中间计算会悄悄截断——尤其客户端传入超 4MB 或 T-SQL 内拼接时。
- 安全写法是分块覆盖:
UPDATE t SET blob_col.WRITE(@chunk, @offset, LEN(@chunk)) WHERE id = @id; - 避免
@a + @b + @c拼接,中间结果可能被隐式转成 8000 字节varchar - 客户端上传大文本,优先走参数绑定,别拼进 SQL 字符串里
- 读取时慎用
CAST(blob_col AS varchar(max)),超长内容可能被截或报错,直接用原字段参与运算
PostgreSQL 的 LO 不是 bytea,混用就存失败
想存大文本进 lo(大对象),就不能往 bytea 字段里塞;反过来,往 bytea 里存大文本,也不能用 lo_from_bytea() 返回 OID。
- 业务表字段类型必须是
oid(不是int4),才能存lo_from_bytea(0, $1)返回的 OID - 存完必须
COMMIT,否则 LO 对象会被自动清理 - 读取用
lo_get(oid),它一次性加载全部内容进内存——>100MB 小心 OOM - 别在事务里反复调
lo_from_bytea()生成新 OID,旧 LO 不会自动释放,得手动lo_unlink()
最易忽略的是:Oracle 的 LOB 定位器一旦 SELECT ... FOR UPDATE 出来,就必须在同一个事务里写完;SQL Server 的 .WRITE() 偏移量必须精确等于当前长度;PostgreSQL 的 lo_get() 没流式接口,全量加载是唯一选择。

















