web-dev-qa-db-fra.com

ORA-01461: peut lier une valeur LONG uniquement pour l'insertion dans une colonne LONG-Se produit lors d'une requête

Lorsque j'essaie d'interroger des objets, l'erreur suivante est générée:

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

Quelqu'un pourrait-il m'aider s'il vous plaît sur la cause et la solution du problème?

53
Rupesh

Ok, bien, puisque vous n'avez montré aucun code, je vais faire quelques hypothèses ici.

D'après l'erreur ORA-1461, il semble que vous ayez spécifié un type de données LONG dans une instruction select? Et vous essayez de le lier à une variable de sortie? Est-ce correct? L'erreur est assez simple. Vous pouvez uniquement lier une valeur LONG pour une insertion dans une colonne LONG.

Je ne sais pas quoi dire d'autre. L'erreur est assez explicite.

En général, c'est une bonne idée de passer du type de données LONG à un CLOB. Les CLOB sont beaucoup mieux supportés, et les types de données LONG ne sont vraiment là que pour la compatibilité ascendante.

Voici une liste des restrictions de types de données LONG

J'espère que cela pourra aider.

14
Mark J. Bobak

Cela peut aussi arriver avec les colonnes varchar2. Ceci est assez reproductible avec PreparedStatements via JDBC simplement

  1. créer une table avec une colonne de varchar2 (20 ou une longueur quelconque) et
  2. insertion dans le tableau ci-dessus avec une ligne contenant plus de 20 caractères

Donc, comme indiqué ci-dessus, il peut être faux avec les types ou la largeur de colonne dépassée.

Notez également que varchar2 admettant 4 000 caractères maximum, la limite réelle sera de 2 000 caractères pour les caractères double octet.

J'espère que cela t'aides

162
Kiran

Cette erreur se produit lorsque l'on tente d'utiliser une variable varchar de plus de 4000 octets dans une instruction SQL. PL/SQL autorise varchars jusqu'à 32 767 octets, mais la limite pour les tables de base de données et le langage SQL est de 4000. Vous ne pouvez pas utiliser de variables PL/SQL que SQL ne reconnaît pas dans les instructions SQL. une exception, comme l'explique le message, est une insertion directe dans une colonne de type 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

Un collègue de moi et j'ai découvert ce qui suit:

Lorsque nous utilisons le pilote Microsoft .NET Oracle pour nous connecter à une base de données Oracle (System.Data.OracleClient.OracleConnection)

Et nous essayons d'insérer une chaîne d'une longueur comprise entre 2000 et 4000 caractères dans un champ CLOB ou NCLOB à l'aide d'un paramètre de base de données

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();
  • toute chaîne d'une longueur inférieure à 2000 caractères ne lève pas cette exception
  • toute chaîne d'une longueur de plus de 4000 caractères ne lève pas cette exception
  • seules les chaînes d'une longueur comprise entre 2 000 et 4 000 caractères généreront cette exception

Nous avons ouvert un ticket chez Microsoft pour ce bogue il y a de nombreuses années, mais il n'a toujours pas été corrigé.

7
Markus1980Wien

Je faisais face au même problème et le résolvons en remplaçant simplement VARCHAR par CLOB. Ce lien m'a aidé.

4
aneela

Les applications utilisant JDBC 10.1 ont un bogue (ID de document 370438.1) et peuvent générer la même exception ORA-01461 tout en utilisant la base de données de jeux de caractères UTF8, même si les caractères insérés sont inférieurs à la taille maximale de la colonne.

Solution recommandée: - Utilisez les pilotes JDBC 10gR2 ou supérieurs dans ce cas.

HTH

3
pahariayogi

Cette ORA-01461 ne se produit pas uniquement lors de l'insertion dans une colonne longue. Cette erreur peut se produire lors de la liaison d'une chaîne longue pour insertion dans une colonne VARCHAR2 et survient généralement lorsqu'il existe un problème de conversion de caractères multi octets (signifie qu'un seul caractère peut prendre plusieurs octets dans Oracle).

