oci_connect() + apache + umlaute

bsd69

Gitarrist & Cabriofahrer
Hallo Zusammen,

schon wieder plagt mich ein Problem. Wie im Betreff geschrieben, geht's um Daten mit Umlauten, welche via einer PHP-Applikation mittels oci_connect() von einer Oracle-DB abgefragt werden.

Fakt ist: - NLS ist korrekt gesetzt
- die Umlaute sind in der DB korrekt drin
- googlen + Forensuche brachte viele Hinweise, leider keinen der half
- statische HTML-Umlaute werden korrekt dargestellt

Folgende Ports sind installiert:
php5-5.2.5_1
php5-extensions-1.1
php5-oci8-5.2.5_1
php5-pcre-5.2.5_1
php5-session-5.2.5_1
php5-simplexml-5.2.5_1
php5-xml-5.2.5_1

Jemand eine Idee? Habe leider keine mehr :grumble:

Greetz Mäsa
 
Hallo,

zumindest ganz früher brauchte man noch den Oracle-Client selbst.
Dieser ist im wesentlichen die Datei libclntsh.so, welche man in binärer Form nur von Oracle bekommt (auch für FreeBSD?).

Nunja, jetzt scheint aber bei Dir der Oracle-Connect bereits zu funktionieren, also sollte die libclntsh.so kein Problem sein. Scheinbar ist das dann statisch mit einem der Ports zusammengelinkt.

Oracle benötigt aber für andere Codepages noch NLS-Dateien, welche normalerweise im Oracle-Client enthalten sind und bei Dir nicht installiert ist.
Diese Dateien fehlen Dir und wahrscheinlich auch noch die darauf verweisenden Umgebungsvariablen.

Bei Oracle 10g liegen diese im $ORACLE_HOME/nls/data.
Wenn die Umgebungsvariable $ORACLE_HOME auf ein gültiges Verzeichnis mit installiertem Oracle-Client zeigt, dann reicht das aus.

Wenn Du nur das NLS-Verzeichnis hast, dann kannst Du bei 10g die Variable ORA_NLS33 auf dieses Verzeichnis zeigen lassen.

Den Oracle-Client kann man z.B. von Linux nehmen, denn wir brauchen ja nur die NLS-Dateien.

Du solltest also folgende Variablen im PHP-Kontext gesetzt haben:
Code:
NLS_LANG=German_Germany.WE8ISO8859P1

ORACLE_HOME=/pfad/zu/meinem/zb_linux_oracle/client
#oder
ORA_NLS10=/pfad/zu/meinem/zb_linux_oracle/client/nls/data


Wenn mit Deiner PHP-Bibliothek Oracle 10g verlinkt ist, dann passt die Anleitung.
Bei Oracle 8 und 9 heißt die Variable ORA_NLS33, die NLS-Dateien liegen an einem anderen Ort und haben ein anderes Format. Hier kann man aber analog vorgehen.
 
Zuletzt bearbeitet:
Hallo,

Oracle benötigt aber für andere Codepages noch NLS-Dateien, welche normalerweise im Oracle-Client enthalten sind und bei Dir nicht installiert ist.
Diese Dateien fehlen Dir und wahrscheinlich auch noch die darauf verweisenden Umgebungsvariablen.

Bei Oracle 10g liegen diese im $ORACLE_HOME/nls/data.
Wenn die Umgebungsvariable $ORACLE_HOME auf ein gültiges Verzeichnis mit installiertem Oracle-Client zeigt, dann reicht das aus.

Wenn Du nur das NLS-Verzeichnis hast, dann kannst Du bei 10g die Variable ORA_NLS33 auf dieses Verzeichnis zeigen lassen.

Den Oracle-Client kann man z.B. von Linux nehmen, denn wir brauchen ja nur die NLS-Dateien.

Upps sorry, habe natürlich schon den Oracle-Client installiert und die entsprechenden ORA-Parameter auch gesetzt.:
oracle8-client-0.2.0_1 Oracle 8 client

Ebenfalls versuchte ich's noch mit dem Linux-Oracle-Client. Leider ohne Erfolg.

Du solltest also folgende Variablen im PHP-Kontext gesetzt haben:
Code:
NLS_LANG=German_Germany.WE8ISO8859P1

Nicht ganz:
Code:
NLS_LANG=GERMAN_[B]SWITZERLAND[/B].WE8ISO8859P1 :D

Aber danke für deinen Input!

P.S. was ist bei dir der
Code:
PHP-Kontext? php.ini?
 
Zunächst eine Korrektur:
Oracle 10g --> NLS10
Oracle 8+9 --> NLS33

Wie man das bei PHP setzt, kann ich nicht direkt sagen.
Man könnte das z.B. im Environment des Web-Servers setzten.

Es gibt in PHP so einen Aufruf, mit dem man sich das gesamte Environment ausgebenen lassen kann. Das würde ich mal in eine Test-PHP-Seite einbauen und schauen, ob die Variablen wirklich gesetzt sind.

