Was ist neu in SQL:2016


Im Dezember 2016 hat ISO eine neue Version des internationalen SQL-Standards herausgebracht (ISO/IEC 9075:2016). Sie ersetzt die vorherige Version von 2011.

Dieser Artikel gibt einen kurzen Überblick über die neuen SQL Funktionen. Genauer gesagt behandelt dieser Artikel nur die Neuerungen in Teil 2 des Standards (SQL/Foundation) – das ist der Hauptteil des Standards.

Weiters zeigt dieser Artikel die Verfügbarkeit der neuen Funktionen in sechs gängigen Datenbaken. Die entsprechenden Abbildungen – siehe unten – spiegeln jedoch nur die Verfügbarkeit der Funktionen, wie sie der SQL-Standard beschreibt, wieder. Ein X in der Zeile JSON bedeutet also nicht, dass diese Datenbank keine JSON-Unterstützung hat. Es bedeutet lediglich, dass die im Standard beschriebenen Funktionen nicht unterstützt werden. Tatsächlich kann jede der sechs Datenbanken mit JSON umgehen – aber jeder auf andere Weise.0

Bevor wir uns die neuen Funktionen ansehen, noch ein paar Statistiken: Teil 2 des SQL-Standards hat mit 1732 Seiten um 260 Seiten (~18%) mehr als der Voränger. Es wurden 44 neue optionale Funktionen (+14%) eingeführt. Und diese wären…

Zeilenmustererkennung

Zeilenmustererkennung identifiziert Gruppen von Zeilen, deren Abfolge einem Muster entspricht. Zur Beschreibung des Musters wird ein regulärer Ausdruck verwendet.. Zeilengruppen, die einem Muster entsprechen, können gefiltert, gruppiert und aggregiert werden.

Die Hauptanwendung der Zeilenmustererkennung ist Analyse von Zeitreihen. Da die neue match_recognize-Klausel jedoch Funktionen von where, group by, having und over vereint, ist sie auch bei vielen anderen Problemen nützlich.

Im März habe ich einen Vortrag zur Zeilenmustererkennung gehalten. Darin werden einige Beispiele in zwei Umsetzunsvarianten verglichen: einmal mit, und einmal ohne die neue match_recognize-Klausel. Die Beispiele zeigen sowohl typische, als auch atypische Anwendungen:

  • Zusammenhängende Ereignisse: Sitzungen in einem Web-Log identifizieren und wie man dabei Unterbrechungen toleriert.

  • Top-N pro Gruppe (kann schneller als Window-Funktionen sein!)

  • Zeitintervalle: Löcher finden (Terminvergabe)

  • Zeitintervalle: Löcher füllen (neue Zeilen generieren)

Die Folien zum Vortrag sind hier.

Weiterführende Informationen gibte es auch im technischen Report “Row Pattern Recognition in SQL” (ISO/IEC TR 19075-5:2016) (gratis download bei ISO).

JSON

Seit nunmehr 18 Jahren unterstützt SQL Arrays, Multisets (verschachtelte Tabellen) und zusammengesetzte Typen (Objekte). In 2003 wurde ein eigener XML-Typ eingeführt. Jetzt gibt es auch JSON-Unterstützung.

Im Folgenden werden die wichtigsten Aspekte der neuen JSON-Unterstützung kurz erklärt. Weitere Details sind im technischen Report von ISO.

Kein nativer JSON-Typ

Obwohl sich XML und JSON etwas ähneln – sie sind Dokumente mit verschachtelten Strukturen – ist die Integration in SQL sehr unterschiedlich. Der auffälligste Unterschied ist, dass der Standard im Gegensatz zu XML keinen nativen JSON-Typ einführt. Stattdessen verwendet der Standard Strings, um JSON-Daten zu speichern.

Das beutet aber nicht, dass Datenbankhersteller keinen JSON-Typ bereitstellen dürfen. Der Standard definiert lediglich eine Reihe von Funktionen, die Strings als JSON-Daten interpretieren. Datenbanken mit standardkonformer JSON-Unterstützung müssen diese String-Funktionen bereitstellen. Datenbanken können dennoch einen JSON-Typen mit den entsprechenden Funktionen anbieten. Sie können sogar die Standardfunktionen für ihren JSON-Typen bereitstellen.

