web-dev-qa-db-ja.com

ORA-01461:LONG値は、LONG列への挿入のみにバインドできます-問合せ時に発生します

オブジェクトを照会しようとすると、次のエラーが発生します。

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

誰かが問題の原因と解決策について私を助けてくれますか?

63
Rupesh

わかりました、まあ、あなたはコードを表示しなかったので、ここでいくつかの仮定をします。

ORA-1461エラーに基づいて、select文でLONGデータ型を指定したようです?そして、それを出力変数にバインドしようとしていますか?そうですか?エラーは非常に単純です。 LONG列に挿入するためのLONG値のみをバインドできます。

他に何を言うべきかわからない。エラーはかなり自明です。

一般に、LONGデータ型からCLOBに移行することをお勧めします。 CLOBははるかによくサポートされており、LONGデータ型は実際には下位互換性のためにのみ存在します。

LONGデータ型制限のリスト

お役に立てば幸いです。

15
Mark J. Bobak

Varchar2列でも発生する可能性があります。これは、JDBCを介してPreparedStatementsを使用するだけでかなり再現可能です。

  1. varchar2(20または任意の長さ)の列を持つテーブルを作成し、
  2. 20文字を超える行を含む上記のテーブルに挿入する

したがって、上記のように、タイプに誤りがあるか、列幅を超えている可能性があります。

また、varchar2は最大4k文字を許可しているため、実際の制限は2バイト文字の2kになります。

お役に立てれば

176
Kiran

このエラーは、SQLステートメントで4000バイトを超えるvarchar変数を使用しようとすると発生します。 PL/SQLでは最大32767バイトのvarcharを使用できますが、データベーステーブルとSQL言語の制限は4000です。SQLがSQLステートメントで認識しないPL/SQL変数は使用できません。メッセージが説明しているように、例外はlong型の列への直接挿入です。

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;
32
Tomasz Żuk

私と同僚の次のことがわかりました。

Microsoft .NET Oracleドライバーを使用してOracleデータベース(System.Data.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文字の長さの文字列のみがこの例外をスローします

何年も前にマイクロソフトでこのバグのチケットをオープンしましたが、まだ修正されていません。

7
Markus1980Wien

このORA-01461は、長い列への挿入中にのみ発生しません。このエラーは、挿入用の長い文字列をVARCHAR2列にバインドするときに発生する可能性があります。最も一般的なのは、マルチバイト(Oracleで単一の文字が複数のバイトスペースを取ることができる)文字変換の問題がある場合です。

データベースがUTF-8の場合、各文字は最大3バイトを使用できるため、3の変換がチェックに適用され、実際には1333文字を使用してvarchar2(4000)に挿入するように制限されます。

別の解決策は、データ型をvarchar2(4000)からCLOBに変更することです。

5
Murali

私は同じ問題に直面していたので、VARCHARCLOBに置き換えるだけで解決しました。これは link に役立ちました。

4
aneela

JDBC 10.1を使用するアプリケーションにはバグ(Doc ID 370438.1)があり、UTF8文字セットデータベースの操作中に、挿入された文字が列の最大サイズより小さくても、同じORA-01461例外をスローできます。

推奨される解決策:-このような場合は10gR2 JDBCドライバー以上を使用してください。

HTH

3
pahariayogi

Kiran の答えは、私の場合の答えです。

コード部分では、文字列を4000文字の文字列に分割し、それらをdbに入れようとします。

このエラーで爆発します。

エラーの原因はutf文字を使用していることです。これらはそれぞれ2バイトをカウントします。コードで4000文字に切り捨てても(文字列。 utf8)文字。

2
mkb

私の特定のケースでは、Mybatisを使用して、Base64でエンコードされたファイルをテーブルのBLOBフィールドに保存しようとしました。

だから私の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();
}

そして働いた。

これが誰にも役立つことを願っています。

1
Francisco M

最初にすべてのCLOB列でEntity Frameworkデータベースに同じ問題がありました。

回避策として、挿入操作で少なくとも4000の幅になるようにテキスト値をスペースで埋めました(これ以上の解決策はありませんでした)。

1
Martin Staufcik

PHPとVARCHAR2列の準備されたステートメントを使用して同じ問題が発生しました。私の文字列はVARCHAR2サイズを超えていません。問題は、バインディングのmaxlengthとして-1を使用したことですが、変数の内容は後で変更されました。

例:

$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を最大列幅(つまり254)に置き換えると、このコードは機能します。 -1の場合、oci_bind_by_paramは、変数コンテンツの現在の長さ(この場合は0)をこの列の最大長として使用します。これにより、実行時にORA-01461が生成されます。

0
David Gausmann

これが起こっていることがわかった別のユースケースを追加します。私はADF Fusionアプリケーションを使用しており、使用されている列タイプはvarchar2(4000)であり、テキストを収容できなかったため、このエラーが発生しました。

0
Vik

XMLTYPE列に文字列を挿入しようとしたときに、このエラーメッセージが表示されました。

具体的には、次のようにJavaのPreparedStatementを使用します。

ps.setString('XML', document);

ここで、XMLはXMLTYPEとして定義されています。

0
doughgle

Oracle XMLTYPE列に4000文字を超えるXMLを挿入 でXMLTYPE列に長いxml文字列(> 4000)を挿入すると、Java/JPA/eclipselink/Oracleのソリューションがあります。明確にするために、リンクが機能しない場合に備えて同じ内容をここに含めてください

4000文字以上のXML文字列を最初に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コード-PreparedStatementの代わりにネイティブクエリを使用する

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

最新のインスタントクライアントドライバーを使用しているときに、Siebel REXPIMP(レジストリインポート)を使用しても同じ問題が発生しました。問題を解決するには、代わりにSiebelが提供するData Directドライバーを使用します。 DLLはSEOR823.DLLです

0
Rick Bahrenburg