Nếu bạn đang sử dụng OPENJSON()
, nhưng bạn đang cố nhớ cách chọn một phần bên trong từ tài liệu JSON, hãy đọc tiếp.
OPENJSON()
cú pháp cho phép bạn chuyển đổi tài liệu JSON thành dạng xem dạng bảng. Nó cũng cho phép bạn chọn một đoạn JSON lồng nhau từ tài liệu JSON.
Cách để làm điều này là với đường dẫn .
Đường dẫn
Đường dẫn bao gồm những điều sau:
- Một ký hiệu đô la (
$
), đại diện cho mục ngữ cảnh. - Một tập hợp các bước đường dẫn. Các bước đường dẫn có thể chứa các phần tử và toán tử sau:
- Tên chính. Ví dụ:
$.pets
và$.pets.dogs
. Nếu tên khóa bắt đầu bằng ký hiệu đô la hoặc chứa các ký tự đặc biệt như dấu cách, thì tên khóa phải được bao quanh bằng dấu ngoặc kép (ví dụ:$."my pets"
). - Các phần tử của mảng. Ví dụ:
$.pets.dogs[1]
. Chỉ mục của mảng dựa trên 0, vì vậy, ví dụ này chọn phần tử thứ hai trong mảng. - Toán tử dấu chấm (
.
) chỉ ra một thành viên của một đối tượng. Ví dụ:trong$.pets.dogs
,dogs
là thành viên củapets
.
- Tên chính. Ví dụ:
Ví dụ cơ bản
Dưới đây là một ví dụ đơn giản để chứng minh.
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)
);
Kết quả:
+------+--------+--------+ | id | name | sex | |------+--------+--------| | 1 | Fetch | Male | | 2 | Fluffy | Male | | 3 | Wag | Female | +------+--------+--------+
Trong trường hợp này, đối số thứ hai cho OPENJSON()
là '$.pets.dogs'
, có nghĩa là chúng tôi đang chọn giá trị của dogs
key, bản thân nó là con của pets
.
Kí hiệu đô la ($
) đại diện cho mục ngữ cảnh.
Lưu ý rằng trong ví dụ này, tôi cũng sử dụng WITH
mệnh đề xác định lược đồ. Nếu tôi không bao gồm điều đó, lược đồ mặc định sẽ được sử dụng thay thế.
Đây là giao diện của nó khi sử dụng lược đồ mặc định.
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');
Kết quả:
+-------+-------------------------------------------------+--------+ | 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 | +-------+-------------------------------------------------+--------+
Vì vậy, chúng tôi vẫn đang chọn cùng một JSON lồng nhau, chỉ là chúng tôi đang sử dụng một giản đồ khác.
Lược đồ mặc định luôn trả về ba cột; phím , giá trị và loại .
Chọn phần tử mảng
Như đã đề cập, bạn có thể sử dụng ký hiệu dấu ngoặc vuông để chọn một phần tử cụ thể trong một mảng.
Đây là một ví dụ.
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)
);
Kết quả:
+------+--------+-------+ | id | name | sex | |------+--------+-------| | 1 | Fetch | Male | +------+--------+-------+
Xem như chỉ mục mảng dựa trên 0, chỉ định giá trị 0
trả về phần tử đầu tiên trong mảng.
Dưới đây là ví dụ này trông như thế nào khi sử dụng lược đồ mặc định (tức là không có WITH
mệnh đề).
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]');
Kết quả:
+-------+---------+--------+ | key | value | type | |-------+---------+--------| | id | 1 | 2 | | name | Fetch | 1 | | sex | Male | 1 | +-------+---------+--------+
Chế độ đường dẫn
Khi sử dụng đường dẫn, bạn có tùy chọn khai báo chế độ đường dẫn.
Chế độ đường dẫn xác định điều gì sẽ xảy ra khi biểu thức đường dẫn có lỗi.
Chế độ đường dẫn có thể là lax
hoặc strict
.
- Trong
lax
, hàm trả về các giá trị trống nếu không tìm thấy đường dẫn. Ví dụ:nếu bạn yêu cầu giá trị$.pets.cows
, nhưng JSON không chứa khóa đó, hàm trả về null, nhưng không phát sinh lỗi. - Trong
strict
, hàm này sẽ xảy ra lỗi nếu không tìm thấy đường dẫn.
Chế độ đường dẫn mặc định là lax
, vì vậy nếu bạn không khai báo, hãy lax
Được sử dụng.
Ví dụ
Dưới đây là một ví dụ để chứng minh cách mỗi chế độ đường dẫn xử lý các đường dẫn bị thiếu.
Chế độ Lax
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');
Kết quả:
(0 rows affected)
Vì vậy, chế độ lỏng lẻo không gây ra bất kỳ lỗi nào. Nó chỉ dẫn đến không có hàng nào bị ảnh hưởng.
Nếu chúng tôi chỉ định lược đồ của riêng mình và chúng tôi đã chọn đúng đối tượng con, nhưng chúng tôi sử dụng một đường dẫn bị thiếu để ánh xạ tới tên cột, nó sẽ trả về NULL
trong cột đó.
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'
);
Kết quả:
+------+--------+---------+ | id | name | color | |------+--------+---------| | 1 | Fetch | NULL | | 2 | Fluffy | NULL | | 3 | Wag | NULL | +------+--------+---------+
Chế độ nghiêm ngặt
Đây là những gì sẽ xảy ra khi chúng tôi sử dụng chế độ nghiêm ngặt.
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');
Kết quả:
Msg 13608, Level 16, State 3, Line 16 Property cannot be found on the specified JSON path.
Như mong đợi, nó đã dẫn đến lỗi.
Lỗi tương tự cũng xảy ra khi chúng tôi chọn đúng khóa JSON, nhưng ánh xạ một cột với một khóa không tồn tại.
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'
);
Kết quả:
Msg 13608, Level 16, State 6, Line 16 Property cannot be found on the specified JSON path.
Đường dẫn trùng lặp
Nếu tài liệu JSON của bạn chứa các đường dẫn trùng lặp ở cùng mức lồng nhau, OPENJSON()
có thể trả lại tất cả.
Điều này trái ngược với JSON_VALUE()
và JSON_QUERY()
, cả hai đều chỉ trả về giá trị đầu tiên phù hợp với đường dẫn.
Đây là một ví dụ về việc sử dụng OPENJSON()
để trả về các đường dẫn trùng lặp.
DECLARE @json NVARCHAR(4000) = N'{
"dog": {
"names": {
"name": "Fetch",
"name": "Good Dog"
}
}
}';
SELECT * FROM OPENJSON(@json, '$.dog.names');
Kết quả:
+-------+----------+--------+ | key | value | type | |-------+----------+--------| | name | Fetch | 1 | | name | Good Dog | 1 | +-------+----------+--------+
Đối tượng con lồng nhau
Khi xác định lược đồ của riêng bạn, bạn có thể sử dụng AS JSON
tùy chọn trả về toàn bộ đối tượng con dưới dạng tài liệu JSON của riêng nó.
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
);
Kết quả:
+--------+ | dogs | |--------| | [ { "id" : 1, "name" : "Fetch", "sex" : "Male" }, { "id" : 2, "name" : "Fluffy", "sex" : "Male" }, { "id" : 3, "name" : "Wag", "sex" : "Female" } ] | +--------+
Nếu chúng tôi chưa sử dụng AS JSON
tùy chọn, chúng tôi sẽ nhận được lỗi hoặc NULL, tùy thuộc vào việc chúng tôi có chỉ định lax
hay không hoặc strict
chế độ.
Đây là nó trong mỗi chế độ khi bỏ qua AS JSON
tùy chọn.
Chế độ lỏng lẻo
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'
);
Kết quả:
+--------+ | dogs | |--------| | NULL | +--------+
Chế độ nghiêm ngặt
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'
);
Kết quả:
Msg 13624, Level 16, State 1, Line 16 Object or array cannot be found in the specified JSON path.