Hallo,
ich habe mich nun eine ganze Weile mit der Migration einer PHP Anwendung von MySQL auf Oracle beschäftigt. Ich möchte hier meine Erfahrung aufschreiben, damit jemand anderem evtl. geholfen wird. Einen Anspruch auf Vollständigkeit der Themen gibt es natürlich nicht.
Hier die wesentlichen Punkte:
---
Oracle kennt kein NOW(). Ein Ersatz mit CURRENT_TIMESTAMP hat hier geholfen.
---
Die Datumsangaben werden, im Gegensatz zu MySQL, nicht sehr frei interpretiert. Sie müssen
A) mit TO_DATE() übergeben werden. Dabei ist das komplette Format der Datumsangabe zu übergeben.
B) durch Anpassen von NLS_DATE_FORMAT umgestaltet werden. Voraussetzung ist, dass man in seiner Anwendung immer im selben Format übergibt. Dazu gehört auch die Uhrzeit, die man bei entsprechendem Format dann immer angeben muss.
Doch Achtung: Wenn man OCI verwendet, kann man die Oracle-Parameter verändern wie man möchte. Es zeigt keine Wirkung (also einfach lassen). Es hilft nur, bei jedem Query vorher die Session mit ALTER SYSTEM SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS' SCOPE = SPFILE; auf das gewünschte Format zu bringen. Dann klappt es. Performance-Einschränkung habe ich gemessen und kam auf 0,0005 Sekunden mehr für einen Query mit Anpassung der Session (10'000 Querys ausgeführt).
---
Eine ON DUPLICATE KEY Funtion gibt es in Oracle nicht. Das kann man nur mit komplexeren IF THEN Anweisungen oder einer MERGE WHEN NOT MATCHED Funktion erreichen. Diese ist aber recht komplex. In diesen Fällen habe ich mir lieber einen SELECT vorneweg gegönnt und entscheide dann im Code ob ich ein INSERT oder ein UPDATE mache.
---
Oracle kennt keine INSERTs im Stil von INSERT INTO table SET Field1=Value1, Field2=Value2 etc. Das geht nur mit INSERT INTO table(Field1, Field2) VALUES(Value1, Value2). Ich habe mir einen kleinen Parser gebaut, der die INSERTS zur Laufzeit umbaut. Ansonsten hätte ich bergeweise INSERTS umbauen müssen. Ausserdem hat mir die Code-Übersichtlichkeit in der SET Variante mehr zugesagt. Code ist weiter unten im Thread...
---
Einen vergleichbaren Ersatz für LIMIT gibt es unter Oracle nicht. Stattdessen muss man den Query in zwei übergeordnete Query's einschachteln um das zu simulieren. Auch hier habe ich mir einen Parser zur Laufzeit gebaut, der die bestehenden LIMIT-Angaben umwandelt (nicht in Sub-Selects). Code ist weiter unten im Thread...
---
Die TO_DAYS() Funktion aus MySQL kann man möglicherweise in Oracle einfach durch TRUNC() ersetzen. Das liefert auch die Tageszahl.
---
Die MONTH(Date) Funktion aus MySQL kann mit TO_NUMBER(TO_CHAR(Date,'mm')) übersetzt werden.
---
Die YEAR(Date) Funktion aus MySQL kann mit TO_NUMBER(TO_CHAR(Date,'yyyy')) übersetzt werden.
---
Vor allem die Oracle XE hat per Default nur 10 Prozesse eingestellt. Das führt bei schnellen Datenbank-Zugriffen zu Fehlermeldungen (TNS:listener). Dem kann man mit ALTER SYSTEM SET PROCESSES=300 SCOPE=SPFILE; abhelfen (danach DB restarten).
---
Statt CONCAT() fügt man in Oracle Strings übrigens mit dem || Operator zusammen.
---
AutoID Spalten kennt Oracle nicht. Dazu muss man mit Sequenzen und Triggern arbeiten. Das Internet ist voll mit Beispielen dazu.
---
LIKE-Suchen sind bei Oracle immer Case-Sensitiv! Bei MySQL ist das nicht der Fall. Nun hat man evtl. ein Problem zB bei Nutzer-Logins etc. Hier kann es helfen, die Abfrage so zu gestalten (Beispielsuche nach Usernamen):
$SQL = "SELECT * FROM tbluser WHERE UPPER(USERNAME) LIKE '%" . strtoupper($Username) . "%' ORDER BY USERID";
Leider benutzt Oracle nun nicht mehr einen auf USERNAME stehenden Index. Da gibt es aber Abhilfe, indem man den Index folgend anlegt:
CREATE INDEX idx_Userame ON tbluser(UPPER(USERNAME));
---
GROUP BY kann bei Oracle nicht mit Aliasen arbeiten. Man sollte dann den eigentlichen (im Query angegebenen) Ausdruck erneut zur Sortierung heranziehen.
Ich hoffe es hilft jemandem...
Grüße,
Donald
ich habe mich nun eine ganze Weile mit der Migration einer PHP Anwendung von MySQL auf Oracle beschäftigt. Ich möchte hier meine Erfahrung aufschreiben, damit jemand anderem evtl. geholfen wird. Einen Anspruch auf Vollständigkeit der Themen gibt es natürlich nicht.

