Jeśli używasz OPENJSON()
, ale próbujesz zapamiętać, jak wybrać wewnętrzny fragment z dokumentu JSON, czytaj dalej.
OPENJSON()
składnia umożliwia konwersję dokumentów JSON na widok tabelaryczny. Pozwala również wybrać zagnieżdżony fragment JSON z dokumentu JSON.
Sposobem na to jest użycie ścieżek .
Ścieżki
Ścieżka składa się z następujących elementów:
- Znak dolara (
$
), który reprezentuje element kontekstu. - Zestaw kroków ścieżki. Kroki ścieżki mogą zawierać następujące elementy i operatory:
- Nazwy kluczy. Na przykład
$.pets
i$.pets.dogs
. Jeśli nazwa klucza zaczyna się od znaku dolara lub zawiera znaki specjalne, takie jak spacje, musi być otoczona cudzysłowami (na przykład$."my pets"
). - Elementy tablicy. Na przykład
$.pets.dogs[1]
. Indeksy tablicy są liczone od zera, więc ten przykład wybiera drugi element tablicy. - Operator kropki (
.
) wskazuje członka obiektu. Na przykład w$.pets.dogs
,dogs
jest członkiempets
.
- Nazwy kluczy. Na przykład
Przykład podstawowy
Oto prosty przykład do zademonstrowania.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets.dogs')
WITH (
[id] int,
[name] varchar(60),
[sex] varchar(6)
);
Wynik:
+------+--------+--------+ | id | name | sex | |------+--------+--------| | 1 | Fetch | Male | | 2 | Fluffy | Male | | 3 | Wag | Female | +------+--------+--------+
W tym przypadku drugi argument OPENJSON()
to '$.pets.dogs'
, co oznacza, że wybieramy wartość dogs
klucz, który sam jest dzieckiem pets
.
Znak dolara ($
) reprezentuje element kontekstu.
Zauważ, że w tym przykładzie używam również WITH
klauzula definiująca schemat. Gdybym tego nie uwzględnił, zamiast tego zostałby użyty domyślny schemat.
Oto jak to wygląda przy użyciu domyślnego schematu.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets.dogs');
Wynik:
+-------+-------------------------------------------------+--------+ | key | value | type | |-------+-------------------------------------------------+--------| | 0 | { "id" : 1, "name" : "Fetch", "sex" : "Male" } | 5 | | 1 | { "id" : 2, "name" : "Fluffy", "sex" : "Male" } | 5 | | 2 | { "id" : 3, "name" : "Wag", "sex" : "Female" } | 5 | +-------+-------------------------------------------------+--------+
Więc nadal wybieramy ten sam zagnieżdżony JSON, po prostu używamy innego schematu.
Domyślny schemat zawsze zwraca trzy kolumny; klucz , wartość i wpisz .
Wybieranie elementów tablicy
Jak wspomniano, możesz użyć notacji z nawiasami kwadratowymi, aby wybrać określony element w tablicy.
Oto przykład.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets.dogs[0]')
WITH (
[id] int,
[name] varchar(60),
[sex] varchar(6)
);
Wynik:
+------+--------+-------+ | id | name | sex | |------+--------+-------| | 1 | Fetch | Male | +------+--------+-------+
Ponieważ indeksy tablic są liczone od zera, określając wartość 0
zwraca pierwszy element tablicy.
Oto jak wygląda ten przykład przy użyciu domyślnego schematu (tj. bez WITH
klauzula).
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets.dogs[0]');
Wynik:
+-------+---------+--------+ | key | value | type | |-------+---------+--------| | id | 1 | 2 | | name | Fetch | 1 | | sex | Male | 1 | +-------+---------+--------+
Tryb ścieżki
Podczas korzystania ze ścieżek masz możliwość zadeklarowania trybu ścieżki.
Tryb ścieżki określa, co się stanie, gdy wyrażenie ścieżki zawiera błąd.
Tryb ścieżki może być lax
lub strict
.
- W
lax
w trybie, funkcja zwraca puste wartości, jeśli nie można znaleźć ścieżki. Na przykład, jeśli zażądasz wartości$.pets.cows
, ale JSON nie zawiera tego klucza, funkcja zwraca wartość null, ale nie zgłasza błędu. - W
strict
w trybie, funkcja zgłasza błąd, jeśli nie można znaleźć ścieżki.
Domyślny tryb ścieżki to lax
, więc jeśli tego nie zadeklarujesz, lax
Jest używane.
Przykład
Oto przykład pokazujący, jak każdy tryb ścieżki obsługuje brakujące ścieżki.
Tryb rozluźnienia
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, 'lax $.pets.cows');
Wynik:
(0 rows affected)
Tak więc tryb lax nie wyrzucił żadnych błędów. Spowodowało to po prostu brak wpływu na zero wierszy.
Gdybyśmy określili nasz własny schemat i wybrali poprawny podobiekt, ale użyliśmy brakującej ścieżki do mapowania na nazwę kolumny, zwróciłoby to NULL
w tej kolumnie.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}'
SELECT *
FROM OPENJSON(@json, 'lax $.pets.dogs')
WITH (
[id] int 'lax $.id',
[name] varchar(60) 'lax $.name',
[color] varchar(6) 'lax $.color'
);
Wynik:
+------+--------+---------+ | id | name | color | |------+--------+---------| | 1 | Fetch | NULL | | 2 | Fluffy | NULL | | 3 | Wag | NULL | +------+--------+---------+
Tryb ścisły
Oto, co się dzieje, gdy używamy trybu ścisłego.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, 'strict $.pets.cows');
Wynik:
Msg 13608, Level 16, State 3, Line 16 Property cannot be found on the specified JSON path.
Zgodnie z oczekiwaniami spowodowało to błąd.
Ten sam błąd występuje, gdy wybieramy poprawny klucz JSON, ale mapujemy kolumnę na nieistniejący klucz.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, 'strict $.pets.dogs')
WITH (
[id] int 'strict $.id',
[name] varchar(60) 'strict $.name',
[color] varchar(6) 'strict $.color'
);
Wynik:
Msg 13608, Level 16, State 6, Line 16 Property cannot be found on the specified JSON path.
Zduplikowane ścieżki
Jeśli Twój dokument JSON zawiera zduplikowane ścieżki na tym samym poziomie zagnieżdżenia, OPENJSON()
może zwrócić je wszystkie.
Jest to w przeciwieństwie do JSON_VALUE()
i JSON_QUERY()
, z których oba zwracają tylko pierwszą wartość, która pasuje do ścieżki.
Oto przykład użycia OPENJSON()
aby zwrócić zduplikowane ścieżki.
DECLARE @json NVARCHAR(4000) = N'{
"dog": {
"names": {
"name": "Fetch",
"name": "Good Dog"
}
}
}';
SELECT * FROM OPENJSON(@json, '$.dog.names');
Wynik:
+-------+----------+--------+ | key | value | type | |-------+----------+--------| | name | Fetch | 1 | | name | Good Dog | 1 | +-------+----------+--------+
Zagnieżdżone obiekty podrzędne
Podczas definiowania własnego schematu możesz użyć AS JSON
możliwość zwrócenia całego podobiektu jako własnego dokumentu JSON.
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets')
WITH (
[dogs] nvarchar(max) '$.dogs' AS JSON
);
Wynik:
+--------+ | dogs | |--------| | [ { "id" : 1, "name" : "Fetch", "sex" : "Male" }, { "id" : 2, "name" : "Fluffy", "sex" : "Male" }, { "id" : 3, "name" : "Wag", "sex" : "Female" } ] | +--------+
Gdybyśmy nie użyli AS JSON
opcja, otrzymalibyśmy błąd lub NULL, w zależności od tego, czy określiliśmy lax
lub strict
tryb.
Tutaj jest w każdym trybie z pominięciem AS JSON
opcja.
Tryb rozluźnienia
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets')
WITH (
[dogs] nvarchar(max) 'lax $.dogs'
);
Wynik:
+--------+ | dogs | |--------| | NULL | +--------+
Tryb ścisły
DECLARE @json NVARCHAR(4000) = N'{
"pets" : {
"cats" : [
{ "id" : 1, "name" : "Fluffy", "sex" : "Female" },
{ "id" : 2, "name" : "Long Tail", "sex" : "Female" },
{ "id" : 3, "name" : "Scratch", "sex" : "Male" }
],
"dogs" : [
{ "id" : 1, "name" : "Fetch", "sex" : "Male" },
{ "id" : 2, "name" : "Fluffy", "sex" : "Male" },
{ "id" : 3, "name" : "Wag", "sex" : "Female" }
]
}
}';
SELECT *
FROM OPENJSON(@json, '$.pets')
WITH (
[dogs] nvarchar(max) 'strict $.dogs'
);
Wynik:
Msg 13624, Level 16, State 1, Line 16 Object or array cannot be found in the specified JSON path.