Die einzig unangenehme Konsequenz, Strings für JSON-Daten zu verwenden, ist die Fehlerbehandlung.1 Gäbe es einen JSON-Typ, könnten Parsingfehler nur bei der Typenumwandlung (cast) auftreten. Stattdessen definiert der Standard eine on error-Klausel für alle Funktionen, die einen String als JSON-Daten interpretieren. Mit dieser Klausel kann man das Verhalten bei fehlerhaften JSON-Daten steuern:

json_value(json, '$.id' null on error)

Die Voreinstellung ist error or error. Der String '$.id' ist ein JSON-Pfad.

Natürlich ist es trotzdem möglich, eine Tabellenspalte anzulegen, die nur gültige JSON-Daten annimmt:

CREATE TABLE … (
   jcol CLOB CHECK (jcol IS JSON)
)

Der Check-Constraint verwendet das neue is json-Prädikat, um zu prüfen, ob der String gültige JSON-Daten enthält. Das is json-Prädikat kann auch auf spezielle JSON-Untertypen prüfen und ist damit flexibler als ein einzelner Datentyp für alle JSON-Daten:

<expr> is [not] json [ value | array | object | scalar ]

JSON Formate

Der SQL-Standard erlaubt es, Datenbanken mehrere JSON-Formate anzubieten. Das in RFC 7159 beschriebene Format muss als Voreinstellung unterstützt werden.

Alle Funktionen, die JSON-Daten lesen oder erzeugen, akzeptieren die optionale format-Klausel (default: format json). Datenbanken können auch syntaktisch völlig unterschiedliche Formate anbieten (z. B. BSON).

JSON-Daten erzeugen

Der Standard definiert die folgenden Funktionen zum erstellen von JSON-Strukturen:

json_object([key] <expr> value <expression> [,…])

Erzeugt ein JSON-Objekt. Die Attributnamen und -werte werden von den Schlüsselwörtern key (optional) und value eingeleitet:

json_object( key 'id'   value 1234
           ,     'name' value 'Markus')

Alternativ kann einen Doppelpunkt (:) zwischen Attributname und -wert verwenden:2

json_object( 'id': 1234
           , 'name': 'Markus')

Das Komma dient lediglich zum Auflisten mehrere Attribute (Key/Value-Paare). Das ist ein wesentlicher Unterschied zu den Funktionen json_object in MySQL und SQLite oder json_build_object in PostgreSQL: diese Benutzen das Komma auch zur Trennung des Attributnamens vom Wert.

json_array([<expr>[,…]])

Erzeugt ein JSON-Array mit den angegebenen Werten.

json_array(<query>)

Erzeugt aus dem Ergebnis der Abfrage ein JSON-Array. Die Abfrage muss genau eine Spalte liefern. Die Reihenfolge der Elemente kann mit der order by-Klausel in der Abfrage gesteuert werden.

json_arrayagg(<expr> [order by …])

Erzeugt ein JSON-Array aus den Werten einer Zeilengruppe (analog zu array_agg):

SELECT json_arrayagg(col [order by seq])
  FROM …
 GROUP BY x

Die optionale order by-Klausel3 ist in den Klammern – nicht wie bei listagg in einer within group-Klausel.

json_objectagg([key] <expr> value <expression>)

Erzeugt ein JSON-Objekt aus den Attributnamen und -werten aus einer Zeilengruppe. Dabei kommt dieselbe Syntax wie bei json_object zur Anwendung:

SELECT json_objectagg(k value v)
  FROM …
 GROUP BY x

Da JSON-Object ungeordnet sind, gibt es keine order by-Klausel.

Auf JSON-Elemente zugreifen

Die folgenden Funktionen nutzen die sogenannte SQL/JSON path language (siehe unten) um auf Teile eines JSON-Dokumentes zuzugreifen. Diese Funktionen interpretieren einen String als JSON-Dokument und akzeptieren daher die on error-Klausel.

json_exists(<json>, <path>)

Prüft ob der angegebene Pfad im JSON-Dokument existiert. Liefert true, false oder unknown und kann daher direkt in der where-Klausel genutzt werden:

WHERE json_exists(jcol, '$.name')
json_value(<json>, <path> [returning <type>])

Extrahiert einen skalaren JSON-Wert – also kein Objekt oder Array – und liefert ihn als nativen SQL-Wert. Die optionale returning-Klausel führt eine entsprechende Typenumwandlung durch. Ohne returning-Klausel liefert json_value einen String.

json_query(<json>, <path> …)

