Character Length Semantics

02.
November
2023
Veröffentlicht von: Dr. Gudrun Pabst

Seit Oracle 9i gibt es die Möglichkeit anzugeben, ob die Datenbank die Längenangabe bei CHAR und VARCHAR2 als Byte oder als Zeichenanzahl interpretiert. Dies bezeichnet man als Character Length Semantics. Wozu dient die Angabe und welche Auswirkungen hat sie?

1. Hintergrund

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:

  • ab Oracle 9i
  • BYTE oder CHAR
  • (nur) relevant für Zeichensätze, die Zeichen mit mehr als 1 Byte enthalten wie z. B. AL32UTF8

Dabei ist aber zu beachten, dass die maximale Länge für VARCHAR2

  • bei Tabellenspalten 4000 Bytes (extended 32767 Bytes)
  • bei PL/SQL-Variablen 32767 Bytes

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.

2. Festlegung

Für die Festlegung der gewünschten Semantik gibt es verschiedene Methoden:

  • NLS_LENGTH_SEMANTICS
  • explizite Angabe
     

2.1.    NLS_LENGTH_SEMANTICS

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.


2.1.1.    Instanzebene

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.
 

2.1.2.    Clientseitig

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:
 

PL/SQL

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.
 

2.1.3.    Prüfen der aktuellen Werte

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


2.2.    Explizite Angabe

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;


3.    Auswirkungen

Wie verhalten sich Spalten und PL/SQL-Variablen bei Änderung des Werts für NLS_LENGTH_SEMANTICS?

3.1.    Tabellenspalten

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

  • bei der Einstellung NLS_LENGTH_SEMANTICS=BYTE eine Spalte TEST_COL   VARCHAR2(20 BYTE) angelegt,
  • bei der Einstellung NLS_LENGTH_SEMANTICS=CHAR eine Spalte TEST_COL   VARCHAR2(20 CHAR).

Diese Einstellung wird bei der Spalte permanent gespeichert, eine Änderung von NLS_LENGTH_SEMANTICS ändert nichts mehr an der Spaltendefinition.


3.2.    Variablen in PL/SQL

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.

 

Fazit

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.

Jede Menge Know-how für Sie!

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.