Ich habe Java-Code, der eine UTF-8-Zeichenfolge auf die Größe meiner Oracle-Spalte (11.2.0.4.0) zuschneidet, was zu einem Fehler führt, da Java und Oracle die Zeichenfolge als unterschiedliche Bytelängen betrachten. Ich habe überprüft NLS_CHARACTERSET
, ob mein Parameter in Oracle 'UTF8' ist.
Ich habe einen Test geschrieben, der mein Problem unten mit dem Unicode-Chipmunk-Emoji (🐿️) veranschaulicht.
public void test() throws UnsupportedEncodingException, SQLException {
String squirrel = "\uD83D\uDC3F\uFE0F";
int squirrelByteLength = squirrel.getBytes("UTF-8").length; //this is 7
Connection connection = dataSource.getConnection();
connection.prepareStatement("drop table temp").execute();
connection.prepareStatement("create table temp (foo varchar2(" + String.valueOf(squirrelByteLength) + "))").execute();
PreparedStatement statement = connection.prepareStatement("insert into temp (foo) values (?)");
statement.setString(1, squirrel);
statement.executeUpdate();
}
Dies schlägt in der letzten Zeile des Tests mit der folgenden Meldung fehl:
ORA-12899: Wert zu groß für Spalte
"MYSCHEMA". "TEMP". "FOO" (aktuell: 9, maximal: 7)
Die Einstellung von NLS_LENGTH_SEMANTICS
ist BYTE
. Leider kann ich dies nicht ändern, da es sich um ein Legacy-System handelt. Ich bin nicht daran interessiert, die Spaltengröße zu erhöhen, sondern nur die Oracle-Größe einer Zeichenfolge zuverlässig vorhersagen zu können.
Antworten:
Was folgt, ist meine Spekulation.
Java
String
s werden intern mit der UTF-16-Codierung dargestellt . Wenn SiegetBytes("UTF-8")
Java zwischen den beiden Codierungen konvertieren und wahrscheinlich eine aktuelle Java-Plattform verwenden.Wenn Sie versuchen, ein Java
String
in der Datenbank zu speichern , führt Oracle auch eine Konvertierung zwischen dem nativen Java-UTF-16 und dem Datenbankzeichensatz durch, wie durch bestimmtNLS_CHARACTERSET
.Der Chipmunk-Charakter wurde 2014 als Teil des Unicode-Standards genehmigt (gemäß der von Ihnen verlinkten Seite), während die neueste Version von Oracle 11g rel.2 2013 veröffentlicht wurde .
Man könnte annehmen, dass Oracle einen anderen oder veralteten Zeichenkonvertierungsalgorithmus verwendet, sodass die Bytedarstellung von 🐿️) auf dem Server (9 Byte lang) anders ist als
getBytes()
die auf dem Client zurückgegebene (7 Byte).Um dieses Problem zu beheben, können Sie Ihren Oracle-Server aktualisieren oder UTF-16 als Datenbankzeichensatz verwenden.
quelle
Das Problem liegt in der Behandlung von zusätzlichen Unicode-Zeichen durch Oracle, wenn dies der Fall
NLS_LENGTH_SEMANTICS
istUTF8
.Aus der Dokumentation (Hervorhebung hinzugefügt).
Darüber hinaus ist der letzte Codepunkt in der Eichhörnchenzeichenfolge ein Variationsselektor und optional. Ich habe dies mit einem Unicode-Zeicheninspektor gesehen
Nach dem Ändern des Datenbankparameters
NLS_CHARACTERSET
inAL32UTF8
den Test bestanden.quelle