Extrahiert einen Teil eines JSON-Dokumentes und liefert ihn als JSON-String. Die Hauptunterschiede zu json_value sind: (1) json_query kann auf jeden JSON-Typ zugreifen; (2) json_query liefert immer einen String; (3) json_query kann mehrere Elemente aus einem JSON-Dokument extrahieren.

Aufgrund dieser Unterschiede gibt es zwei Spezialfälle:

Mehrere Treffer

Per Default liefert json_query (wie json_value) einen Fehler, wenn der JSON-Path mehrere Treffer hat. Die optionale with [ conditional | unconditional ] [array] wrapper-Klausel packt die Ergebnisse in ein JSON-Array und liefert alle Treffer.

JSON path bezeichnet einen String

Json_query liefert generell JSON-Daten. Wenn der JSON-Pfad einen einzelnen String trifft, ist das Ergebnis noch immer ein JSON-String: JSON-Sonderzeichen werden maskiert, der ganze String ist in Anführungszeichen. Die omit quotes [on scalar string]-Klausel liefert stattdessen die Rohdaten (wie json_value).

Letztendlich gibt es noch die Funktion json_table: Sie ist im Wesentlichen eine Tabellenfunktion, die in der from-Klausel verwendet wird.

json_table(<json>, <path> columns …)

Erzeugt aus den Daten eines JSON-Dokuments eine Tabelle. json_table führt keine neue Funktionalität ein, ist aber oft einfacher (und schneller) als die entsprechenden json_value-Aufrufe.4

In ISO’s technischem Report (Absatz 5.3.4) gibt es eine ausführliche Beschreibung dieser Funktion. Das folgende Beispiel dient lediglich als Vorgeschmack. Es übersetzt ein JSON-Object (Array mit zwei Objekten) in eine Tabelle:

[{id: 1, name: "Marvin"},
 {id: 2, name: "Arthur"}
]
SELECT jt.*
  FROM t
     , JSON_TABLE
       ( jcol
       , '$[*]'
         COLUMNS (id   NUMERIC      PATH '$.id',
                  name VARCHAR(255) PATH '$.name'
                 )
       ) jt

Die Funktion json_table erzeugt eine Zeile für jedes Element, das dem JSON-Pfad ($[*]) entspricht. Die columns-Klausel legt die Typen und Namen der Spalten fest und deklariert über einen weiteren JSON-Pfad (relativ zum Hauptpfad) den eigentlichen Wert.

idname
1Marvin
2Arthur

JSON-Pfade

Der SQL-Standard definiert eine Pfad-Sprache für JSON.5 Sie setzt zahlreiche Funktionen von ECMAscript um, ist aber weder ein Sub- noch ein Superset von ECMAscript.6

In der JSON-Pfad-Sprache steht das Dollarzeichen ($) das aktuelle Element, der Punkt (.) für einen Objekt-, und die eckige Klammer ([]) für einen Arrayzugriff. Die folgenden Beispiele verdeutlichen das:

$.name

Bezeichnet das Attribute name des aktuellen JSON-Objektes.

$[0]

Bezeichnet das erste Element des aktuellen JSON-Arrays.

$.events[last]

Bezeichnet das letzte Arrayelement des Attributes events des aktuellen JSON-Objektes.

$.events[0 to 4, last]

Bezeichnet die ersten fünf und das letzte Array-Element des Attributes events des aktuellen JSON-Objektes.

$.*

Bezeichnet alle Attribute des aktuellen JSON-Objektes.

JSON-Pfade unterstützen Filterausdrücke der Form ?(<Ausdruck>). In Filtern bezeichnet das At-Zeichen (@) das aktuelle Element.

$.* ?(@.type()=="number")

Bezeichnet alle Elemente vom Typ number.

$.events[*] ?⁠(exists(@.name))

Bezeichnet alle Arrayelemente des Attributes events, welche das Attribute name enthalten.

$?⁠(@.name starts with "Lorem")

Bezeichnet das aktuelle JSON-Element, wenn der Wert des Attributes name mit Lorem beginnt.

Weiters sind die folgenden Funktionen in Filtern zulässig: size() (Array-Größe), ceiling(), floor(), abs() und datetime() (zum Parsen – siehe unten).

SQL/JSON-Pfade arbeiten in zwei Modi: lax (Voreinstellung) oder strict. Der Modus kann am Begin des Pfades angegeben werden (z. B. 'strict $.name'). Im Modus strict löst jeder Fehler die Fehlerbehandlung aus (entsprechend der on error-Klausel). Das gilt für den Zugriff auf nicht vorhandene Attribute oder die Verwendung eines skalaren Wertes als Array oder Objekt.

