JSON-Daten generieren
Mit SQL-Funktionen können Sie formatierte JSON-Daten aus relationalen Tabellen generieren.
Wir werden mit relationalen Daten arbeiten, um JSON zu generieren. Wir beginnen mit den Daten in zwei Tabellen. Eine enthält grundlegende Mitarbeiterdaten. Die andere enthält Kontoinformationen. Sie werden wie hier gezeigt erstellt und gefüllt.
create table empdata (id int,
last_name varchar(10),
first_name varchar(10),
office_number varchar(10),
work_phone varchar(20),
home_phone varchar(20));
create table emp_account (id int,
account varchar(20));
insert into empdata values (901, 'Doe', 'John', 'E-334', '555-7242', '555-3762');
insert into emp_account values (901, '36232'), (901, '73263');
insert into empdata values (902, 'Pan', 'Peter', 'E-216', '555-8925', null);
insert into emp_account values (902, '76232'), (902, '72963');
insert into empdata values (903, 'Jones', 'Mary', 'E-739', '555-4311', '555-6312');
insert into empdata values (904, 'Smith', 'Sally', null, null, null);
{"id":901, "name" : { "first":"John", "last":"Doe" }, "office" : "E-334",
"phones" : [ { "type":"home", "number":"555-3762" },
{ "type":"work", "number":"555-7242" } ],
"accounts" : [ { "number":"36232"}, { "number":"73263"}] }
{"id":902, "name" : { "first":"Peter", "last":"Pan" }, "office" : "E-216",
"phones" : [ { "type":"work", "number":"555-8925" } ],
"accounts" : [ { "number":"76232"}, {"number":"72963"}] }
{"id":903, "name" : { "first":"Mary", "last":"Jones" }, "office" : "E-739",
"phones" : [ { "type":"home", "number":"555-6312" },
{ "type":"work", "number":"555-4311" } ], }
{"id":904, "name" : { "first":"Sally", "last":"Smith" } }JSON-Basisobjekt erstellen
Beginnen Sie mit einem einfachen Beispiel, um zu sehen, wie einfach es ist, ein JSON-Basisobjekt zu generieren.
select json_object ('id' value id,
'name' value last_name,
'office' value office_number)
from empdata;
{"id":901,"name":"Doe","office":"E-334"}
{"id":902,"name":"Pan","office":"E-216"}
{"id":903,"name":"Jones","office":"E-739"}
{"id":904,"name":"Smith","office":null}select json_object ('id' value id,
'name' value last_name,
'office' value office_number
absent on null)
from empdata;Jetzt gibt es keinen office -Wert für 904.{"id":901,"name":"Doe","office":"E-334"}
{"id":902,"name":"Pan","office":"E-216"}
{"id":903,"name":"Jones","office":"E-739"}
{"id":904,"name":"Smith"}JSON-Objekte verschachteln
select json_object ('first' value first_name,
'last' value last_name)
from empdata;Das Ergebnis dieser Abfrage lautet wie folgt:{"first":"John","last":"Doe"}
{"first":"Peter","last":"Pan"}
{"first":"Mary","last":"Jones"}
{"first":"Sally","last":"Smith"}select json_object ('id' value id,
'name' value json_object ( 'first' value first_name,
'last' value last_name),
'office' value office_number
absent on null)
from empdata;{"id":901,"name":{"first":"John","last":"Doe"},"office":"E-334"}
{"id":902,"name":{"first":"Peter","last":"Pan"},"office":"E-216"}
{"id":903,"name":{"first":"Mary","last":"Jones"},"office":"E-739"}
{"id":904,"name":{"first":"Sally","last":"Smith"}}JSON-Array erstellen
select json_array
(case when home_phone is not null then
json_object('type' value 'home',
'number' value home_phone) end,
case when work_phone is not null then
json_object('type' value 'work',
'number' value work_phone) end
)
from empdata;Hier ist das Ergebnis. Die Ausgabe für jeden Eintrag wird über zwei Zeilen getrennt, um das vollständige Ergebnis anzuzeigen.["{\"type\":\"home\",\"number\":\"555-3762\"}",
"{\"type\":\"work\",\"number\":\"555-7242\"}"]
["{\"type\":\"work\",\"number\":\"555-8925\"}"]
["{\"type\":\"home\",\"number\":\"555-6312\"}",
"{\"type\":\"work\",\"number\":\"555-4311\"}"]
[]Dies ist ein wenig unerwartet. Warum sind all diese zusätzlichen \ Zeichen im Ergebnis? Dies zeigt den Unterschied zwischen der Verarbeitung normaler Zeichendaten und Zeichendaten, die bereits als JSON formatiert wurden. Wenn JSON_ARRAY (oder eine der JSON-Veröffentlichungsfunktionen) seine Argumente betrachtet, erkennt es, wenn das Argument das direkte Ergebnis einer anderen JSON-Funktion ist. Ist dies der Fall, wird die Zeichenfolge als bereits formatierte JSON-Daten interpretiert. Dies bedeutet, dass die Funktion keines der Sonderzeichen in der Zeichenfolge mit Escapezeichen maskiert. Wenn das Argument nicht das direkte Ergebnis einer JSON-Funktion ist, wird es als Nicht-JSON-Zeichendaten interpretiert und die Escapeverarbeitung für den Wert ausgeführt. Da in diesem Beispiel das JSON_OBJECT in einen CASE -Ausdruck eingebettet wurde, ist die Tatsache, dass die Zeichenfolge bereits formatiert war, nicht bekannt. Um diese unerwünschten Escapezeichenfolgen zu vermeiden, müssen Sie JSON_ARRAY explizit mitteilen, dass das Argument bereits JSON ist, indem Sie die Klausel FORMAT JSON verwenden.
select json_array
(case when home_phone is not null then
json_object('type' value 'home',
'number' value home_phone) end
format json,
case when work_phone is not null then
json_object('type' value 'work',
'number' value work_phone) end
format json)
from empdata;Das Ergebnis lautet wie folgt:[{"type":"home","number":"555-3762"},{"type":"work","number":"555-7242"}]
[{"type":"work","number":"555-8925"}]
[{"type":"home","number":"555-6312"},{"type":"work","number":"555-4311"}]
[]select json_object ('id' value id,
'name' value json_object ( 'first' value first_name,
'last' value last_name),
'office' value office_number,
'phones' value json_array
(case when home_phone is not null then
json_object('type' value 'home',
'number' value home_phone
) end format json,
case when work_phone is not null then
json_object('type' value 'work',
'number' value work_phone
) end format json)
absent on null)
from empdata;Dies gibt Folgendes zurück:{"id":901,"name":{"first":"John","last":"Doe"},"office":"E-334",
"phones":[{"type":"home","number":"555-3762"},{"type":"work","number":"555-7242"}]}
{"id":902,"name":{"first":"Peter","last":"Pan"},"office":"E-216",
"phones":[{"type":"work","number":"555-8925"}]}
{"id":903,"name":{"first":"Mary","last":"Jones"},"office":"E-739",
"phones":[{"type":"home","number":"555-6312"},{"type":"work","number":"555-4311"}]}
{"id":904,"name":{"first":"Sally","last":"Smith"},
"phones":[]}Array aus mehreren Datenzeilen erstellen
select json_array(json_object('number' value account))
from emp_account;Das Ergebnis dieser Abfrage lautet wie folgt:[{"number":"36232"}]
[{"number":"73263"}]
[{"number":"76232"}]
[{"number":"72963"}]Das generierte ein Array für jede Kontonummer. Was wir brauchen, ist ein Array für jeden ID -Wert. Dazu müssen alle number -JSON-Objekte für einen einzelnen ID -Wert in einem einzelnen Array zusammengefasst werden.select json_arrayagg(json_object('number' value account))
from emp_account group by id;JSON_ARRAYAGG ist eine Aggregatfunktion, die mit Datengruppen arbeitet. In diesem Fall erfolgt die Gruppierung in der Spalte ID . Jeder Account für einen ID generiert ein Objekt, dann werden alle diese Objekte in einem einzelnen Array zusammengefasst. Diese Abfrage gibt nur zwei Zeilen zurück, eine für jeden ID -Wert, nach dem genau gesucht wurde.[{"number":"36232"},{"number":"73263"}]
[{"number":"76232"},{"number":"72963"}]select json_object ('id' value id,
'name' value json_object ( 'first' value first_name,
'last' value last_name),
'office' value office_number,
'phones' value json_array
(case when home_phone is not null then
json_object('type' value 'home',
'number' value home_phone
) end format json,
case when work_phone is not null then
json_object('type' value 'work',
'number' value work_phone
) end format json),
'accounts' value (select json_arrayagg(
json_object('number' value account))
from emp_account a
where a.id = e.id group by id) format json
absent on null)
from empdata e;Jetzt haben wir unser Endergebnis erreicht.{"id":901,"name":{"first":"John","last":"Doe"},"office":"E-334",
"phones":[{"type":"home","number":"555-3762"},
{"type":"work","number":"555-7242"}],
"accounts":[{"number":"36232"},{"number":"73263"}]}
{"id":902,"name":{"first":"Peter","last":"Pan"},"office":"E-216",
"phones":[{"type":"work","number":"555-8925"}],
"accounts":[{"number":"76232"},{"number":"72963"}]}
{"id":903,"name":{"first":"Mary","last":"Jones"},"office":"E-739",
"phones":[{"type":"home","number":"555-6312"},
{"type":"work","number":"555-4311"}]}
{"id":904,"name":{"first":"Sally","last":"Smith"},"phones":[]}JSON in einem Objekt kombinieren
select json_object('employees' value json_arrayagg(
json_object ('id' value id,
'name' value json_object ( 'first' value first_name,
'last' value last_name),
'office' value office_number,
'phones' value json_array
(case when home_phone is not null then
json_object('type' value 'home',
'number' value home_phone
) end format json,
case when work_phone is not null then
json_object('type' value 'work',
'number' value work_phone
) end format json),
'accounts' value (select json_arrayagg(
json_object('number' value account))
from emp_account a
where a.id = e.id group by id) format json
absent on null)))
from empdata e;Zuerst schließen wir die Ergebnisse mit einem JSON_ARRAYAGG ein, um ein Array von Mitarbeiterinformationen zu erstellen. Anschließend wird das Array mit einem JSON_OBJECT eingeschlossen, sodass das Endergebnis ein einzelnes JSON-Objekt ist. Das Ergebnis ist jetzt ein JSON-Objekt.{"employees":[
{"id":901,"name":{"first":"John","last":"Doe"},"office":"E-334",
"phones":[{"type":"home","number":"555-3762"},
{"type":"work","number":"555-7242"}],
"accounts":[{"number":"36232"},{"number":"73263"}]},
{"id":902,"name":{"first":"Peter","last":"Pan"},"office":"E-216",
"phones":[{"type":"work","number":"555-8925"}],
"accounts":[{"number":"76232"},{"number":"72963"}]},
{"id":903,"name":{"first":"Mary","last":"Jones"},"office":"E-739",
"phones":[{"type":"home","number":"555-6312"},
{"type":"work","number":"555-4311"}]},
{"id":904,"name":{"first":"Sally","last":"Smith"},"phones":[]}
]}Ergebnisdatentyp festlegen
select json_object ('id' value id,
'name' value last_name,
'office' value office_number
returning varbinary(2000) format bson)
from empdata;Verwenden eines allgemeinen Tabellenausdrucks zum Aggregieren eindeutiger Werte
with sales_tmp(sales_person) as (
select distinct(sales_person) from sales),
region_tmp(region,sales_person) as (
select distinct region, sales_person from sales)
select json_object( key sales_person
value (select JSON_ARRAYAGG(region order by region)
from region_tmp r where r.sales_person = s.sales_person)
format json)
FROM sales_tmp s order by sales_person;Aus der Beispieltabelle werden die folgenden drei Zeilen zurückgegeben:{"GOUNOT":["Manitoba","Ontario-North","Ontario-South","Quebec"]}
{"LEE":["Manitoba","Ontario-North","Ontario-South","Quebec"]}
{"LUCCHESSI":["Manitoba","Ontario-South","Quebec"]}with sales_tmp(sales_person) as (
select distinct(sales_person) from sales),
region_tmp(region,sales_person) as (
select distinct region, sales_person from sales)
select json_objectagg( key sales_person
value (select JSON_ARRAYAGG(region order by region)
from region_tmp r where r.sales_person = s.sales_person)
format json)
FROM sales_tmp s;Gibt eine Zeile zurück, die ein JSON-Objekt enthält. Es ist hier in mehrere Zeilen unterteilt, damit es leicht zu lesen ist.{"LEE":["Manitoba","Ontario-North","Ontario-South","Quebec"],
"GOUNOT":["Manitoba","Ontario-North","Ontario-South","Quebec"],
"LUCCHESSI":["Manitoba","Ontario-South","Quebec"]}