Und wie gesagt: Du brauchst NLS_LANG und eine der anderen Variablen. Also immer zwei ... und die NLS-Dateien natürlich.
Das sinnvollste ist es, wenn Du NLS_LANG und ORACLE_HOME setzt.
 
Zunächst eine Korrektur:
Oracle 10g --> NLS10
Oracle 8+9 --> NLS33

Wie man das bei PHP setzt, kann ich nicht direkt sagen.
Man könnte das z.B. im Environment des Web-Servers setzten.

Es gibt in PHP so einen Aufruf, mit dem man sich das gesamte Environment ausgebenen lassen kann. Das würde ich mal in eine Test-PHP-Seite einbauen und schauen, ob die Variablen wirklich gesetzt sind.

Und wie gesagt: Du brauchst NLS_LANG und eine der anderen Variablen. Also immer zwei ... und die NLS-Dateien natürlich.
Das sinnvollste ist es, wenn Du NLS_LANG und ORACLE_HOME setzt.

Hallo nochmals,

dies habe ich leider alles hinter mir. Die Umlaute wollen einfach nicht. Vielleicht fällt mir ja noch was anderes ein.
Danke auf jeden Fall!
 
Hallo,

um Deine Chancen zu verbessern hier einige Hintergrundinformationen:

Man muss bei Oracle den Client und den Server im Bezug auf Zeichensatz unterscheiden.


Zur Datenbank
Die Datenbank hat zwei Zeichensätze: Einen primären und einen lokalisierten.

Der primäre Zeichensatz der Datenbank ist/war meistens immer irgendwas mit 8 Bit wie WE8ISO8859P1, US7BITASCII(?) oder WE8DEC. Dieser wird z.B. verwendet bei CHAR, VARCHAR2 und CLOB.

Der sekundäre nationale Zeichensatz ist meistens ein Unicode-Zeichensatz. Dieser wird bei den Datentypen NCHAR, NVARCHAR2 und NCLOB verwendet.

Zum Client
Der Client bekommt von der Datenbank die dort eingestellten Zeichensätze mitgeteilt und versucht diese in den lokal darstellbaren Zeichensatz (NLS_LANG) zu konvertieren. Das macht der Client gerne mal falsch.
Während bei dem sekundären Unicode-Zeichensatz noch sehr genau definiert ist, welches Zeichen in der Datenbank steht, wird in den primören 8-Bit-Zeichensätzen aus Sicht der Datenbank mehr oder weniger schwammige 8-Bit-Werte gespeichert.
WE8DEC ist die Situation sogar noch verschärft. Im Prinzip kann man hier nur erwarten, dass man unter einer bestimmten NLS-Konfiguration im Client die Zeichen so wieder zurückbekommt, wie man sie reingeschrieben hat. Wenn die NLS-Konfiguration von Server und Client abweicht, dann versucht Oracle zu konvertieren und man bekommt eigentlich in jedem Fall Müll dabei raus.

Ich würde das alles vorher mal mit sqlplus und einfachen Tabellen von der Shell aus testen. Wenn es mit sqlplus mit einem bestimmten NLS-Environment richtig funktioniert, dann hat man gute Chancen, dass es damit auch mit PHP geht.
 
Zuletzt bearbeitet:
Hallo,

danke dir nochmals für deinen Input. Das Problem ist eigentlich in der Zwischenzeit das Folgende:

ich setze die NLS-Parameter und baue eine sqlplus zur DB auf. Sämtliche Umlaute werden korrrekt dargestellt :) Ohne setzen der NLS-Parameters werden keine Umlaute dargestellt, ist ja klar. Hmm.. wenn ich nun die funktionierenden NLS-Parameter setze und mittels der php-Applikation einen oci_connect zur DB aufbauen will, funktioniert bereits der Connect nicht mehr ;'( Ohne NLS funktioniert der Connect, aber logischerweise die Umlaute nicht.

Ich habe noch die Möglichkeit, beim oci_connect den Zeichensatz mitzugeben. Wenn ich dies tue, erhalte ich die Errormeldung

Code:
[10-Apr-2008 15:15:41] PHP Notice:  oci_connect() [<a href='function.oci-connect'>function.oci-connect</a>]: Your version of Oracle Client doesn't support setting the charset; bad or no charset conversions may result in /blabla/applikation.php

Ich glaube, damit sieht's dann eben schlecht aus.... :grumble:
 
Hallo,

ich würde bei der vorletzten Variante weiterversuchen, bei der die NLS-Paramter gesetzt werden und ein normaler Oracle-Connect von PHP aus gemacht wird.

Was passiert denn, wenn Du als "apache"-User mit sqlplus einen Connect versuchst?

Du kannst vorerst mal damit probieren die NLS-Parameter in dem init-Skript vom Apache zu setzen.
 
Hallo,

ich würde bei der vorletzten Variante weiterversuchen, bei der die NLS-Paramter gesetzt werden und ein normaler Oracle-Connect von PHP aus gemacht wird.

Was passiert denn, wenn Du als "apache"-User mit sqlplus einen Connect versuchst?

