运行 背靠背时 CLOB 提交不起作用

CLOB Commits not working when run back to back

我们运行正在使用较旧的 Oracle 服务器 10.1.0.5。

我有一些简单的代码可以将一个 CLOB 替换为不同列中的另一个。 我正在用不同列中的另一个更简单的字符串替换特定字符串,因此我可以执行一些基本的 XML 解析。参考:here.

我希望执行一系列更新命令,在每个命令之间进行提交,并正确更新所有字段。如果我 运行 如下所示,只有最后一个查询被提交,尽管 运行ning 作为脚本。间歇性提交似乎不需要。

我可以通过 运行 逐行更新和提交来让它工作,但我想知道为什么我不能 运行 一次完成所有这些。我只展示了前 2 个更新。我错过了什么?

set define off

update TABLE1 SET COL_CLEANED = replace(COL_ORIGINAL,' ',  ' ');
COMMIT;

update TABLE1 SET COL_CLEANED = replace(COL_ORIGINAL,'§',  'SECT.');
COMMIT;

update TABLE1 ...

谢谢,

sse

正如@OldProgrammer 所说,您正在重复替换 COL_CLEANED 值并覆盖之前的更改...

假设您从一个需要多次替换的简单值开始:

create table table1 (col_original clob, col_cleaned clob);

insert into table1 (col_original)
values (to_clob('Test without breaks - §1'));

并进行了第一次更新:

update TABLE1 SET COL_CLEANED = replace(COL_ORIGINAL,' ',  ' ');

select col_original, col_cleaned from table1;

COL_ORIGINAL                             COL_CLEANED                             
---------------------------------------- ----------------------------------------
Test without breaks - §1  Test without breaks - §1           

现在进行第二次更新:

update TABLE1 SET COL_CLEANED = replace(COL_ORIGINAL,'§',  'SECT.');

select col_original, col_cleaned from table1;

COL_ORIGINAL                             COL_CLEANED                             
---------------------------------------- ----------------------------------------
Test without breaks - §1  Test without breaks - SECT.1  

没有提交也没有回滚。但是你采用了 original 值——它仍然有两个旧模式——并替换了其中的第二个模式。第一次更新只是被第二次覆盖。

您需要对 cleaned 值应用连续更新;只有第一次更新使用原始值:

-- first update is based on COL_ORIGINAL
update TABLE1 SET COL_CLEANED = replace(COL_ORIGINAL,' ',  ' ');

select col_original, col_cleaned from table1;

COL_ORIGINAL                             COL_CLEANED                             
---------------------------------------- ----------------------------------------
Test without breaks - §1  Test without breaks - §1           

-- subsequent updates are based on COL_CLEANED to keep earlier changes    
update TABLE1 SET COL_CLEANED = replace(COL_CLEANED,'§',  'SECT.');
--------------------------------------------^^^^^^^

select col_original, col_cleaned from table1;

COL_ORIGINAL                             COL_CLEANED                             
---------------------------------------- ----------------------------------------
Test without breaks - §1  Test without breaks - SECT.1            

顺便说一下,这些提交并不是真正需要的;您应该为每个逻辑事务提交一次,而不是为每个语句提交一次。


顺便说一句,您可以为此使用 the utl_i18n.unescape_reference() function,但在您的示例中,它会给您多字节 'section' 字符而不是字符串 'SECT.':

update TABLE1 SET COL_CLEANED = UTL_I18N.UNESCAPE_REFERENCE(COL_ORIGINAL);

select col_original, col_cleaned from table1;

COL_ORIGINAL                             COL_CLEANED                             
---------------------------------------- ----------------------------------------
Test without breaks - §1  Test without breaks - §1                

并且它可能会做出与您的其他 hard-coded 替换不同的其他更改。另一方面,在某些时候,您的 col_original 可能已经通过类似的函数传递给 escape 对您当前存储的值的引用;由于真正的原始文本本来 § 已经被转义为 §,无论如何将其恢复为原始字符可能更合适。除非您最终遇到无法显示它的字符集,否则也许。