ORA-01461 (with > 4k varchar2) 错误仅在合并语句中。插入或更新工作正常

ORA-01461 (with > 4k varchar2) error Only in merge statement. Insert or update works fine

这是我的线索... 我在 oracle 11g 上。找了很多,都没找到。

我需要执行 DML 操作,它可以包含大于 4k 个字符的数据。

如果我直接在 oracle 中使用 sql 块,就像下一个一样,一切正常

declare 
  txtV varchar2(32000);
BEGIN 
  txtV:= 'MORE THAN 4k CHARS, here only few for readability' ; 
  Update FD_FILTERDEF 
     set SQLFILTER = txtV 
   where id='blabla';  
END;

但是!!! 如果我使用合并语句,它会给我错误 ORA-01461

declare 
  txtV varchar2(32000);
BEGIN 
  txtV:= '' ; 
  MERGE INTO FD_FILTERDEF A 
        USING ( select  txtV C0 
                  from dual) ST 
           ON (A.CODE = 'bla bla') 
  WHEN MATCHED THEN 
    Update set A.SQLFILTER = st.C0  
  WHEN NOT MATCHED THEN 
    insert (CODE  ,SQLFILTER ) 
      values ('bla bla'  , ST.C0  );  
END; 

如有提示将不胜感激:)

使用这个:

create table fd_filterdef
( code varchar2(10) primary key
, sqlfilter clob );

declare
    txtv varchar2(32000);
begin
    txtv := rpad('select statement, really really long', 5000, ' etc');

    merge into fd_filterdef a
    using (select 'bla bla' as code from dual) st
    on (a.code = st.code)
    when matched then
        update set a.sqlfilter = txtv
    when not matched then
        insert (code, sqlfilter)
        values (st.code,txtv);
end;
/

select code, length(sqlfilter) from fd_filterdef;

CODE       LENGTH(SQLFILTER)
---------- -----------------
bla bla                 5000

从 dual 中选择 long 变量会隐式地将其转换为 SQL varchar2,在 12c 之前它最多只能容纳 4000 个字节。

你不能 select varchar2 超过 4k https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits001.htm

查看您的代码

 select  txtV C0 from dual

但是在 oracle 12c 中你可以 https://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF30020

@William 很好的提示,你发布的作品。

但我很确定我已经测试了一个非常相似的语法,其中唯一的区别在于 select 语句, 您提供的那个工作正常...以下一个会引发错误:

declare 
  txtV varchar2(32000);
BEGIN 
  txtV:= '5000 chars ....';
  MERGE INTO FD_FILTERDEF A 
        USING ( select  'not used' Code from dual) ST 
           ON (A.CODE = 'TESTCODE') 
  WHEN MATCHED THEN 
    Update set A.SQLFILTER = txtV   --<<<< LOOK HERE I USE DIRECTLY THE VARIABLE DELCARED, NOT THE ONE FROM SELECT STMT 
  WHEN NOT MATCHED THEN 
    insert (CODE  ,SQLFILTER ) 
      values (st.code  , txtV  );  
END;

@William ... 好吧,也许我在写脚本时有点混乱。我对 "pk error" 感到惊讶,因为在我看来我已经按如下方式完成了脚本。我打算完全不使用 "select" 语句,只是在插入和更新中传递代码(如下所示),因为我以编程方式构建查询并用占位符替换值.... 这样就完全没有pk错误了。在你的例子中,当然,因为在插入中使用了查询中的代码,但在更新中使用了值 "TESTCODE" ...所以它正在搜索(和更新)代码,但插入另一个:P 对不起我的错误:)

declare 
  txtV varchar2(32000);
BEGIN 
  txtV:= '5000 chars ....';
  MERGE INTO FD_FILTERDEF A 
        USING ( select  'not used' Code from dual) ST 
           ON (A.CODE = 'TESTCODE') 
  WHEN MATCHED THEN 
    Update set A.SQLFILTER = txtV   --<<<< LOOK HERE I USE DIRECTLY THE VARIABLE DELCARED, NOT THE ONE FROM SELECT STMT 
  WHEN NOT MATCHED THEN 
    insert (CODE  ,SQLFILTER ) 
      values ('TESTCODE'  , txtV  );  
END;