2016-07-23 4 views
2

Angenommen, ich habe eine Zeichenfolge (varchar2) und ich möchte ein Leerzeichen hinzufügen, wo immer ich zwei aufeinanderfolgende a's habe. Also zum Beispiel: 'graanh' -> 'gra anh'.Oracle db: Wie Leerzeichen an bestimmten Positionen in Strings hinzugefügt werden

OK, dies ist trivial zu tun, entweder mit replace oder regexp_replace. Aber beide ersticken auf drei oder mehrere aufeinander folgende a's. Zum Beispiel:

SQL> select replace('aaaaa', 'aa', 'a a') from dual; 

REPLACE 
------- 
a aa aa 

SQL> select regexp_replace('aaaaa', 'aa', 'a a') from dual; 

REGEXP_ 
------- 
a aa aa 

Dies liegt daran, die Suche nach dem „next“ Auftreten des Übereinstimmungsmusters nach dem Ende der „vorherigen“ beginnt. Tatsächlich gibt regexp_count('aaaaa', 'aa') 2 zurück, nicht 4.

Das gewünschte Ergebnis ist 'aaaaa' -> 'a a a a a'. Das Problem ist, dass ich das Muster 'aa' nicht ersetzen möchte. Was ich ersetzen möchte, ist die leere Zeichenfolge BETWEEN a auf beiden Seiten der leeren Zeichenfolge. Die Beschreibung würde also etwa lauten: Finden Sie alle Vorkommen einer leeren Zeichenfolge mit einem Zeichen auf beiden Seiten, und ersetzen Sie diese leere Zeichenfolge durch ein Leerzeichen.

Kann dies mit String- oder Regexp-Funktionen gemacht werden? Bitte tun Sie nicht bieten Lösungen mit rekursiven Abfragen oder (der Horror!) PL/SQL-Verfahren; Ich weiß, dass sie gemacht werden können, aber ich bin interessiert, ob es eine "natürliche" Lösung gibt, ein Werkzeug, das genau für diese Frage existiert, die mir fehlt.

Worst Case, replace(replace('aaaaa', 'aa', 'a a'), 'aa', 'a a') wird den Trick tun. Ist dies der beste Fall?

Damit Sie nicht denken, dass dies eine seltsame Anforderung ist: Ich experimentiere mit verschiedenen Methoden zum Trennen von durch Komma getrennten Strings. Einige der Methoden haben eine sehr unangenehme Angewohnheit, NULL-Token innerhalb solcher Strings zu ignorieren (das heißt, aus zwei aufeinander folgenden Kommas erhält man keinen NULL, wie Sie sollten). Also, bevor Sie diese Methoden verwenden, müsste man die Eingabezeichenfolge analysieren und ein Leerzeichen oder die Zeichenfolge 'NULL' oder so etwas zwischen aufeinander folgenden Kommas hinzufügen. Natürlich wäre es besser, nach JEDEM Komma (und am Anfang der Zeichenkette) ein Leerzeichen einzufügen und nach dem Aufteilen in Token ein Leerzeichen vom Anfang jedes Zeichens zu entfernen. Aber das warf die Frage auf, die ich oben gestellt habe, und die meiner Meinung nach einen eigenen Verdienst hat.

Vielen Dank!

+0

Ha! Als ich diesen Beitrag als FYI fand, um eine Methode zum Parsen einer Zeichenfolge zu nennen, die Nullen erlaubt, habe ich bemerkt, dass du sie bearbeitet hast. :-) http://StackOverflow.com/a/31464699/2543416 –

+0

Was ist mit dem Bau eigener eingebaut? mit Java nicht PL/SQL natürlich? –

+0

@ J.Chomel - Ich könnte das tun (nachdem ich Java gelernt habe); Frage ist, wäre es effizienter als dieser doppelte Ruf zu ersetzen? Irgendwie vermute ich, dass die Kontextumschaltung teurer sein wird, als zweimal 'replace' aufzurufen. Darüber hinaus war mein Hauptzweck mit dieser Frage zu erfahren, ob es einige String-Funktionen oder Features oder Techniken gab, die mir fehlten. Es ist einige Monate später, ich habe mehr gelernt, und ich glaube, die Antwort auf diese allgemeinere Frage ist NEIN. Vielen Dank! – mathguy

Antwort

1

Wenn Sie wirklich PL/SQL den Horror und rekursive Abfragen unnatürlich finden, dann haben Sie wahrscheinlich mit replace(replace('aaaaa', 'aa', 'a a'), 'aa', 'a a') gehen, wie Sie bereits vorgeschlagen haben, wenn auch als „worst case“. Warum halten Sie dies für die schlimmsten Fall bleibt mir unklar.

+0

Um es klar zu stellen: Ich benutze immer rekursive Abfragen, und es gibt mindestens einen Fall, den ich kenne (den Algorithmus von Eratosthenes implementierend), wo PL/SQL viel besser funktioniert als alles andere, was in Plain-SQL möglich ist.Ich meinte für dieses Problem wäre ein rekursives CTE unnatürlich und PL/SQL unnötig (da es keine Möglichkeit gibt, eine einfachere/bessere Lösung als den "schlimmsten Fall", den ich bereits erwähnt habe, zuzulassen). Ich wollte einfach keine Lösungen mit FOR-Loops dafür sehen. Wenn Sie eine rekursive CTE- oder PL/SQL-Lösung einfacher als replace (replace()) vorschlagen können, schlagen Sie dies bitte vor. – mathguy

+0

Ich halte es für den "schlimmsten Fall" in dem Sinne, dass jede angebotene Lösung nicht schlechter sein sollte als der "schlimmste Fall". Der "beste Fall" wäre eine regexp-Lösung (oder eine ähnliche Lösung), die nach einem Muster sucht und es ermöglicht, ein Untermuster innerhalb dieses Musters zu ersetzen, wie ich in meinem Beitrag erklärt habe. Tut mir leid, wenn das nicht klar war, ich habe mein Bestes getan, um es zu erklären, aber vielleicht gescheitert. – mathguy

Verwandte Themen