Hier die wesentlichen Punkte:
---
Oracle kennt kein NOW(). Ein Ersatz mit CURRENT_TIMESTAMP hat hier geholfen.
---
Die Datumsangaben werden, im Gegensatz zu MySQL, nicht sehr frei interpretiert. Sie müssen
A) mit TO_DATE() übergeben werden. Dabei ist das komplette Format der Datumsangabe zu übergeben.
B) durch Anpassen von NLS_DATE_FORMAT umgestaltet werden. Voraussetzung ist, dass man in seiner Anwendung immer im selben Format übergibt. Dazu gehört auch die Uhrzeit, die man bei entsprechendem Format dann immer angeben muss.
Doch Achtung: Wenn man OCI verwendet, kann man die Oracle-Parameter verändern wie man möchte. Es zeigt keine Wirkung (also einfach lassen). Es hilft nur, bei jedem Query vorher die Session mit ALTER SYSTEM SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS' SCOPE = SPFILE; auf das gewünschte Format zu bringen. Dann klappt es. Performance-Einschränkung habe ich gemessen und kam auf 0,0005 Sekunden mehr für einen Query mit Anpassung der Session (10'000 Querys ausgeführt).
---
Eine ON DUPLICATE KEY Funtion gibt es in Oracle nicht. Das kann man nur mit komplexeren IF THEN Anweisungen oder einer MERGE WHEN NOT MATCHED Funktion erreichen. Diese ist aber recht komplex. In diesen Fällen habe ich mir lieber einen SELECT vorneweg gegönnt und entscheide dann im Code ob ich ein INSERT oder ein UPDATE mache.
---
Oracle kennt keine INSERTs im Stil von INSERT INTO table SET Field1=Value1, Field2=Value2 etc. Das geht nur mit INSERT INTO table(Field1, Field2) VALUES(Value1, Value2). Ich habe mir einen kleinen Parser gebaut, der die INSERTS zur Laufzeit umbaut. Ansonsten hätte ich bergeweise INSERTS umbauen müssen. Ausserdem hat mir die Code-Übersichtlichkeit in der SET Variante mehr zugesagt. Code ist weiter unten im Thread...
---
Einen vergleichbaren Ersatz für LIMIT gibt es unter Oracle nicht. Stattdessen muss man den Query in zwei übergeordnete Query's einschachteln um das zu simulieren. Auch hier habe ich mir einen Parser zur Laufzeit gebaut, der die bestehenden LIMIT-Angaben umwandelt (nicht in Sub-Selects). Code ist weiter unten im Thread...
---
Die TO_DAYS() Funktion aus MySQL kann man möglicherweise in Oracle einfach durch TRUNC() ersetzen. Das liefert auch die Tageszahl.
---
Die MONTH(Date) Funktion aus MySQL kann mit TO_NUMBER(TO_CHAR(Date,'mm')) übersetzt werden.
---
Die YEAR(Date) Funktion aus MySQL kann mit TO_NUMBER(TO_CHAR(Date,'yyyy')) übersetzt werden.
---
Vor allem die Oracle XE hat per Default nur 10 Prozesse eingestellt. Das führt bei schnellen Datenbank-Zugriffen zu Fehlermeldungen (TNS:listener). Dem kann man mit ALTER SYSTEM SET PROCESSES=300 SCOPE=SPFILE; abhelfen (danach DB restarten).
---
Statt CONCAT() fügt man in Oracle Strings übrigens mit dem || Operator zusammen.
---
AutoID Spalten kennt Oracle nicht. Dazu muss man mit Sequenzen und Triggern arbeiten. Das Internet ist voll mit Beispielen dazu.
---
LIKE-Suchen sind bei Oracle immer Case-Sensitiv! Bei MySQL ist das nicht der Fall. Nun hat man evtl. ein Problem zB bei Nutzer-Logins etc. Hier kann es helfen, die Abfrage so zu gestalten (Beispielsuche nach Usernamen):
$SQL = "SELECT * FROM tbluser WHERE UPPER(USERNAME) LIKE '%" . strtoupper($Username) . "%' ORDER BY USERID";
Leider benutzt Oracle nun nicht mehr einen auf USERNAME stehenden Index. Da gibt es aber Abhilfe, indem man den Index folgend anlegt:
CREATE INDEX idx_Userame ON tbluser(UPPER(USERNAME));
---
GROUP BY kann bei Oracle nicht mit Aliasen arbeiten. Man sollte dann den eigentlichen (im Query angegebenen) Ausdruck erneut zur Sortierung heranziehen.
Ich hoffe es hilft jemandem...
Grüße,
Donald
Kommentar