Im Modus lax werden solche Fehler unterdrückt. Dazu werden skalare Werte nötigenfalls in ein Array gepackt oder ein Array ausgepackt, damit die Pfadangabe der Dokumentenstruktur entspricht. Im Modus lax kann man mit variablen Dokumentenstrukturen arbeiten, ohne den JSON-Pfad an jedes Dokument anpassen zu müssen.

Was fehlt in SQL/JSON

Der SQL-Standard stellt keine Funktionen zum Ändern von JSON-Daten zur Verfügung (wie zum Beispiel json_set von MySQL, PostgreSQL und SQLite oder json_modify von SQL Server). Ein update kann also immer nur das ganze JSON-Dokument ersetzen.

Hinweis in eigener Sache

Wenn Dir dieser Artikel gefällt, könnte mein Buch SQL Performance Explained oder mein Training auch etwas für Dich sein.

Zeitangaben formatieren und parsen

Das Formatieren und Parsen von Zeitangaben (Datum, Uhrzeit) ist eine jener Lücken des SQL-Standards, die von so ziemlich jedem Hersteller gefüllt wurde. Natürlich hat sie jeder anders gefüllt. SQL:2016 hat nun Funktionen dafür definiert.

Der SQL-Standard verwendet dafür Format-Templates wie zum Beispiel 'YYYY-MM-DD'. Die folgende Tabelle zeigt die standardisierten Mnemonics – beachte die auffällige Ähnlichkeit zu den „datetime format models“ der Oracle-Datenbank.

MnemonicBedeutungextract field
YYYY | YYY | YY | YJahrYEAR
RRRR | RRGerundetes Jahr7
MMMonatMONTH
DDTag des MonatsDAY
DDDTag des Jahres
HH | HH12Stunde (Basis 12)
HH24Stunde (Basis 24)HOUR
MIMinuteMINUTE
SSSekunde der MinuteSECOND
SSSSSSekunde des Tages
FF1 | … | FF9Sekundenbruchteil(in SECOND)
A.M. | P.M.AM / PM
TZHZeitzone: StundeTIMEZONE_HOUR
TZMZeitzone: MinuteTIMEZONE_MINUTE

Beachte, dass extract (gutes, altes SQL-928) auch auf Zeitkomponenten zugreifen kann. Ich habe die entsprechenden extract Feldnamen daher in die Tabelle aufgenommen.

Diese Formattemplates können in der JSON-Pfad-Funktion datetime (siehe oben) und in einem cast verwendet werden:

CAST(<datetime> AS <char string type> [FORMAT <template>])
CAST(<char string> AS <datetime type> [FORMAT <template>])

Listagg

Listagg ist eine Ordered-Set-Funktion, die den Funktionen group_concat und string_agg entspricht, wie sie einige Datenbanken anbieten. Listagg transformiert Werte einer Zeilengruppe in einen String mit konfigurierbarem Separator.

Die minimale Syntax lautet:

LISTAGG(<expr>, <separator>) WITHIN GROUP(ORDER BY …)

Listagg hat eine optionale on overflow-Klausel, um das Verhalten bei einem Überlauf zu steuern:

LISTAGG(<expr>, <separator> ON OVERFLOW …)

Die Voreinstellung ist on overflow error. Mit on overflow truncate wird der Überlauf verhindert, indem nur so viele Elemente an den String gefügt werden, wie ohne Überlauf Platz haben. Weiters kann man mit der on overflow truncate-Klausel steuern, wie das Ergebnis bei einem Überlauf abgeschlossen wird:

ON OVERFLOW TRUNCATE [<filler>] WITH[OUT] COUNT

Der optionale <filler> wird als letztes Element an den String angefügt (default: ...). Mit with count kann man zusätzlich die Anzahl der verworfenen Elemente eingeklammert an das Endergebnis setzen lassen.

Ich habe einen detaillierten Artikel über listagg geschrieben. Bitte beachte auch die typensicheren Alternativen, die für viele Anwendungen die bessere Wahl sind.

Trigonometrische und logarithmische Funktionen

SQL:2016 führt trigonometrische Funktionen (sin, cos, tan, asin, acos, atan, sinh, cosh, tanh), eine allgemeine logarithmische Funktion (log(<basis>, <wert>)) und eine Kurzform für den Logarithmus zur Basis 10 ein (log10(<wert>)).

