Upload
hoangnhan
View
218
Download
0
Embed Size (px)
Citation preview
Reguläre Ausdrücke in Oracle 10g –Waren Queries bis jetzt irregulär?
Dr. Martin WunderliTrivadis AG
www.trivadis.com
Oracle 10g: Reguläre Ausdrücke 2 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 3 © 2004
Wer suchet, der findet
> Um in einer gegebenen Menge von Datensätzen zu suchen, gibt esverschiedene Methoden
> Den Weg der Suche beschreiben, d.h. prozedural. Beispielsweise in derForm von Schleifen und IF-Anweisungen, in der Form von Navigationsanweisungen bei Netzwerkdatenbanken usw.
> Das Ergebnis der Suche beschreiben, d.h. deklarativ. Unter diese Rubrikfallen 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 vieleZeichen (%) 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 eineRegular Expression/einen regulären Ausdruck
Oracle 10g: Reguläre Ausdrücke 4 © 2004
Theoretischer Hintergrund
> Reguläre Ausdrücke sind bekannt aus derBerechenbarkeitstheorie, einem Teilgebiet der theoretischenInformatik
> Reguläre Ausdrücke bilden eine Famile von kompakten formalenSprachen. Mit einer solchen Sprache lassen sich Mengen von Zeichenketten beschreiben
> Beispiel: Unter der Annahme, dass der Punkt . für ein beliebigesZeichen steht, definiert der reguläre Ausdruck a.b die Mengeder 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 5 © 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 sehrkomplexe 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 derVerwendung von regulären Ausdrücken immer den Aufbau in Einzelschritten dokumentieren
Oracle 10g: Reguläre Ausdrücke 6 © 2004
Die wichtigsten Symbole in regulären Ausdrücken
> Sollen Sonderzeichen wie ( und [ nicht zur Bildung von Symbolen verwendetwerden, muss man sie explizit mit \ markieren
Verankern die Regular Expression am Beginn/Ende einer Zeile/des zudurchsuchenden Strings
^/$
Entweder die Zeichenkette xx oder die Zeichenkette yyxx|yy
Referenzierung einer Gruppierung, hier der zweiten\2
Gruppierung, welche z.B. wiederholt oder ersetzt werden kann( )
Zeichenklasse, hier alle alphanummerischen Zeichen[:alnum:]
Genau ein Zeichen aus der Menge 0-9 und A-F[0-9A-F]
Genau 1 beliebiges Zeichen.
3 bis 6-malige Wiederholung des vorangehenden Ausdrucks{3,6}
Genau 4-malige Wiederholung des vorangehenden Ausdrucks{4}
0 oder 1-malige Wiederholung des vorangehenden Ausdrucks?
0/1 bis n-malige Wiederholung des vorangehenden Ausdrucks*/+
BedeutungSymbol
Oracle 10g: Reguläre Ausdrücke 7 © 2004
Einfache Beispiele für reguläre Ausdrücke
> Auf den Ausdruck bericht passt genau eine Zeichenkette, nämlichbericht
> Auf den Ausdruck bericht.. passt bericht01, bericht0a, bericht15 aber nicht bericht1
> Auf den Ausdruck bericht[0-8] passt bericht8 aber nichtbericht9
> Auf den Ausdruck bericht[[:digit:]]\.(txt|doc) passtbericht1.txt und bericht2.doc, nicht aber bericht3-doc
> Auf den Ausdruck bericht[A-Z]\.doc passt berichtA.doc aberauch gegenberichtA.doc und berichtB.document
> Auf den Ausdruck ^bericht[A-Z]\.doc$ passen gegenberichtA.docund berichtB.document aber nicht
Oracle 10g: Reguläre Ausdrücke 8 © 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 9 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 10 © 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 nochvorhanden ist
> Es ist aber relativ langsam, eher für PL/SQL geeignet (die meistenFunktionen arbeiten mit out Parametern) und es implementiertreguläre Ausdrücke nicht vollständig
> In SQL verwendbar ist z.B. die Funktion AMATCH, die ab eineranzugegebenden Position in einem String zu Suchen beginnt
select count(*) from my_all_objectswhere owa_pattern.amatch(object_name,1,'A') > 0 ;
COUNT(*)----------
16256
Oracle 10g: Reguläre Ausdrücke 11 © 2004
DAS OWA_PATTERN Package (1)
> Die Performance ist aber wie erwähnt nicht umwerfend
> Wenn man aber ein Problem mit RegExp lösen muss, dann ist eszumindest eine Lösungsmöglichkeit
select count(*) from my_all_objectswhere owa_pattern.amatch(object_name,1,'A') >0 ;
COUNT(*)----------
16256
Elapsed: 00:00:15.66
select count(*) from my_all_objectswhere regexp_like(object_name,'^A') ;
COUNT(*)----------
16256
Elapsed: 00:00:00.58
Oracle 10g: Reguläre Ausdrücke 12 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 13 © 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 14 © 2004
NLS Unterstützung
> Die NLS Unterstützung ist sehr umfassend
> '.' matched immer auf ein Zeichen, egal aus wievielen Bytes esbesteht
> 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 odernicht
> Die Reguläre Expression wird bei Bedarf in das Character Set des Suchstrings konvertiert
Oracle 10g: Reguläre Ausdrücke 15 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance Aspekte
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 16 © 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 NULLCONSTRAINT check_part# CHECK (regexp_like(partno,'[A-F][[:digit:]]{2}\.[[:digit:]]{3}\.[[:digit:]]{3}'))
)
Oracle 10g: Reguläre Ausdrücke 17 © 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 address2 FROM email3 WHERE regexp_like (address, '.*@.*\.(com|de)');
ADDRESS------------------------------Sven.Vetter@[email protected]@firma.de
Oracle 10g: Reguläre Ausdrücke 18 © 2004
Ersetzen mit REGEXP_REPLACE (1)
von [email protected] [email protected]@trivadis.com [email protected] ?
> In Oracle 10g sehr einfach mit Back References:SELECT address,
regexp_replace (address, '(.*)\.(.*)@(.*)', '\2.\1@\3')FROM email
SELECT substr(address,instr (address, '.') + 1,instr (address, '@') - instr (address, '.') - 1) || '.'
|| substr (address, 1, instr (address, '.') - 1)|| substr (address, instr (address, '@'))
FROM email
Oracle 10g: Reguläre Ausdrücke 19 © 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_neu6 FROM email;
ADDRESS ADRESS_NEU------------------------------ [email protected] [email protected]@trivadis.com [email protected]@firma.com [email protected]
Oracle 10g: Reguläre Ausdrücke 20 © 2004
Ersetzen: Auf der Wunschliste…
> Das wäre schön…
> Aus 'Meine Telefonnummer ist 987 65 43' würde durch
eine korrekte Telefonnummer: +4119876543
update phoneset nr_text = '+411\1' -- funktioniert nicht!where regexp_like(nr_text, '([[:digit:]]{7})')
Oracle 10g: Reguläre Ausdrücke 21 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance Aspekte
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 22 © 2004
Telefonnummern-Check und Formatierung (1)
> Gegeben sei folgende Tabelle mit Telefonnummern von Kunden:
> Wir wollen nun zum einen nur die korrekten ZürcherTelefonnummern daraus selektieren und zum andern dieseformatiert in internationaler Schreibweise ausgeben
+41 / 52 987 65467
+41 / (0)1 987 65456
01 / 987 65 445
+41 1 987 65 434
01.98.76.523
01-98'76'5412
01/987-65401
Telefonnummer
Oracle 10g: Reguläre Ausdrücke 23 © 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:
> Demo…
+41198765455
+41198765444
+41198765433
+41198765412
+41198765401
Telefonnummer
Oracle 10g: Reguläre Ausdrücke 24 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance Aspekte
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 25 © 2004
Bemerkungen zur Performance
> Reguläre Ausdrücke benutzen keine Indizes, jedes regexp_likeetc. 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. Dadurchkö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 26 © 2004
Reguläre Ausdrücke in Oracle 10g
> Grundlagen
> Vor Oracle 10g
> Ab Oracle 10g
> Check/Suchen/Ersetzen
> Ein komplexeres Beispiel
> Performance
> Fazit
Know-how. Wir wissen wie.
> Agenda
Oracle 10g: Reguläre Ausdrücke 27 © 2004
Regular Expressions: Kernaussagen…
Im Kern geht es um Daten.
> der Trivadis
> 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 Aussenstehen-der 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