ORA-01461: может связывать длинное значение только для вставки в длинный столбец-происходит при запросе

когда я пытаюсь запросить объекты, я получаю следующую ошибку:

ORA-01461: can bind a LONG value only for insert into a LONG column

может ли кто-нибудь помочь мне в причине и решении проблемы?

14 ответов


хорошо, ну, так как вы не показали никакого кода, я сделаю несколько предположений здесь.

основываясь на ошибке ORA-1461, кажется, что вы указали длинный тип данных в инструкции select? И вы пытаетесь привязать его к выходной переменной? Это правда? Ошибка довольно прямолинейна. Вы можете привязать только длинное значение для insert в длинный столбец.

Не знаю, что еще сказать. Ошибки понятно.

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

здесь список длинных ограничений типа данных

надеюсь, это поможет.


Это также может произойти с varchar2 столбцов. Это довольно воспроизводимо с PreparedStatements через JDBC просто

  1. создание таблицы со столбцом varchar2 (20 или любой произвольной длины) и
  2. вставка в приведенную выше таблицу со строкой, содержащей более 20 символов

Так как выше сказано, это может быть неправильно с типами или превышена ширина столбца.

также обратите внимание, что, поскольку varchar2 позволяет 4K chars max, реальный предел будет 2k для двухбайтовых символов

надеюсь, что это помогает


эта ошибка возникает при попытке использовать переменную varchar длиной более 4000 байт в инструкции SQL. PL/SQL позволяет varchars до 32767 байт, но ограничение для таблиц базы данных и языка SQL составляет 4000. Вы не можете использовать переменные PL/SQL, которые SQL не распознает в операторах SQL; исключение, как объясняется в сообщении, является прямой вставкой в столбец длинного типа.

create table test (v varchar2(10), c clob);


declare
  shortStr varchar2(10) := '0123456789';
  longStr1 varchar2(10000) := shortStr;
  longStr2 varchar2(10000);
begin
  for i in 1 .. 10000
  loop
    longStr2 := longStr2 || 'X';
  end loop;

  -- The following results in ORA-01461
  insert into test(v, c) values(longStr2, longStr2);

  -- This is OK; the actual length matters, not the declared one
  insert into test(v, c) values(longStr1, longStr1);

  -- This works, too (a direct insert into a clob column)
  insert into test(v, c) values(shortStr, longStr2);

  -- ORA-01461 again: You can't use longStr2 in an SQL function!
  insert into test(v, c) values(shortStr, substr(longStr2, 1, 4000));
end;

коллега меня и узнал следующее:

когда мы используем драйвер Microsoft .NET Oracle для подключения к базе данных oracle (система.Данные.OracleClient.Объекта oracleconnection)

и мы пытаемся вставить строку длиной от 2000 до 4000 символов в поле CLOB или NCLOB, используя параметр базы данных

oraCommand.CommandText = "INSERT INTO MY_TABLE (NCLOB_COLUMN) VALUES (:PARAMETER1)";
// Add string-parameters with different lengths
// oraCommand.Parameters.Add("PARAMETER1", new string(' ', 1900)); // ok
oraCommand.Parameters.Add("PARAMETER1", new string(' ', 2500));  // Exception
//oraCommand.Parameters.Add("PARAMETER1", new string(' ', 4100)); // ok
oraCommand.ExecuteNonQuery();
  • любая строка длиной менее 2000 символов не будет выбрасывать это исключение
  • любая строка с длина более 4000 символов не будет выбрасывать это исключение
  • только строки длиной от 2000 до 4000 символов будут выбрасывать это исключение

мы открыли билет в microsoft для этой ошибки много лет назад, но она до сих пор не была исправлена.


я столкнулся с той же проблемой и решил ее, просто заменив VARCHAR с CLOB. Это ссылке помог мне.


приложения, использующие JDBC 10.1, имеют ошибку (DOC ID 370438.1) и могут создавать то же исключение ORA-01461 при работе с базой данных набора символов UTF8, даже если вставленные символы меньше максимального размера столбца.

рекомендуемое решение: - в таком случае используйте драйверы 10gR2 JDBC или выше.

HTH


Киранответ определенно является ответом для моего случая.

в части кода я разделяю строку на 4000 строк символов и пытаюсь поместить их в db.

взрывается с этой ошибкой.

причиной ошибки является использование символов utf, каждый из которых насчитывает 2 байта. Даже я усекаю до 4000 символов в коде(sth. как струна.Возьмите (4000)), oracle считает 4001, когда строка содержит "ö" или любой другой не-eng(не ascii, чтобы быть точным, которые представлены двумя или байты в символах utf8).


У меня была такая же проблема с базой данных Entity Framework сначала на всех столбцах CLOB.