Der natürliche Logarithmus ln(<wert>) wurde bereits mit SQL:2003 eingeführt.

Polymorphe Tabellenfunktionen

SQL Tabellenfunktionen – eingeführt mit SQL:2003 – sind Funktionen, die eine Tabelle als Ergebnis liefern. Tabellenfunktionen müssen die Namen und Typen der Ergebnisspalten – den sogenannten Zeilentyp – in der Deklaration festlegen:

CREATE FUNCTION <name> (<parameters>)
       RETURNS TABLE (c1 NUMERIC(10,2), c2 TIMESTAMP)
   ...

Diese Funktion liefert also eine Tabelle mit zwei Spalten: c1 und c2 mit dem jeweils entsprechenden Typen.

Nach dem Anlegen können Tabellenfunktionen in der from und join-Klausel verwendet werden.9

Prominente Beispiele für Tabellenfunktionen sind:

SQL:2016 führt polymorphe Tabellenfunktionen (PTF) ein: Diese müssen den Ergebnistyp nicht vorab festlegen. Stattdessen können sie eine describe component procedure bereitstellen, die den Ergebnistyp zur Laufzeit festlegt. Weder der Autor der PTF, noch der Nutzer müssen die Spalten Typen oder Namen vorweg festlegen.

Die in SQL:2016 beschriebenen PTFs werden derzeit von keiner der getesteten Datenbanken unterstützt.10 Interessierte Leser sei der technische Report “Polymorphic table functions in SQL” empfohlen. Unter anderem beschreibt der Report die folgenden Beispiele:

  • CSVreader: Die Spalten werden von der ersten Zeile einer CSV-Datei festgelegt.

  • Pivot (eigentlich unpivot): macht aus Spalten Zeilen (z. B. phonetype, phonenumber).

  • TopNplus: liefert die ersten N Zeilen und eine Weitere mit der Summe über die restlichen Zeilen.

Ich persönlich denke, dass man die Beispiele des Reports auch mit anderen SQL-Mitteln umsetzen könnte.11 Die Umsetzung der Funktion json_table als PTF wäre vielleicht ein interessantes Beispiel gewesen. Wie auch immer: die Beispiele im Report sind weniger dazu gedacht nützlich zu sein, als die Möglichkeiten zu zeigen.

Sonstige Neuerungen

Join … using akzeptiert nun die as-Klausel (F404):

FROM A
JOIN B USING (…) AS correlation_name

Der Typ decfloat[(<precision>)] wurde neu eingeführt (T076).

Benannte Argumente in Funktions- und Prodzeduraufrufen (name => value) sind nicht mehr auf call-Answeisungen beschränkt (T524).

Eine default-Klausel für Funktionen (T525) und inout-Argumente (T523).

Funktionstaxonomie: obsolete und neue Funktionen

Der Vollständigkeit halber: Teil ISO/IEC 9075-2:2016 führt keine neuen, zwingenden Funktionen ein.12

