【发布时间】:2017-08-22 15:36:26
【问题描述】:
我有一个 NoteDetail 表,其中 NoteText 的 varchar(4000) 字段和 NoteNumber 的 number(4,0) 字段。这个想法是,如果一个超过 4000 个字符的音符出现,它会被分成多个音符,并带有递增的 NoteNumber 条目。
执行插入的逻辑如下,它在 Oracle 10 上运行良好。最近该应用程序已移至 Oracle 12c,我收到错误消息:“ORA-01461: can bind a LONG value only for insert into a LONG column" Oracle DBA 无法弄清楚为什么会发生这种情况。
以下是我的插入代码的本质;我最好的猜测是,如果传入的字符串足够长,那么即使我分配给 varchar2(4000) 类型的变量,SUBSTR() 函数也会返回一个 long。供参考:Oracle SQL Developer 指出错误发生在插入点(在下面 else 块的循环中)。
有谁知道如何解决这个问题?
DECLARE
s_incoming_string varchar2(32000);
s_substring_value varchar2(4000);
i_note_iteration number(4,0);
i_note_iterations number(4,0);
i_substr_start number(6,0);
k_NoteId number(19,0);
BEGIN
SELECT noteid_seq.nextval INTO k_NoteId FROM dual;
s_incoming_string := {a 7000 character long note};
i_note_iterations := ceil(length(s_incoming_string)/4000);
IF i_note_iteration = i_note_iterations THEN
--I NEVER GET AN ERROR ON THIS BRANCH!!!
INSERT INTO NoteDetail (NoteId, NoteNumber, NoteText)
VALUES (k_NoteId, 1, s_incoming_string);
ELSE
FOR i_note_iteration IN 1..i_note_iterations
LOOP
i_substr_start := (4000 * (i_note_iteration - 1)) + 1;
IF i_note_iteration = i_note_iterations THEN
--this is the last chunk of text; no need
--to read past the end of the buffer
s_substring_value = SUBSTR(s_incoming_string, i_substr_start);
ELSE
--I ONLY GET AN ERROR if this branch is executed before the insert:
s_substring_value = SUBSTR(s_incoming_string, 4000);
END IF;
INSERT INTO NoteDetail (NoteId, NoteNumber, NoteText)
VALUES (k_NoteId, i_note_iteration, s_incoming_string);
END LOOP;
END IF;
END;
表架构是:
DCLARE TABLE NoteDetail (
NoteId number(19,0),
NoteNumber number(4,0),
NoteText varchar2(4000)
);
【问题讨论】:
-
请包含重现问题所需的最短代码。还请在表格中附加一个结构。目前只有你的 cmets 而不是真正的代码和
insert语句。 -
我添加了架构和更多代码。
-
对于投票结束这个的人,你能至少解释一下原因吗?我现在才在我的职业生涯中第一次遇到 Oracle,我必须让这些样本如此通用,这样我才不会因为泄露公司信息而被解雇。请让我在这里休息一下。
-
你这样做的方式看起来有点工匠精神(即:在 CLOB 发明之前,有点像 1980 年代):为什么不改用 CLOB?
-
如果您的文本列最大为 4000 字节,请尝试使用 SUBSTRB 和 LENGTHB 函数。也必须小心把它拼回来
标签: oracle type-conversion oracle12c