в качестве обходного пути я заполнил текстовые значения пробелами шириной не менее 4000 в операциях вставки (не было лучшего решения).


в моем конкретном случае я пытался сохранить файл с кодировкой Base64 в поле BLOB таблицы, используя Mybatis.

поэтому в моем xml у меня было:

<insert id="save..." parameterType="...DTO">
    <selectKey keyProperty="id" resultType="long" order="BEFORE">
        SELECT SEQ.nextVal FROM DUAL
    </selectKey>
    insert into MYTABLE(
        ID,
        ...,
        PDF
    ) values (
        #{id, jdbcType=VARCHAR},
        ...,
        #{tcPdf, jdbcType=BLOB},
    )
</insert>

и в моем DTO:

String getPdf(){
    return pdf;
}

это делает MyBatis угрозой, как если бы была последовательность символов строки и попытайтесь сохранить ее как Varchar. Поэтому мое решение было следующим:

в моем DTO:

Byte[] getPdf(){
    return pdf.getBytes();
}

и работал.

Я надеюсь, что это может помочь кому-то.


я столкнулся с той же проблемой, используя Siebel REXPIMP (импорт реестра) при использовании последнего драйвера Instant Client. Чтобы устранить проблемы, используйте драйвер Siebel, предоставленный Data Direct. DLL является SEOR823.DLL


добавление другого варианта использования, где я нашел это происходит. Я использовал приложение ADF Fusion, и используемый тип столбца был varchar2 (4000), который не мог вместить текст и, следовательно, эту ошибку.


я обнаружил это сообщение об ошибке при попытке вставить строку в столбец XMLTYPE.

в частности, используя PreparedStatement Java, как это:

ps.setString('XML', document);

здесь XML здесь определяется как XMLTYPE.


у меня есть решение для Java/JPA/eclipselink / oracle при вставке длинной строки xml (>4000) в столбец XMLTYPE в вставьте XML с более чем 4000 символов в столбец Oracle XMLTYPE. Для ясности включите то же самое содержимое здесь, Если ссылка не работает

сначала вам нужно преобразовать строку xml для более чем 4000 charcaters в тип SQLXML.

окружающая среда: jpa 2.1.0, eclipselink 2.5.2, oracle db 11gr2

SQL:

CREATE TABLE "XMLTEST"
( "ID" NUMBER(10,0) NOT NULL ENABLE, 
  "DESCRIPTION" VARCHAR2(50 CHAR) NOT NULL ENABLE, 
  "XML_TXT" "XMLTYPE" NOT NULL ENABLE
);

INSERT INTO XMLTEST (ID, DESCRIPTION, XML_TXT) VALUES (101, 'XML DATA', '<data>TEST</data>');
COMMIT;

DROP TABLE "XMLTEST";

Java-Код

String sql = "INSERT INTO XMLTEST (ID, DESCRIPTION, XML_TXT) VALUES (?, ?, ?)";
String xmlDataStr = "<data>test...</data>"; // a long xml string with length > 4000 characters
Connection con = getEntityManager().unwrap(Connection.class);
SQLXML sqlXml = con.createSQLXML();
sqlXml.setString(xmlDataStr);

код Java-используйте PreparedStatement

PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setLong(1, 201);
pstmt.setLong(2, "Long XML Data");
pstmt.setSQLXML(3, sqlXml);
pstmt.execute();

Java code-используйте собственный запрос вместо PreparedStatement

Query query = getEntityManager().createNativeQuery(sql);
query.setParameter(1, 301);
query.setParameter(2, "Long XML Data");
query.setParameter(3, sqlXml);
query.executeUpdate();

У меня была такая же проблема с использованием PHP и подготовленных операторов в столбце VARCHAR2. Моя строка не exceeed размер VARCHAR2. Проблема в том, что я использовал -1, как maxlength, для привязки, но содержимое переменной изменено позже.

пример:

$sMyVariable = '';
$rParsedQuery = oci_parse($rLink, 'INSERT INTO MyTable (MyVarChar2Column) VALUES (:MYPLACEHOLDER)');
oci_bind_by_name($rParsedQuery, ':MYPLACEHOLDER', $sMyVariable, -1, SQLT_CHR);

$sMyVariable = 'a';
oci_execute($rParsedQuery, OCI_DEFAULT);
$sMyVariable = 'b';
oci_execute($rParsedQuery, OCI_DEFAULT);

если заменить -1 на максимальную ширину столбца (i. e. 254) тогда этот код работает. С -1 oci_bind_by_param использует текущую длину содержимого переменной (в моем случае 0) в качестве максимальной длины для этого столбца. Этот результаты в ORA-01461 при выполнении.