Du kannst vorerst mal damit probieren die NLS-Parameter in dem init-Skript vom Apache zu setzen.

Ja weisst du, das habe ich leider alles schon hinter mir. Immer wenn ich die NLS setze, egal wo, auch im Init-Script vom Apache, funzt der oci_connect nicht mehr. Drehe mich leider im Kreis :grumble:
 
:):) PROBLEM GELÖST :):)

Für die Nachwelt:

Unglaublich, aber wahr. Die Errormeldungen führen oftmals in die Irre bzw. auf den falschen Weg...

Die unglaubliche, aber einfache Lösung, sofern man(n) die Ursache findet:
Code:
chmod o+rx /usr/local/oracle8-client

Zur Ergänzung:
Folgende NLS-Parameter habe ich im .bash_profile des Users "root" gesetzt:
(gilt natürlich nur bei Verwendung der bash, ansonsten entsprechend im .cshrc oder .profile etc.)
Code:
export ORACLE_HOME=/usr/local/oracle8-client/lib
export ORA_NLS33=/usr/local/oracle8-client/ocommon/nls/admin/data
export NLS_LANG=GERMAN_SWITZERLAND.WE8ISO8859P1

Meine Erklärung dazu:
Code:
Die Erschwernis bei der Fehlersuche war, dass der User "root" den Apache starten muss (wegem Port 80) und dann den Startprozess dem 
unprivilegierten User "www" zuschiebt. Der User "www" konnte daher nicht ins obgenannte Verzeichnis zugreifen. Per default ist dieser User 
ein "nicht-interaktiver-User", weil sein "Home directory: /nonexistent" und seine "Shell: /usr/sbin/nologin" gesetzt sind. Daher versuchte 
ich's ja erst gar nicht mit diesem User.

Ok, that's all. Danke dir rMarkus nochmals für deine wertvollen Tipps und die Unterstützung bei der Lösungssuche :)
 
Hallo,

das Setzen der Variablen in Login von Root dürfte aber nur einen Erfolg bringen, wenn Du Apache als Root von Hand startest.

Normalerweise wird der Apache über den Init gestartet, wobei zwar auch eine Shell (zum Ausführen des init-Shellskriptes) verwendet wird, diese aber nicht als Login-Shell läuft und so keine oder nur teile der Login-Skripte ausführt.

Sinnvoll ist es da eher das init-Skript für den Apache über rc.conf zu parametrisieren oder auch im Notfall selbst zu verändern.


Die Variablen scheinen mir auch noch leicht falsch gesetzt.
Ich würde auch auf ORA_NLS33 verzichten und nur dann setzen, wenn das NLS-Verzeichnis nicht am unter ${ORACLE_HOME}/ocommon/nls/admin/data liegt.

ORACLE_HOME zeigt nicht auf das Lib-Verzeichnis mit z.B. libclntsh.so sondern auf einen Ast tiefer ( cd .. ).

Code:
export ORACLE_HOME=/usr/local/oracle8-client
# export ORA_NLS33=${ORACLE_HOME}/ocommon/nls/admin/data
export NLS_LANG=GERMAN_SWITZERLAND.WE8ISO8859P1
 
Hallo,

das Setzen der Variablen in Login von Root dürfte aber nur einen Erfolg bringen, wenn Du Apache als Root von Hand startest.

Normalerweise wird der Apache über den Init gestartet, wobei zwar auch eine Shell (zum Ausführen des init-Shellskriptes) verwendet wird, diese aber nicht als Login-Shell läuft und so keine oder nur teile der Login-Skripte ausführt.

Sinnvoll ist es da eher das init-Skript für den Apache über rc.conf zu parametrisieren oder auch im Notfall selbst zu verändern.


Die Variablen scheinen mir auch noch leicht falsch gesetzt.
Ich würde auch auf ORA_NLS33 verzichten und nur dann setzen, wenn das NLS-Verzeichnis nicht am unter ${ORACLE_HOME}/ocommon/nls/admin/data liegt.

ORACLE_HOME zeigt nicht auf das Lib-Verzeichnis mit z.B. libclntsh.so sondern auf einen Ast tiefer ( cd .. ).

Code:
export ORACLE_HOME=/usr/local/oracle8-client
# export ORA_NLS33=${ORACLE_HOME}/ocommon/nls/admin/data
export NLS_LANG=GERMAN_SWITZERLAND.WE8ISO8859P1

Hallo nochmals,
ja, das sehe ich auch so. Allerdings sind wir jetzt beim feintunen (was auch richtig ist), prinzipiell funktioniert's aber so, wie von mir oben beschrieben.
Greetz Mäsa
 
Hallo,

ich wollte die Lösung nur noch mal verbessern, da man sonst auch zukünftig mit Oracle und NLS viel "Spass" bekommen kann.

NLS ist eines der ekligsten und undurchsichtigsten Themen bei Oracle. Der Rest bei Oracle ist eigentlich sehr sauber und logisch aufgebaut.
 
Zurück
Oben