【问题标题】:Oracle appending to a clobOracle 附加到 clob
【发布时间】:2021-12-07 14:43:56
【问题描述】:

我有一个工作场景,每次更新期间都会向 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;
 /

【问题讨论】:

    标签: oracle procedure clob


    【解决方案1】:
    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 位置的新 lob 定位器(我们称之为 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。当过程返回时,它会立即被丢弃。 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;
    /
    

    【讨论】:

    • 感谢详细的解释和修复
    猜你喜欢
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 2010-12-04
    • 2019-09-05
    • 1970-01-01
    相关资源
    最近更新 更多