Software > Datenbanken
Oracle: "string literal too long" trotz Check
(1/1)
claus:
Falls es jemanden wie mir gehen sollte, hier eine kleine Hilfe:
Man überprüft z.B. mit Perl, ob ein geänderter Wert eines Datenbanken-Felds über die dafür vorgesehene Maximalgrösse kommen würde (z.B. varchar2(4000):
--- Code: ---my $length = length($new_value);
if ($length < 4000)
{
&update_component_table($new_value, $id);
}
else
{
print "[ERROR] component $id value would be too long!\n";
}
--- Ende Code ---
Perl gibt zurück, dass alles innerhalb der Toleranzen ist (also kleiner als 4000 Zeichen), aber Oracle meldet sich dann mit der "ORA-01704" Fehlermeldung (String Literal too long), dann hat das normalerweise den Grund, dass Oracle als NLS_LENGTH_SEMANTICS(*) eben Byte hat und nicht Chars, was der einfache Perl Code lediglich abprüft.
Um das zu vermeiden, muss man folgendes hinzufügen:
(... my $length = length($new_value);... )
foreach (split (//, $new_value))
{
$length++ if (ord($_) > 127);
}
(...if ($length < 4000)...)
Damit wird man, wie ich (wir) heute feststellen, dass die Länge des Strings eben doch grösser als 4000 Bytes (und eben weniger als 4000 Zeichen) ist.
(*) = Diese Attribute findet man über:
--- Code: ---select * from v$nls_parameters
--- Ende Code ---
Im "Oracle Programming Book" steht dazu übrigens nur "Contact your Database Administrator" anstelle, dass eben dieser einzeilige SQL-Befehl angegeben wird... Mann oh Mann.
Vielleicht hilft es jemanden, hat mich heute eine gute Stunde oder so beschäftigt
Claus
sunfreak:
Jou,
da bin ich auch schon mal reingerasselt. Je nach Zeichesatz braucht Oracle 3 byte um einen Chaqracter abzuspeichern.
Früher mit 7Byte Zeichensatz war das wurscht.
Eigentlich muesste man den Datentyp von VARCHAR2 in VARBYTE2 umtaufen ;-)
(Was von der Definition des Datentyps byte her auch wieder schlecht ist).
Allerdings habe ich noch keine richtige Berechnungsmöglichkeit gefunden
wieviel Byte denn, abhängig vom Characterset, nun für die Entsprechende
Eingabe benötigt werden.
Frank
claus:
Da kann ich denke ich Abhilfe schaffen (hat bei meinem vorigen Arbeitgeber zumindest funktioniert):
--- Code: ---(... my $length = length($new_value);... )
foreach (split (//, $new_value))
{
$length++ if (ord($_) > 127);
$length++ if (ord($_) > 255);
}
--- Ende Code ---
Also, ein Byte, für 0 < x < 127, zwei Byte für 128 < x < 255 und drei Byte für x > 255.
Das ist aber nur von Bedeutung, wenn für NLS_LENGTH_SEMANTICS "Byte" als Wert gesetzt ist.
--- Zitat ---ord
Returns the numeric (the native 8-bit encoding, like ASCII or EBCDIC, or Unicode) value of the first character of EXPR. If EXPR is omitted, uses $_.
For the reverse, see chr. See the perlunicode manpage and the encoding manpage for more about Unicode.
--- Ende Zitat ---
(Quelle: http://www.mathematik.uni-ulm.de/help/perl5/doc/perlfunc.html#item_ord)
Claus
Navigation
[0] Themen-Index
Zur normalen Ansicht wechseln