Die Funktion T581, “Regular expression substring function” wurde als veraltet (deprecated) markiert (“The functionality is essentially subsumed by Feature F844, “SUBSTRING_REGEX”"13). Beachte, dass die Funktion T141, “SIMILAR predicate” bereits seit SQL:2011 als veraltet gilt.14

Die folgende Tabelle zeigt die neuen, optionale Funktionen (im Vergleich zu 2011).

Feature IDFeature Name
B200Polymorphic table functions
B201More than one PTF generic table parameter
B202PTF Copartitioning
B203More than one copartition specification
B204PRUNE WHEN EMPTY
B205Pass-through columns
B206PTF descriptor parameters
B207Cross products of partitionings
B208PTF component procedure interface
B209PTF extended names
F404Range variable for common column names
R010Row pattern recognition: FROM clause
R020Row pattern recognition: WINDOW clause
R030Row pattern recognition: full aggregate support
T076DECFLOAT data type
T523Default values for INOUT parameters of SQL-invoked procedures
T524Named arguments in routine invocations other than a CALL statement
T525Default values for parameters of SQL-invoked functions
T622Trigonometric functions
T623General logarithm functions
T624Common logarithm functions
T625LISTAGG
T811Basic SQL/JSON constructor functions
T812SQL/JSON: JSON_OBJECTAGG
T813SQL/JSON: JSON_ARRAYAGG with ORDER BY
T814Colon in JSON_OBJECT or JSON_OBJECTAGG
T821Basic SQL/JSON query operators
T822SQL/JSON: IS JSON WITH UNIQUE KEYS predicate
T823SQL/JSON: PASSING clause
T824JSON_TABLE: specific PLAN clause
T825SQL/JSON: ON EMPTY and ON ERROR clauses
T826General value expression in ON ERROR or ON EMPTY clauses
T827JSON_TABLE: sibling NESTED COLUMNS clauses
T828JSON_QUERY
T830Enforcing unique keys in SQL/JSON constructor functions
T831SQL/JSON path language: strict mode
T832SQL/JSON path language: item method
T833SQL/JSON path language: multiple subscripts
T834SQL/JSON path language: wildcard member accessor
T835SQL/JSON path language: filter expressions
T836SQL/JSON path language: starts with predicate
T837SQL/JSON path language: regex_like predicate
T838JSON_TABLE: PLAN DEFAULT clause
T839Formatted cast of datetimes to/from character strings

Über den Autor

Foto von Markus Winand

Markus Winand lehrt effizientes SQL – inhouse und online. Er minimiert die Entwicklungszeit durch modernes SQL und optimiert die Laufzeit durch schlaue Indizierung – dazu hat er auch das Buch SQL Performance Explained veröffentlicht.

Kaufen Sie sein Buch bei Amazon

Titelbild von „SQL Performance Explained“: Eichhörnchen läuft durchs Grass

Die Essenz: SQL-Tuning auf 200 Seiten

Bei Amazon kaufen
(Taschenbuch)

Taschenbuch und PDF auch auf Markus' Webseite erhältlich.

Holen Sie sich Markus

…für ein Training ins Büro.

Sein beliebtes Training stimmt Entwickler auf SQL Performance ein.

Erfahren Sie mehr»

Fußnoten

  1. Ohne Zweifel ist die “driver-based solution” von IBM DB2 der standard JSON-Funktionalität nicht im entferntesten ähnlich.

  2. Performance kann natürlich auch eine sehr unangenehme Konsequenz sein – auch wenn ich glaube, dass eine gute Umsetzung die Auswirkungen minimieren kann.

  3. Optionale Funktion T814 — Colon in JSON_OBJECT or JSON_OBJECTAGG

  4. Optional feature T813 — SQL/JSON: JSON_ARRAYAGG with ORDER BY.

  5. Noch wichtiger: json_table kann mehrere Zeilen erzeugen. Das kann man zwar auch mit anderen Mittel erreichen, es wird dann aber sehr mühsam.

  6. Da es für JSON-Pfade keinen anderen etablierten internationalen Standard gibt, definiert der SQL-Standard die Sprache selbst.

  7. TR 19075-6:2017 §6.1

  8. Beim parsen kann RR andere Regeln zum füllen der fehlenden Ziffern haben als YY (SQL:2016-2: §9.43, General Rule 6biv)

  9. Intermediate SQL-92, jetzt Teil von T052.

  10. Eine syntaktische Ergänzung ist nötig: table(). Lateral wird ebenfalls oft im Zusammenspiel mit Tabellenfunktionen benutzt.

  11. Obwohl die Oracle-Datenbank sehr entspannt mit der create function syntax umgeht: sie akzeptiert die CVSreader deklaration aus dem technischen Report. Tatsächlich akzeptiert die Oracle-Datenbank alles, was der returns table-Klausel folgt.

  12. CVSreader: SQL/MED kommt mir in den Sinn (hat aber keine Polymorphie). Für eine CSV-Leser könnten Arrays aber eine ausreichende Lösung sein.

    Unpivot: verwende join lateral (values (phtype1, phonenumber1), (phtype2, phonenumber2)) (mit einer on-Klausel, um null zu filtern).

    TopNplus: verwende match_recognize (wie in den Folien aufgezeigt).

  13. Basierend auf der Nummerierung der zweingenden Features in der Tabelle “Feature taxonomy and definition for mandatory features” in 9075-2:2011 vs. 9075-2:2016.

  14. SQL:2016-2 Annex D.

  15. SQL:2016 ergänzt “the use of <similar predicate part 2> in <case expression>”.

„modern SQL“ von Markus Winand ist unter einer Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License lizenziert.
Impressum | Kontakt | KEINE GEWÄHR | Handelsmarken | Datenschutz | CC-BY-NC-ND 3.0 Lizenz