我的问题非常重要。
我应该执行运行INSERT INTO
查询的PL / SQL脚本。它看起来像:
DECLARE
newId NUMBER(38,0) := &1;
BEGIN
Insert into FOO ("ID", "DESCRIPTION")
values (newId+1, 'LARGE CLOB WHICH PRODUCES EXCEPTION');
-- A LOT OF INSERT QUERIES
END;
/
exit;
所以,我发现将CLOB分配给VARCHAR2变量是一个好主意,因为它可能是32767字节长。我的目标是为每个INSERT INTO
查询执行此操作。像:
--assign CLOB to VARCHAR2 variable
-- INSERT variable instead of CLOB type
我想指出我在脚本中有很多INSERT INTO
个查询,所以我应该在每个INSERT INTO
查询之前重新分配变量,我该怎么做?
答案 0 :(得分:4)
您正在获取ORA-01704,因为您的字符串文字超过4000个字节,这是SQL调用中字符串文字的大小限制。在PL / SQL中,限制为32k,因此如果您的所有值都小于该值,则可以将它们分配给PL / SQL变量并将其用于插入:
DECLARE
newId NUMBER(38,0) := &1;
newDescription varchar2(32767); -- or clob
BEGIN
newDescription := 'LARGE CLOB WHICH PRODUCES EXCEPTION';
Insert into FOO ("ID", "DESCRIPTION")
values (newId+1, newDescription);
newDescription := 'ANOTHER LARGE CLOB WHICH PRODUCES EXCEPTION';
Insert into FOO ("ID", "DESCRIPTION")
values (newId+1, newDescription);
...
END;
/
如果任何值超过32k,您将需要一个PL / SQL CLOB变量,并且需要通过附加短路(< 32k)字符串文字来构造它,这很麻烦。
使用多个插入语句可能不是最好的方法。您可以使用SQL * Loader或外部表来更简单地加载数据。或者您可以使用utl_file
读取值,例如进入相同的PL / SQL变量,然后插入一个循环 - 这将是更少的代码,更容易维护。
您还可以使用集合来保存字符串值:
DECLARE
TYPE stringTab IS table of varchar2(32767); -- or clob
newDescriptions stringTab := new stringTab();
BEGIN
newDescriptions.extend;
newDescriptions(newDescriptions.last) := 'LARGE CLOB WHICH PRODUCES EXCEPTION';
newDescriptions.extend;
newDescriptions(newDescriptions.last) := 'ANOTHER LARGE CLOB WHICH PRODUCES EXCEPTION';
forall i in newDescriptions.first..newDescriptions.last
insert into FOO ("ID", "DESCRIPTION")
values (&1 + 1, newDescriptions(i));
END;
/
...这将是性能和(可能)可读性之间的权衡,与集合的内存使用相对应。你可以在块中填充它,或者再次从文件中读取值到集合中,如果这对你的情况是可行的。
您仍然可以通过针对现有表的查询生成此内容,例如:
set pages 0
set lines 32767
set long 32767
set define off
select 'DECLARE' || chr(10)
|| ' newId NUMBER(38,0) := &1;' || chr(10)
|| ' newDescription varchar2(32767);' || chr(10)
|| 'BEGIN'
from dual;
select ' newDescription := q''[' || description || ']'';' || chr(10)
|| ' newId := newId + 1;' || chr(10)
|| ' insert into FOO ("ID", "DESCRIPTION") values (newId, newDescription);' || chr(10)
from foo;
select 'END;' || chr(10)
|| '/' || chr(10)
|| 'exit'
from dual;
set define on
如果您的任何字符串值包含单引号,我使用了the alternative quoting mechanism,但您需要选择合适的引号分隔符。再次假设您的CLOB值都不超过32k。
如果你真的想用一个充满插入语句的脚本来做这件事,我也会重新考虑;如果数据来自表格,那么导出/导入可能更合适。
答案 1 :(得分:0)
您还可以在PL / SQL中声明clob变量。请参阅lob semantics和DBMS_LOB包来操纵它。它可以是:
DECLARE
myLOBFromDatabase CLOB;
BEGIN
SELECT lobComun INTO myLOBFromDatabase FROM table WHERE id=1;
/* Manipulate lob wth dbms_lob package at will here */
Insert into FOO ("ID", "DESCRIPTION")
values (newId+1, myLOBFromDatabase );
END;
答案 2 :(得分:0)
对此我有一个奇怪的解决方法,但是它可以工作。
DECLARE
JS CLOB;
BEGIN
JS := TO_CLOB( 'THE FIRST PART OF CLOB SHOULD BE LESS THEN 32K
......
......'||
'.......
THIS IS SECOND PART IS LESS THEN 32K TOO'||
'.......
LAST PART');
END;
这种方式让我插入了超过1M