Ошибка при вставке данных столбца XMLTYPE в базу данных Oracle 11g размером более 4 КБ

I am trying to insert a XML request data into a table where the size of the XML message is more than 4KB and I am receiving the error: 'ORA-01461: can bind a LONG value only for insert into a LONG column'. I am receiving the XML request data as part of a transaction as a string data and due to the server used (webMethods Integration server 9.0) I have a limitation of converting the data into another format. I have tried the following methods:

  • вставить в значения тестовой таблицы (xmltype())
  • вставить в значения тестовой таблицы (xmltype().getClobVal())
  • вставить в тестируемые значения (TO_CLOB())
  • Схема таблицы приведена ниже:

    desc testtable
    Name    Null     Type      
    ------- -------- --------- 
    XMLDATA NOT NULL XMLTYPE() 
    

    Вставка в таблицу также должна происходить в течение короткого времени, поскольку операция выполняется для каждого сообщения запроса, поступающего на сервер. Пожалуйста помоги.


    person Rohit Jose    schedule 27.09.2014    source источник
    comment
    Не знаком с веб-методами, но, похоже, проблема заключается в том, что он связывает ваши XML-данные в вашем выражении insert как (ужасный) тип данных long. Либо (а) попытаться заставить его связать значение как BLOB/CLOB и использовать конструктор xmltype(:yourBindVariable), либо (б) использовать временную таблицу со столбцом long, затем insert ... select из временной таблицы в вашу целевую таблицу, или (в) использовать анонимный блок PL/SQL (вместо чистого insert) для преобразования на стороне сервера long в xmltype. Не могу предположить, какой из них сработает, но хотя бы с чего начать.   -  person peter.hrasko.sk    schedule 29.09.2014
    comment
    Спасибо @nop77svk - я пробовал xmltype(:yourBindVariable), это не сработало. Я попробую ваши предложения (b) и (c), но, поскольку база данных не находится под моим контролем, я не смогу продолжить это. Я надеялся решить проблему в самом коде приложения.   -  person Rohit Jose    schedule 02.10.2014
    comment
    Если вы не можете возиться с базой данных, то может сработать анонимный подход PL/SQL. Я отправляю вам ответ с кодом, так как он требует форматирования кода.   -  person peter.hrasko.sk    schedule 02.10.2014


    Ответы (3)


    Этот "анонимный блок PL/SQL" может сработать, но я не уверен, так как у меня нет собственных веб-методов для его проверки...

    Вместо

    insert into testtable
    values (xmltype(:1))
    

    попробуй запустить

    declare
        l_long          long;
        l_string        varchar2(32767);
    begin
        l_long := :1;
        l_string := l_long;
        insert into testtable values (xmltype(l_string));
    end;
    

    Однако может возникнуть проблема с обработкой XML-документов, содержащих более 32767 (возможно, даже более 4000) символов.

    person peter.hrasko.sk    schedule 02.10.2014
    comment
    Я попытался запустить код непосредственно в SQL Developer для XML-данных размером 5,44 КБ. Я получаю аналогичную ошибку, как и раньше. - ORA-01461: can bind a LONG value only for insert into a LONG column ORA-06512: at line 7 01461. 00000 - "can bind a LONG value only for insert into a LONG column" - person Rohit Jose; 02.10.2014

    Я немного изменил приведенный выше код, и теперь он работает, но я не совсем уверен, почему:

    declare
        l_long          long;
        l_clob          clob;
    begin
        l_long := :1;
        l_clob := TO_CLOB(l_long);
        insert into testtable values (xmltype(l_clob));
        dbms_lob.freetemporary(l_clob);
    end;
    

    Это также работает для данных типа XML выше 4 КБ. @ nop77svk - спасибо за ваше руководство.

    person Rohit Jose    schedule 02.10.2014
    comment
    Приятно видеть, что это в конечном итоге сработало. Однако требуется небольшая очистка... Удалите объявление l_string и объявление l_xmltype+назначение. Вы дважды выполняете синтаксический анализ входных данных XML DOM ... что не соответствует эффективности производительности, о которой вы просили. - person peter.hrasko.sk; 02.10.2014
    comment
    И было бы неплохо поместить dbms_lob.freetemporary(l_clob); под оператором insert into testtable .... - person peter.hrasko.sk; 02.10.2014
    comment
    @ nop77svk - я отредактировал код, включив в него ваши предложения. Спасибо :) - person Rohit Jose; 02.10.2014

    По умолчанию все в wM определяется как строка. Но при использовании подключения адаптера вам необходимо проверить тип входа. Таким образом, для поля, которое было определено как Long в БД, вам нужно либо передать длинный объект из wM, либо вам нужно сделать тип ввода для поля как строку в службе адаптера. Также вам необходимо проверить размер, определенный в БД. Если вы подозреваете большой размер, вместо этого установите тип поля в БД как CLOB.

    person Adhiraj    schedule 01.11.2014