Ich weiß, dass dies bis zu einem gewissen Grad mit PHP und MYSQL beantwortet wurde, aber ich habe mich gefragt, ob mir jemand den einfachsten Ansatz zum Aufteilen einer Zeichenfolge (durch Kommas getrennt) in mehrere Zeilen in Oracle 10g (vorzugsweise) und 11g beibringen kann.
Die Tabelle lautet wie folgt:
Name | Project | Error
108 test Err1, Err2, Err3
109 test2 Err1
Ich möchte Folgendes erstellen:
Name | Project | Error
108 Test Err1
108 Test Err2
108 Test Err3
109 Test2 Err1
Ich habe einige mögliche Lösungen rund um den Stapel gesehen, die jedoch nur eine einzige Spalte ausmachten (die durch Kommas getrennte Zeichenfolge). Jede Hilfe wäre sehr dankbar.
REGEXP
,XMLTABLE
undMODEL
Klausel findet Split Komma getrennte Zeichenfolge in einer Tabelle mit Oracle SQLAntworten:
Dies kann ein verbesserter Weg sein (auch mit Regexp und Connect by):
BEARBEITEN : Hier ist eine einfache (wie in "nicht in der Tiefe") Erklärung der Abfrage.
length (regexp_replace(t.error, '[^,]+')) + 1
wird verwendetregexp_replace
, um alles zu löschen, was nicht das Trennzeichen ist (in diesem Fall Komma), und umlength +1
zu ermitteln, wie viele Elemente (Fehler) vorhanden sind.Der
select level from dual connect by level <= (...)
verwendet eine hierarchische Abfrage , um eine Spalte mit einer zunehmenden Anzahl gefundener Übereinstimmungen von 1 bis zur Gesamtzahl der Fehler zu erstellen.Vorschau:
table(cast(multiset(.....) as sys.OdciNumberList))
macht einige Casting von Orakeltypen.cast(multiset(.....)) as sys.OdciNumberList
transformiert mehrere Sammlungen (eine Sammlung für jede Zeile im Originaldatensatz) in eine einzige Sammlung von Zahlen, OdciNumberList.table()
Funktion wandelt eine Sammlung in eine Ergebnismenge um.FROM
Ohne Join wird ein Cross-Join zwischen Ihrem Dataset und dem Multiset erstellt. Infolgedessen wird eine Zeile im Datensatz mit 4 Übereinstimmungen viermal wiederholt (mit einer zunehmenden Zahl in der Spalte "column_value").Vorschau:
trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value))
verwendet den Parametercolumn_value
als nth_appearance / ocurrence fürregexp_substr
.t.name, t.project
als Beispiel), um die Visualisierung zu vereinfachen.Einige Verweise auf Oracle-Dokumente:
quelle
'[^,]+'
zum Analysieren von Zeichenfolgen gibt nicht das richtige Element zurück, wenn die Liste ein Nullelement enthält. Weitere Informationen finden Sie hier: stackoverflow.com/questions/31464275/…regexp_count(t.error, ',')
anstelle von verwendenlength (regexp_replace(t.error, '[^,]+'))
, was eine weitere Leistungsverbesserung bringen kannreguläre Ausdrücke sind eine wunderbare Sache :)
quelle
Name
s verbunden ist, was sichtbar wird, wenn Sie entfernendistinct
. Leider fügtand Name = prior Name
das Hinzufügen zurconnect by
Klausel Ursachen hinzuORA-01436: CONNECT BY loop in user data
.ORA-01436
Fehler vermeiden, indem SieAND name = PRIOR name
(oder was auch immer der Primärschlüssel sein mag) undAND PRIOR SYS_GUID() IS NOT NULL
Es gibt einen großen Unterschied zwischen den beiden folgenden:
Wenn Sie die Zeilen nicht einschränken, erzeugt die CONNECT BY- Klausel mehrere Zeilen und liefert nicht die gewünschte Ausgabe.
Neben regulären Ausdrücken werden einige andere Alternativen verwendet:
Konfiguration
Verwenden von XMLTABLE :
Verwenden der MODEL- Klausel:
quelle
('"' || REPLACE(text, ',', '","') || '"')
Klammern geben muss und nicht entfernt werden können? Oracle-Dokumente ([ docs.oracle.com/database/121/SQLRF/functions268.htm ) sind mir nicht klar. Ist esXQuery_string
?Ein paar weitere Beispiele dafür:
Verwenden Sie möglicherweise auch DBMS_UTILITY.comma_to_table & table_to_comma: http://www.oracle-base.com/articles/9i/useful-procedures-and-functions-9i.php#DBMS_UTILITY.comma_to_table
quelle
comma_to_table()
nur mit Token funktioniert, die den Namenskonventionen für Datenbankobjekte von Oracle entsprechen. Es wird wie'123,456,789'
zum Beispiel auf eine Schnur geschleudert.Ich möchte einen anderen Ansatz mit einer PIPELINED-Tabellenfunktion vorschlagen. Es ähnelt etwas der Technik von XMLTABLE, außer dass Sie Ihre eigene benutzerdefinierte Funktion zum Teilen der Zeichenfolge bereitstellen:
Ergebnisse:
Das Problem bei dieser Art von Ansatz ist, dass der Optimierer häufig die Kardinalität der Tabellenfunktion nicht kennt und eine Vermutung anstellen muss. Dies kann möglicherweise schädlich für Ihre Ausführungspläne sein. Daher kann diese Lösung erweitert werden, um Ausführungsstatistiken für das Optimierungsprogramm bereitzustellen.
Sie können diese Optimierungsschätzung anzeigen, indem Sie einen EXPLAIN PLAN für die obige Abfrage ausführen:
Obwohl die Sammlung nur 3 Werte enthält, hat der Optimierer 8168 Zeilen dafür geschätzt (Standardwert). Dies mag zunächst irrelevant erscheinen, aber es kann für den Optimierer ausreichend sein, sich für einen suboptimalen Plan zu entscheiden.
Die Lösung besteht darin, die Optimierungserweiterungen zu verwenden, um Statistiken für die Sammlung bereitzustellen:
Testen des resultierenden Ausführungsplans:
Wie Sie sehen können, ist die Kardinalität im obigen Plan nicht mehr der geschätzte Wert von 8196. Es ist immer noch nicht korrekt, da wir eine Spalte anstelle eines Zeichenfolgenliteral an die Funktion übergeben.
In diesem speziellen Fall wäre eine gewisse Anpassung des Funktionscodes erforderlich, um eine genauere Schätzung vorzunehmen, aber ich denke, das Gesamtkonzept wird hier ziemlich genau erläutert.
Die in dieser Antwort verwendete str2tbl-Funktion wurde ursprünglich von Tom Kyte entwickelt: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:110612348061
Das Konzept der Zuordnung von Statistiken zu Objekttypen kann in diesem Artikel näher erläutert werden: http://www.oracle-developer.net/display.php?id=427
Die hier beschriebene Technik funktioniert in 10g +.
quelle
REGEXP_COUNT wurde erst in Oracle 11i hinzugefügt. Hier ist eine Oracle 10g-Lösung, die aus der Art-Lösung übernommen wurde.
quelle
Ausgehend von Oracle 12c Sie nutzen könnten
JSON_TABLE
undJSON_ARRAY
:Und fragen Sie:
Ausgabe:
db <> Geigen-Demo
quelle
Hier ist eine alternative Implementierung mit XMLTABLE, die das Casting in verschiedene Datentypen ermöglicht:
... oder wenn Ihre durch Trennzeichen getrennten Zeichenfolgen in einer oder mehreren Zeilen einer Tabelle gespeichert sind:
quelle
Ich möchte eine andere Methode hinzufügen. Dieser verwendet rekursive Abfragen, was ich in den anderen Antworten nicht gesehen habe. Es wird von Oracle seit 11gR2 unterstützt.
Es ist sehr flexibel mit dem spaltenden Charakter. Ändern Sie es einfach in den
INSTR
Anrufen.quelle
Ohne Connect by oder Regexp zu verwenden :
quelle
Ich hatte das gleiche Problem und xmltable half mir:
SELECT id, trim (COLUMN_VALUE) Text FROM t, xmltable (('"' || REPLACE (text, ',', '", "') || '"'))
quelle
In Oracle 11g und höher können Sie eine rekursive Unterabfrage und einfache Zeichenfolgenfunktionen verwenden (die möglicherweise schneller sind als reguläre Ausdrücke und korrelierte hierarchische Unterabfragen):
Oracle Setup :
Abfrage :
Ausgabe :
db <> hier fummeln
quelle
Ich hatte die Funktion DBMS_UTILITY.comma_to _table verwendet, um den Code wie folgt zu bearbeiten
Ich hatte meine eigenen Tabellen- und Spaltennamen verwendet
quelle
comma_to_table()
nur mit Token funktioniert, die den Namenskonventionen für Datenbankobjekte von Oracle entsprechen. Es wird wie'123,456,789'
zum Beispiel auf eine Schnur geschleudert.