Si la base de données est UTF-8, étant donné que chaque caractère peut prendre jusqu'à 3 octets, la conversion de 3 appliquée à la vérification et donc limitée à l'utilisation de 1333 caractères à insérer dans varchar2 (4000).

Une autre solution serait de changer le type de données de varchar2 (4000) à CLOB. 

2
Murali

La réponse de Kiran est définitivement la solution pour mon cas.

Dans la partie de code, je divise une chaîne en 4000 chaînes de caractères et essaie de les placer dans la base de données.

Explose avec cette erreur.

La cause de l'erreur est l'utilisation de caractères utf, ceux-ci comptent chacun 2 octets. Même si je tronque à 4000 caractères dans le code (sth. Comme String.Take (4000)), Oracle considère 4001 lorsque la chaîne contient 'ö' ou tout autre non-eng (non ascii pour être précis, qui sont représentés avec deux ou octets dans utf8) caractères.

2
mkb

Dans mon cas particulier, j'essayais de stocker un fichier encodé en Base64 dans un champ BLOB de table, en utilisant Mybatis.

Donc, dans mon xml j'avais:

<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>

et dans mon DTO:

String getPdf(){
    return pdf;
}

Cela constitue pour Mybatis une menace comme s'il s'agissait d'une séquence de caractères de chaîne et que vous essayez de la stocker en tant que Varchar. Donc ma solution était la suivante:

Dans mon DTO:

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

Et travaillé.

J'espère que cela pourrait aider n'importe qui.

1
Francisco M

J'ai eu le même problème avec la base de données Entity Framework d'abord sur toutes les colonnes CLOB. 

En guise de solution de contournement, j'ai rempli les valeurs de texte avec des espaces d'au moins 4000 en largeur dans les opérations d'insertion (sans solution meilleure).

1
Martin Staufcik

J'ai eu le même problème en utilisant PHP et en préparant des instructions sur une colonne VARCHAR2 . Ma chaîne n'a pas dépassé la taille de VARCHAR2. Le problème était que j'ai utilisé -1 comme longueur maximale pour la liaison, mais le contenu variable a changé plus tard.

Par exemple:

$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);

Si vous remplacez -1 par la largeur de colonne maximale (c'est-à-dire 254), ce code fonctionnera alors . Avec -1, oci_bind_by_param utilise la longueur actuelle du contenu de la variable (dans mon cas 0) comme longueur maximale pour cette colonne. Cela se traduit par ORA-01461 lors de l'exécution.

0
David Gausmann

Ajout d'un autre cas d'utilisation où j'ai trouvé cela se produisant. J'utilisais une application ADF Fusion et le type de colonne utilisé était un varchar2 (4000) qui ne pouvait pas accueillir le texte et par conséquent cette erreur.

0
Vik

J'ai rencontré ce message d'erreur en essayant d'insérer String dans une colonne XMLTYPE.

Utilisant spécifiquement le PreparedStatement de Java comme ceci:

ps.setString('XML', document);

XML est défini ici comme XMLTYPE.

0
doughgle

J'ai une solution pour Java/JPA/eclipselink/Oracle lorsque vous insérez une longue chaîne xml (> 4000) dans une colonne XMLTYPE en Insérez du XML de plus de 4000 caractères dans une colonne Oracle XMLTYPE . Pour plus de clarté, incluez le même contenu ici au cas où le lien ne fonctionnerait pas

Vous devez d’abord convertir la chaîne XML de plus de 4000 charcaters en type SQLXML.

Environnement: 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";

Code 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);

Code Java - utilisez PreparedStatement

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

Code Java - utilisez une requête native au lieu de 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

J'ai rencontré le même problème lors de l'utilisation de Siebel REXPIMP (importation de registre) lors de l'utilisation du dernier pilote Instant Client. Pour résoudre les problèmes, utilisez plutôt le pilote Data Direct fourni par Siebel. Le DLL est SEOR823.DLL

0
Rick Bahrenburg