Ein Zeichen in einem Text ist gekennzeichnet durch die Angabe seiner Position in einem Zeichensatz. Beim Speichern des Textes wird für jedes Zeichen diese Position abgespeichert. Die anfänglichen Zeichensätze umfassten nur 7 Bit oder 8 Bit Positionen für Zeichen, d. h. jedes Zeichen konnte durch 1 Byte angegeben und gespeichert werden. Um die speziellen Schriftzeichen der einzelnen Sprachen in einem einheitlichen Zeichensatz zusammenzufassen, wurde der Unicode-Zeichensatz entwickelt. In diesem Zeichensatz kann ein Zeichen bis zu 4 Byte für die Angabe seiner Position und damit als Speicherplatz benötigen.
Für die Datenbank bedeutet dies: Bei Zeichensätzen, in denen jedes Zeichen nur 1 Byte benötigt, gibt es keinen Unterschied zwischen der Anzahl Bytes, die in einer Spalte gespeichert werden können, und der Anzahl der Zeichen, die eine Spalte speichern kann. Bei Zeichensätzen wie Unicode ist die Anzahl der Bytes, die ein Text benötigt, im allgemeinen jedoch größer als die Anzahl der Zeichen im Text. Mit Character Length Semantics wird festgelegt, ob die Längenangabe einer Spalte oder einer Variable als Anzahl Bytes oder Anzahl Zeichen zu verstehen ist.
Character Length Semantics:
Dabei ist aber zu beachten, dass die maximale Länge für VARCHAR2
ist, auch wenn die Deklaration CHAR angibt!
Bei der Bestimmung der benötigten Anzahl Zeichen sollte daher betrachtet werden, welche Zeichenketten gespeichert werden sollen. Handelt es sich um deutsche Texte, so ergibt sich aus der Verteilung von 1-Byte-Zeichen zu 2-Byte-Zeichen (Umlaute, ß) und 3-Byte-Zeichen (€), dass 3900 Zeichen (extended bzw. PL/SQL 32000 Zeichen) für Standardtexte ausreichen. Wenn zu erwarten ist, dass die Texte z. B. viele €-Zeichen enthalten, sollten die Werte entsprechend reduziert werden.
Für die Festlegung der gewünschten Semantik gibt es verschiedene Methoden:
Der Parameter NLS_LENGTH_SEMANTICS legt fest, wie die Längen in CHAR- und VARCHAR2-Angaben ohne explizites Schlüsselwort BYTE oder CHAR interpretiert werden. Dies betrifft sowohl DDL-Statements für Spalten als auch Variablen in PL/SQL-Code.
Der Parameter NLS_LENGTH_SEMANTICS auf Instanzebene wird als Default für alle Sessions verwendet, die diese Einstellung nicht überschreiben. Er kann mit alter system geändert werden.
ACHTUNG: Wird der Parameter in der init.ora oder im spfile gesetzt, empfiehlt Oracle, ihn aus Kompatibilitätsgründen mit bestehenden Installationsskripten (auch von Oracle) nicht auf CHAR zu setzen.
Ab Oracle 10g kann der Parameter clientseitig über eine Umgebungsvariable mit dem Namen NLS_LENGTH_SEMANTICS oder einen Registry-Eintrag gesetzt werden. Die Einstellung gilt dann auf diesem Rechner für alle Sessions, die von einem Datenbank-Client geöffnet werden, der diese Einstellung benutzt, z. B. SQL*Plus.
Verwendet man den SQL Developer, muss man im Abschnitt „Database NLS“ der Präferenzen einstellen, ob die Längenangaben als Zeichen oder als Byte interpretiert werden:
Der Login-Prozess setzt dann in der Session beim Start den gewünschten Wert.
Der Parameter kann auf Sessionebene auch manuell gesetzt werden durch:
alter session set nls_length_semantics = CHAR;
Die hiermit getroffene Einstellung ist nur für die aktuelle Session gültig. Ohne diese Angabe wird die Einstellung der Instanz verwendet.
Mit der Abfrage
select dbi.parameter parameter_name ,
dbi.value wert_instanz ,
dbs.value wert_session
from nls_instance_parameters dbi ,
nls_session_parameters dbs
where dbi.parameter = dbs.parameter
and dbi.parameter = 'NLS_LENGTH_SEMANTICS';
können die aktuellen Werte geprüft werden:
PARAMETER_NAME WERT_INSTANZ WERT_SESSION
------------------------- --------------- ---------------
NLS_LENGTH_SEMANTICS BYTE BYTE
Sowohl bei DDL-Statements für Columns als auch bei Variablen-Deklarationen in PL/SQL kann explizit angegeben werden, ob die Längenangabe als Byte- oder als Zeichenanzahl zu verstehen ist.
Beispiel-DDL:
create table test (
test_text varchar2(200 CHAR) );
In PL/SQL:
declare
v_text varchar2(30 CHAR);
begin
…
end;
Wie verhalten sich Spalten und PL/SQL-Variablen bei Änderung des Werts für NLS_LENGTH_SEMANTICS?
Wird eine Textspalte in einer Tabelle ohne Angabe der gewünschten Semantik angelegt, erhält sie die gerade in der Session aktive Einstellung. Dies bedeutet: Mit alter table test add ( test_col varchar2(20) ); wird
Diese Einstellung wird bei der Spalte permanent gespeichert, eine Änderung von NLS_LENGTH_SEMANTICS ändert nichts mehr an der Spaltendefinition.
Bei der Deklaration von Variablen in PL/SQL ohne explizite Angabe der gewünschten Semantik wird ebenfalls die Session-Einstellung verwendet. Der Code
declare
v_text varchar2(5);
begin
v_text := 'äöüß';
end;
funktioniert bei der Session-Einstellung NLS_LENGTH_SEMANTICS=CHAR .
Bei NLS_LENGTH_SEMANTICS=BYTE liefert er den Fehler ORA-06502: PL/SQL: numeric or value error: character string buffer too small.
Wird ein PL/SQL-Code als Routine in der Datenbank gespeichert, hinterlegt die Datenbank die aktuelle Einstellung von NLS_LENGTH_SEMANTICS bei der Routine. Der hinterlegte Wert kann in USER_PLSQL_OBJECT_SETTINGS überprüft werden.
Unabhängig von der Session-Einstellung wird bei der Ausführung der hinterlegte Wert verwendet:
alter session set nls_length_semantics=char;
create or replace function fc_char_len_sem (
p_text in varchar2 )
return varchar2
is
v_text varchar2(5);
begin
--
v_text := p_text;
return v_text;
--
end fc_char_len_sem;
/
alter session set nls_length_semantics=byte;
select fc_char_len_sem ( 'äöüß' ) text
from dual;
TEXT
----
äöüß
Auch bei einem impliziten Recompile ändert sich daran nichts.
Wird die Routine jedoch explizit rekompiliert (Ausnahme siehe unten), werden die Einstellungen der aktuellen Session verwendet. Nach einem expliziten Recompile in einer Session mit der Einstellung NLS_LENGTH_SEMANTICS=BYTE liefert der Select eine Fehlermeldung:
alter function fc_char_len_sem compile;
select fc_char_len_sem ( 'äöüß' ) text
from dual;
select fc_char_len_sem ( 'äöüß' ) text
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "DEMO.FC_CHAR_LEN_SEM", line 8
Ausnahme: Bei explizitem Kompilieren mit der Angabe reuse settings werden die Einstellungen verwendet, die in den PL/SQL Object Settings gespeichert sind, also auch die gespeicherte Einstellung für NLS_LENGTH_SEMANTICS.
Wird die Character Length – Semantik beim Anlegen von Objekten nicht angegeben, kann es zu Situationen kommen, in denen vorher funktionierende Anwendungen plötzlich auf Fehler laufen.
Daher sollte sowohl beim Anlegen von Tabellenspalten als auch im PL/SQL-Code immer angegeben werden, wie die Längenangabe bei Textspalten und -variablen zu verstehen ist.
In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den
Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.