Substr Oracle vs. Postgres

Wir verwenden auf der Arbeit eigentlich schon immer bei der Oracle-Funktion „SUBSTR“ als Start-Index die 0, wenn wir vorne am String anfangen wollen. Analog zu PHP, wo das ja auch so ist. Das klappt unter Oracle auch. Da wir gerade mit Postgres als DBMS experimentieren, habe ich nun aber herausgefunden, dass das unter Postgres nicht funktioniert, und zwar auf subtile Weise.

Unter Postgres passiert das hier, wenn man versucht, die letzten 4 Zeichen abzuschneiden:

-- lore
select SUBSTR( 'lorem', 0, LENGTH( 'lorem' ) );

-- lorem
select SUBSTR( 'lorem', 1, LENGTH( 'lorem' ) );

Wie man sieht kommt mit Start-Index 0 nicht das korrekte Ergebnis dabei heraus. Postgres scheint das als „-1″, also als „beginne 1 Zeichen vor dem Start“, zu interpretieren.

Unter Oracle sieht es dagegen so aus:

-- lorem
select SUBSTR( 'lorem', 0, LENGTH( 'lorem' ) ) from dual;

-- lorem
select SUBSTR( 'lorem', 1, LENGTH( 'lorem' ) ) from dual;

Wieso ist das so? In der Oracle-Doku steht explizit das hier:

If position is 0, then it is treated as 1.

Fazit: Man sollte immer 1 verwenden als Start-Index und nicht 0.

Der erste Parameter unterscheidet sich übrigens auch für negative Zahlen:

  • Oracle: Wenn die Positionsangabe negativ ist, ermittelt Oracle die Startposition rückwärts vom Ende des Strings.
  • Postgres: Unterstützt das offenbar nicht, beschwert sich aber auch nicht, sondern macht irgendwas.

Siehe Beispiele:

-- Oracle: em
select SUBSTR( 'lorem', -2 ) from dual;

-- Postgres: lorem
select SUBSTR( 'lorem', -2 );

-- Oracle: em
select SUBSTR( 'lorem', -2, 5 ) from dual;

-- Postgres: lo
select SUBSTR( 'lorem', -2, 5 );

Gerade an letzterem Beispiel kann man erahnen, dass Postgres gewissermaßen die 5 ersten Zeichen aus dem String “ lorem“ benutzt, so als hätte der die Positionen „-2, -1, 0, 1, 2″ und erst ab 1 würden die Zeichen des Strings kommen.

Beim Umstieg von Oracle auf Postgres muss man auf jeden Fall solche Fälle beachten. Wenn Parameter 2 oder 3 mit festen Zahlen verwendet werden, kann man das ganz gut mit einer Textsuche finden. In meinem Fall ging es mit einer Suche nach “ substr“, da wir für die PHP-Version überall das Pendant „mb_substr“ verwenden. Wenn die Parameter aber dynamisch aus anderen Quellen kommen, kann das auf den ersten Blick durchaus schwierig werden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Bitte beachte die Kommentarregeln: 1) Kein Spam, und bitte höflich bleiben. 2) Ins Namensfeld gehört ein Name. Gerne ein Pseudonym, aber bitte keine Keywords. 3) Keine kommerziellen Links, außer es hat Bezug zum Beitrag. mehr Details...

So, noch mal kurz drüber schauen und dann nichts wie ab damit. Vielen Dank fürs Kommentieren! :-)