Oracle 追加到 clob

Oracle appending to a clob

我有一个工作场景,每次更新期间都会向 CLOB 添加一个换行符。

我在下面有一个类似的情况,但似乎没有用。我不明白为什么,希望有人能解释问题所在,因为我更愿意将换行代码嵌入到过程中,而不是让用户必须为每次更新添加它。


-- Works 

ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

CREATE table t(
seq_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
c CLOB,
create_date DATE DEFAULT SYSDATE
);
/

insert into t (c) values (
      rpad('X',20,'X')
  );
/

create or replace procedure lob_append( p_id in number, p_text in varchar2 )
 as
 l_clob clob;
 begin

 select c into l_clob from t where seq_num = p_id for update;

 dbms_lob.writeappend( l_clob, length(p_text), p_text );
 end;
/

 select * from t;
 /

exec lob_append(1, chr(10)|| rpad('Z',20,'Z'));
/

select * from t;
 /

-- Doesn't work 

DROP table t;
/

CREATE table t(
seq_num integer  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
c CLOB,
create_date DATE DEFAULT SYSDATE
);
/

insert into t (c) values (
      rpad('X',20,'X')
  );
/

create or replace procedure lob_append( p_id in number, p_text in varchar2 )
 as
 l_clob clob;
 begin

 select c into l_clob from t where seq_num = p_id for update;

-- newline not added
l_clob := l_clob || chr(10);

 dbms_lob.writeappend( l_clob, length(p_text), p_text );
 end;
/

 select * from t;
 /

-- Data not added
 exec lob_append(1, rpad('Z',20,'Z'));

select * from t;
 /

select c into l_clob from t where seq_num = p_id for update;

此时在您的代码中,l_clob 包含一个 lob 定位器(我们称之为 LOCATOR_A),它指向数据库中的特定字符串.如果您调用 dbms_lob.writeappend(l_clob, ...),它将使用新值更新 LOCATOR_A 处的字符串。

l_clob := l_clob || chr(10);

当您调用此行时,第一部分 l_clob || chr(10) 创建一个指向临时 CLOB 位置的新定位器(我们称之为 LOCATOR_B),并为其提供字符串值 + 换行符。第二部分 l_clob := value 将临时 lob 定位器 LOCATOR_B 分配给 l_clob 变量。此时,您丢失了对存储在数据库中的永久 lob 指针 LOCATOR_A 的引用。

dbms_lob.writeappend( l_clob, length(p_text), p_text )

现在更新临时 lob LOCATOR_B。当程序 returns 时,它会立即被丢弃。 LOCATOR_A指向的数据库clob没有改变。

我建议改为将换行符添加到您的 varchar2,这样您就不会创建新的临时 clob。

create or replace procedure lob_append( p_id in number, p_text in varchar2 )
 as
 l_clob clob;
 begin

 select c into l_clob from t where seq_num = p_id for update;

 p_text := chr(10) || p_text;

 dbms_lob.writeappend( l_clob, length(p_text), p_text );
 end;
/