运行 背靠背时 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 对您当前存储的值的引用;由于真正的原始文本本来 §
已经被转义为 §
,无论如何将其恢复为原始字符可能更合适。除非您最终遇到无法显示它的字符集,否则也许。
我们运行正在使用较旧的 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 对您当前存储的值的引用;由于真正的原始文本本来 §
已经被转义为 §
,无论如何将其恢复为原始字符可能更合适。除非您最终遇到无法显示它的字符集,否则也许。