Reguläre Ausdrücke in Oracle 10g

Werbung
Reguläre Ausdrücke in Oracle 10g –
Waren Queries bis jetzt irregulär?
Dr. Martin Wunderli
Trivadis AG
www.trivadis.com
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance
>
Fazit
2
© 2004
Wer suchet, der findet
>
Um in einer gegebenen Menge von Datensätzen zu suchen, gibt es
verschiedene Methoden
>
Den Weg der Suche beschreiben, d.h. prozedural. Beispielsweise in der
Form von Schleifen und IF-Anweisungen, in der Form von
Navigationsanweisungen bei Netzwerkdatenbanken usw.
>
Das Ergebnis der Suche beschreiben, d.h. deklarativ. Unter diese Rubrik
fallen SQL Queries mit WHERE Bedingungen
» Diese WHERE Bedingungen waren bis jetzt beschränkt auf
Vergleichsoperatoren, u.a. auch LIKE. LIKE kann Platzhalter für beliebig viele
Zeichen (%) oder genau ein Zeichen (_) enthalten konnte
» Ab Oracle 10g kann die WHERE Bedingung auch die Definition eines Musters
enthalten, dem ein Datensatz genügen muss: Dieses Muster nennt man eine
Regular Expression/einen regulären Ausdruck
Oracle 10g: Reguläre Ausdrücke
3
© 2004
Theoretischer Hintergrund
>
Reguläre Ausdrücke sind bekannt aus der
Berechenbarkeitstheorie, einem Teilgebiet der theoretischen
Informatik
>
Reguläre Ausdrücke bilden eine Famile von kompakten formalen
Sprachen. Mit einer solchen Sprache lassen sich Mengen von
Zeichenketten beschreiben
>
Beispiel: Unter der Annahme, dass der Punkt . für ein beliebiges
Zeichen steht, definiert der reguläre Ausdruck a.b die Menge
der Wörter (=Sprache) {aac,abc,acc} über dem Alphabet
{a,b,c}. ac oder axc wären nicht Teil dieser Sprache
Oracle 10g: Reguläre Ausdrücke
4
© 2004
Wieso reguläre Ausdrücke?
>
Die Mächtigkeit der regulären Ausdrücke liegt darin, dass man
auf kleinem Raum mit wenigen, speziellen Symbolen sehr
komplexe Muster definieren kann
>
Komplexer als z.B. mit % und _, da die Prüfung von
Zeichenklassen, Anzahl der Wiederholung einer
(Teil-)Zeichenkette, Variationen etc. beschrieben werden können
>
Der Nachteil ist, dass die Komplexität leicht in
Unübersichtlichkeit ausarten kann. Man sollte also bei der
Verwendung von regulären Ausdrücken immer den Aufbau in
Einzelschritten dokumentieren
Oracle 10g: Reguläre Ausdrücke
5
© 2004
Die wichtigsten Symbole in regulären Ausdrücken
Symbol
Bedeutung
*/+
0/1 bis n-malige Wiederholung des vorangehenden Ausdrucks
?
0 oder 1-malige Wiederholung des vorangehenden Ausdrucks
{4}
Genau 4-malige Wiederholung des vorangehenden Ausdrucks
{3,6}
3 bis 6-malige Wiederholung des vorangehenden Ausdrucks
.
Genau 1 beliebiges Zeichen
[0-9A-F]
Genau ein Zeichen aus der Menge 0-9 und A-F
[:alnum:]
Zeichenklasse, hier alle alphanummerischen Zeichen
( )
Gruppierung, welche z.B. wiederholt oder ersetzt werden kann
\2
Referenzierung einer Gruppierung, hier der zweiten
xx|yy
Entweder die Zeichenkette xx oder die Zeichenkette yy
^/$
Verankern die Regular Expression am Beginn/Ende einer Zeile/des zu
durchsuchenden Strings
>
Sollen Sonderzeichen wie ( und [ nicht zur Bildung von Symbolen verwendet
werden, muss man sie explizit mit \ markieren
Oracle 10g: Reguläre Ausdrücke
6
© 2004
Einfache Beispiele für reguläre Ausdrücke
>
Auf den Ausdruck bericht passt genau eine Zeichenkette, nämlich
bericht
>
Auf den Ausdruck bericht.. passt bericht01, bericht0a,
bericht15 aber nicht bericht1
>
Auf den Ausdruck bericht[0-8] passt bericht8 aber nicht
bericht9
>
Auf den Ausdruck bericht[[:digit:]]\.(txt|doc) passt
bericht1.txt und bericht2.doc, nicht aber bericht3-doc
>
Auf den Ausdruck bericht[A-Z]\.doc passt berichtA.doc aber
auch gegenberichtA.doc und berichtB.document
>
Auf den Ausdruck ^bericht[A-Z]\.doc$ passen gegenberichtA.doc
und berichtB.document aber nicht
Oracle 10g: Reguläre Ausdrücke
7
© 2004
Literatur
>
http://www.trivadis.com: Dieser Vortrag und ein Artikel von
Martin Bracher zum Thema 'Regular Expressions'
>
http://www.regular-expressions.info: Eine Einführung in
Reguläre Ausdrücke
>
Mastering Regular Expressions, Jeffrey E.F. Friedl, O'Reilly
>
Regular Expressions Pocket Reference, Tony Stubblebine, O'Reilly
>
Oracle Regular Expressions Pocket Reference, Jonathan Gennick
& Peter Linsey, O'Reilly
Oracle 10g: Reguläre Ausdrücke
8
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance
>
Fazit
9
© 2004
Das OWA_PATTERN Package (1)
>
Seit Oracle8i gibt es das OWA_PATTERN Package (pubpat.sql in
$ORACLE_HOME/rdbms/admin), welches auch in Oracle 10g noch
vorhanden ist
>
Es ist aber relativ langsam, eher für PL/SQL geeignet (die meisten
Funktionen arbeiten mit out Parametern) und es implementiert
reguläre Ausdrücke nicht vollständig
>
In SQL verwendbar ist z.B. die Funktion AMATCH, die ab einer
anzugegebenden Position in einem String zu Suchen beginnt
select count(*) from my_all_objects
where owa_pattern.amatch(object_name,1,'A') > 0 ;
COUNT(*)
---------16256
Oracle 10g: Reguläre Ausdrücke
10
© 2004
DAS OWA_PATTERN Package (1)
>
Die Performance ist aber wie erwähnt nicht umwerfend
select count(*) from my_all_objects
where owa_pattern.amatch(object_name,1,'A') >0 ;
COUNT(*)
---------16256
Elapsed: 00:00:15.66
select count(*) from my_all_objects
where regexp_like(object_name,'^A') ;
COUNT(*)
---------16256
Elapsed: 00:00:00.58
>
Wenn man aber ein Problem mit RegExp lösen muss, dann ist es
zumindest eine Lösungsmöglichkeit
Oracle 10g: Reguläre Ausdrücke
11
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance
>
Fazit
12
© 2004
Reguläre Ausdrücke ab Oracle 10g
>
Oracle unterstüzt reguläre Expressions über 4 Funktionen, die in SQL und
PL/SQL verwendet werden können (Extended Regular Expressions nach IEEE
1003.1)
>
Als Input String sind alle Character Datentypen erlaubt ausser LONG
>
REGEXP_LIKE (string, pattern [, param]): BOOLEAN
» Pattern darf maximal 512 Bytes gross sein
>
REGEXP_INSTR (string, pattern [, pos
[, occurrence [, ret_opt [, param]]]]): Number
>
REGEXP_SUBSTR ((string, pattern [, pos
[, occurrence [, param]]]]): String
>
REGEXP_REPLACE ((string, pattern [, repl_string [, pos
[, occurrence [, param]]]]): String
>
Parameter: i=case insensitive, c=case sensitive, n=. matched Newline, m=^/$
matchen Anfang/Ende von Zeilen, nicht des Strings
Oracle 10g: Reguläre Ausdrücke
13
© 2004
NLS Unterstützung
>
Die NLS Unterstützung ist sehr umfassend
>
'.' matched immer auf ein Zeichen, egal aus wievielen Bytes es
besteht
>
Zeichenklassen passen sich an den verwendeten Zeichensatz an,
so enthält [:digit:] eventuell zusätzlich Arabisch-Indische Ziffern
٠, ١, ٢ bis ٩ usw.
>
[[=i=]] matched i, ï, í usw.
>
NLS_SORT Setting beeinflusst ob zwei Zeichen gleich sind oder
nicht
>
Die Reguläre Expression wird bei Bedarf in das Character Set des
Suchstrings konvertiert
Oracle 10g: Reguläre Ausdrücke
14
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance Aspekte
>
Fazit
15
© 2004
Check Constraint mit REGEXP_LIKE
>
Eignet sich ausgezeichnet als Check-Condition auf Tabellen
>
Beispiel: Validierung einer Artikel-Nummer
» Format x99.999.999
» x = Grossbuchstabe zwischen A und F
» 9 = Zahl
CREATE TABLE parts
(partno VARCHAR2(11) NOT NULL
CONSTRAINT check_part# CHECK (regexp_like(partno,
'[A-F][[:digit:]]{2}\.[[:digit:]]{3}\.[[:digit:]]{3}'))
)
Oracle 10g: Reguläre Ausdrücke
16
© 2004
Suchen mit REGEXP_LIKE
>
Test in der WHERE Bedingung, ob regulärer Ausdruck
eingehalten wird
>
z.B. ob E-Mail-Adressen @ enthalten und mit .com oder .de
enden
SQL> SELECT address
2 FROM email
3 WHERE regexp_like (address, '.*@.*\.(com|de)');
ADDRESS
[email protected]
[email protected]
[email protected]
Oracle 10g: Reguläre Ausdrücke
17
© 2004
Ersetzen mit REGEXP_REPLACE (1)
von
[email protected]
[email protected]
nach
[email protected]
[email protected]
SELECT substr(address,
instr (address, '.') + 1,
instr (address, '@') - instr (address, '.') - 1
) || '.'
|| substr (address, 1, instr (address, '.') - 1)
|| substr (address, instr (address, '@'))
FROM email
>
In Oracle 10g sehr einfach mit Back References:
SELECT address,
regexp_replace (address, '(.*)\.(.*)@(.*)', '\2.\1@\3')
FROM email
Oracle 10g: Reguläre Ausdrücke
18
© 2004
?
Ersetzen mit REGEXP_REPLACE (2)
>
Ein etwas komplexerer Ausdruck
» Es ist nicht sicher, ob zwischen Name und Vorname wirklich ein "."
vorkommt, dieser soll aber nach der Reformatierung vorhanden sein
SQL> SELECT address,
2
regexp_replace (address,
3
'([[:alnum:]]+)\.?([[:upper:]])(.*)@(.*)',
4
'\2\3.\1@\4'
5
) adress_neu
6
FROM email;
ADDRESS
[email protected]
[email protected]
[email protected]
Oracle 10g: Reguläre Ausdrücke
19
ADRESS_NEU
[email protected]
[email protected]
[email protected]
© 2004
Ersetzen: Auf der Wunschliste…
>
Das wäre schön…
>
Aus 'Meine Telefonnummer ist 987 65 43' würde durch
update phone
set nr_text = '+411\1' -- funktioniert nicht!
where regexp_like(nr_text, '([[:digit:]]{7})')
eine korrekte Telefonnummer: +4119876543
Oracle 10g: Reguläre Ausdrücke
20
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance Aspekte
>
Fazit
21
© 2004
Telefonnummern-Check und Formatierung (1)
>
Gegeben sei folgende Tabelle mit Telefonnummern von Kunden:
Telefonnummer
>
1
01/987-6540
2
01-98'76'541
3
01.98.76.52
4
+41 1 987 65 43
5
01 / 987 65 44
6
+41 / (0)1 987 6545
7
+41 / 52 987 6546
Wir wollen nun zum einen nur die korrekten Zürcher
Telefonnummern daraus selektieren und zum andern diese
formatiert in internationaler Schreibweise ausgeben
Oracle 10g: Reguläre Ausdrücke
22
© 2004
Telefonnummern-Check und Formatierung (2)
>
>
Was ist eine Zürcher Telefonnummer? Sie hat die Vorwahl 01 und
hat 7 Ziffern
Das Ziel ist also diese Ausgabe:
Telefonnummer
>
1
+4119876540
2
+4119876541
3
+4119876543
4
+4119876544
5
+4119876545
Demo…
Oracle 10g: Reguläre Ausdrücke
23
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance Aspekte
>
Fazit
24
© 2004
Bemerkungen zur Performance
>
Reguläre Ausdrücke benutzen keine Indizes, jedes regexp_like
etc. führt also normalerweise einen Full Table Scan durch
>
Sollte ein regulärer Ausdruck häufig benutzt werden, kann man
aber darauf einen Function Based Index (FBI) anlegen. Dadurch
können regexp Abfragen sehr performant werden
>
LIKE ist in der Regel schneller:
select count(*) from my_all_objects where
regexp_like(object_name,'^A') ;
...
Elapsed: 00:00:00.58
select count(*) from my_all_objects where object_name like
'A%';
...
Elapsed: 00:00:00.02
Oracle 10g: Reguläre Ausdrücke
25
© 2004
Reguläre Ausdrücke in Oracle 10g
>
Agenda
Know-how.
Wir wissen wie.
Oracle 10g: Reguläre Ausdrücke
>
Grundlagen
>
Vor Oracle 10g
>
Ab Oracle 10g
>
Check/Suchen/Ersetzen
>
Ein komplexeres Beispiel
>
Performance
>
Fazit
26
© 2004
Regular Expressions: Kernaussagen…
>
>
Reguläre Ausdrücke sind extrem
mächtig und ermöglichen Lösungen,
die sonst sehr viel komplizierter
und/oder in PL/SQL implementiert
werden müssten
>
Dokumentation ist das A und O.
Ansonsten versteht ein Aussenstehender den Ausdruck nicht (und nach ein
paar Wochen auch der Autor nicht
mehr ☺)
>
Dort wo man schnell mit LIKE zum
Ziel kommt, sollte man weiterhin LIKE
benutzen: Es ist ist performanter
der Trivadis
Im Kern geht
es um Daten.
Oracle 10g: Reguläre Ausdrücke
27
© 2004
Herunterladen