Error : ORA-01704: string literal too long. Dynamically assign CLOB to variable
Error : ORA-01704: string literal too long. Dynamically assign CLOB to variable
我的问题很重要。
我应该执行运行 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
查询之前重新分配变量,我该怎么做?
您收到 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 或外部 table 来更简单地加载数据。或者您可以使用 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;
/
... 这将是性能和(可能)可读性与集合内存使用之间的权衡。如果您的情况可行,您可以将其填充到块中,或者再次从文件中将值读入集合。
您仍然可以通过对现有 table 的查询生成此信息,例如:
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 以防您的任何字符串值包含单引号,但您需要选择一个 suitable 引号分隔符。再次假设您的 CLOB 值的 none 超过 32k。
如果你真的想用一个充满插入语句的脚本来做这件事,我也会重新考虑;如果数据来自 table,那么 export/import 可能更合适。
您也可以在 PL/SQL 中声明一个 clob 变量。请参阅 lob semantics and the 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;
我对此的解决有点奇怪,但它有效。
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多
我的问题很重要。
我应该执行运行 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
查询之前重新分配变量,我该怎么做?
您收到 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 或外部 table 来更简单地加载数据。或者您可以使用 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;
/
... 这将是性能和(可能)可读性与集合内存使用之间的权衡。如果您的情况可行,您可以将其填充到块中,或者再次从文件中将值读入集合。
您仍然可以通过对现有 table 的查询生成此信息,例如:
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 以防您的任何字符串值包含单引号,但您需要选择一个 suitable 引号分隔符。再次假设您的 CLOB 值的 none 超过 32k。
如果你真的想用一个充满插入语句的脚本来做这件事,我也会重新考虑;如果数据来自 table,那么 export/import 可能更合适。
您也可以在 PL/SQL 中声明一个 clob 变量。请参阅 lob semantics and the 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;
我对此的解决有点奇怪,但它有效。
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多