Applies to: SQL Server 2016 (13.x) and later versions
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
SQL analytics endpoint in Microsoft Fabric
Warehouse in Microsoft Fabric
SQL database in Microsoft Fabric
OPENJSON
テーブル値関数は、JSON テキストを解析し、JSON 入力から行と列としてオブジェクトとプロパティを返します。 つまり、 OPENJSON
は JSON ドキュメントに対する行セット ビューを提供します。 行セット内の列と、それらの列に入力するために使用する JSON プロパティのパスを明示的に指定できます。
OPENJSON
は一連の行を返すので、他のテーブル、ビュー、またはテーブル値関数を使用できるのと同様に、Transact-SQL ステートメントのFROM
句でOPENJSON
を使用できます。
OPENJSON
を使用して、JSON データを SQL Server にインポートするか、JSON データを JSON を直接使用できないアプリまたはサービスのリレーショナル形式に変換します。
Note
OPENJSON
関数は、互換性レベル 130 以上でのみ使用できます。 データベースの互換性レベルが 130 より低い場合、SQL Server は OPENJSON
関数を見つけて実行できません。 他の JSON 関数は、すべての互換性レベルで使用できます。
sys.databases
ビューまたはデータベース プロパティで互換性レベルを確認できます。 次のコマンドを使用して、データベースの互換性レベルを変更できます。
ALTER DATABASE DatabaseName SET COMPATIBILITY_LEVEL = 130
Syntax
OPENJSON( jsonExpression [ , path ] ) [ <with_clause> ]
<with_clause> ::= WITH ( { colName type [ column_path ] [ AS JSON ] } [ ,...n ] )
The OPENJSON
table-valued function parses the jsonExpression provided as the first argument and returns one or more rows containing data from the JSON objects in the expression.
jsonExpression can contain nested sub-objects. If you want to parse a sub-object from within jsonExpression, you can specify a path parameter for the JSON sub-object.
openjson
By default, the OPENJSON
table-valued function returns three columns, which contain the key name, the value, and the type of each key:value
pair found in jsonExpression. As an alternative, you can explicitly specify the schema of the result set that OPENJSON
returns by providing with_clause.
with_clause
The with_clause contains a list of columns with their types for OPENJSON
to return. By default, OPENJSON
matches keys in jsonExpression with the column names in with_clause (in this case, matches keys implies that it is case sensitive). If a column name does not match a key name, you can provide an optional column_path, which is a JSON Path Expressions that references a key within the jsonExpression.
Arguments
jsonExpression
JSON テキストを含む Unicode 文字式です。
OPENJSON では、配列の要素または JSON 式内のオブジェクトのプロパティを反復処理し、各要素またはプロパティの 1 つの行を返します。 The following example returns each property of the object provided as jsonExpression:
DECLARE @json NVARCHAR(2048) = N'{
"String_value": "John",
"DoublePrecisionFloatingPoint_value": 45,
"DoublePrecisionFloatingPoint_value": 2.3456,
"BooleanTrue_value": true,
"BooleanFalse_value": false,
"Null_value": null,
"Array_value": ["a","r","r","a","y"],
"Object_value": {"obj":"ect"}
}';
SELECT * FROM OpenJson(@json);
Results:
キー | value | 型 |
---|---|---|
String_value | John | 1 |
DoublePrecisionFloatingPoint_value | 45 | 2 |
DoublePrecisionFloatingPoint_value | 2.3456 | 2 |
BooleanTrue_value | true | 3 |
BooleanFalse_value | false | 3 |
Null_value | NULL | 0 |
Array_value | ["a","r","r","a","y"] | 4 |
Object_value | {"obj":"ect"} | 5 |
- DoublePrecisionFloatingPoint_value は、IEEE 754 に準拠します。
path
Is an optional JSON path expression that references an object or an array within jsonExpression.
OPENJSON
は、指定された位置にある JSON テキストをシークし、参照されているフラグメントのみを解析します。 詳細については、「 JSON パス式」を参照してください。
You can provide a variable as the value of path. (これは、SQL Server 2016 (13.x) 以前のバージョンではサポートされていません)。
The following example returns a nested object by specifying the path:
DECLARE @json NVARCHAR(4000) = N'{
"path": {
"to":{
"sub-object":["en-GB", "en-UK","de-AT","es-AR","sr-Cyrl"]
}
}
}';
SELECT [key], value
FROM OPENJSON(@json,'$.path.to."sub-object"')
Results
Key | Value |
---|---|
0 | en-GB |
1 | en-UK |
2 | de-AT |
3 | es-AR |
4 | sr-Cyrl |
OPENJSON
が JSON 配列を解析すると、JSON テキスト内の要素のインデックスがキーとして返されます。
JSON の式のプロパティを持つパスの手順を照合に使用する比較では、大文字と小文字および照合順序に関係なく (つまり、BIN2 の比較)。
配列要素の ID
Azure Synapse Analytics のサーバーレス SQL プールの OPENJSON
関数を使用すると、結果として返される各行の ID を自動的に生成できます。 この ID 列は、列定義の後の JSON パスの式 $.sql:identity()
を使用して指定されます。 JSON パス式のこの値を持つ列は、関数が解析する JSON 配列内の各要素に対して一意の 0 から始まる数値を生成します。 ID 値は、配列要素の位置またはインデックスを表します。
DECLARE @array VARCHAR(MAX);
SET @array = '[{"month":"Jan", "temp":10},{"month":"Feb", "temp":12},{"month":"Mar", "temp":15},
{"month":"Apr", "temp":17},{"month":"May", "temp":23},{"month":"Jun", "temp":27}
]';
SELECT * FROM OPENJSON(@array)
WITH ( month VARCHAR(3),
temp int,
month_id tinyint '$.sql:identity()') as months
Results
month | temp | month_id |
---|---|---|
Jan | 10 | 0 |
Feb | 12 | 1 |
Mar | 15 | 2 |
Apr | 17 | 3 |
May | 23 | 4 |
Jun | 27 | 5 |
ID は、Synapse Analytics のサーバーレス SQL プールでのみ使用できます。
with_clause
OPENJSON
関数が返す出力スキーマを明示的に定義します。 The optional with_clause can contain the following elements:
colName
出力列の名前。
既定では、 OPENJSON
は列の名前を使用して JSON テキスト内のプロパティと一致します。 たとえば、スキーマで列 name
を指定した場合、 OPENJSON
は JSON テキストのプロパティ "name" をこの列に設定しようとします。 You can override this default mapping by using the column_path argument.
type
出力列のデータ型。
Note
If you also use the AS JSON
option, the column data type must be nvarchar(MAX).
column_path
指定した列で返されるプロパティを指定する JSON のパス。 For more info, see the description of the path parameter previously in this topic.
Use column_path to override default mapping rules when the name of an output column doesn't match the name of the property.
JSON の式のプロパティを持つパスの手順を照合に使用する比較では、大文字と小文字および照合順序に関係なく (つまり、BIN2 の比較)。
パスの詳細については、「 JSON パス式」を参照してください。
AS JSON
列定義の AS JSON
オプションを使用して、参照先のプロパティに内部 JSON オブジェクトまたは配列が含まれていることを指定します。 If you specify the AS JSON
option, the type of the column must be nvarchar(MAX).
If you don't specify
AS JSON
for a column, the function returns a scalar value (for example, int, string, true, false) from the specified JSON property on the specified path. パスがオブジェクトまたは配列を表し、指定したパスでプロパティが見つからない場合、関数はlax
モードでNULL
を返すか、strict
モードでエラーを返します。 この動作は、JSON_VALUE
関数の動作に似ています。列に
AS JSON
を指定すると、指定したパスの指定した JSON プロパティから JSON フラグメントが返されます。 パスがスカラー値を表し、指定したパスでプロパティが見つからない場合、関数はlax
モードでNULL
を返すか、strict
モードでエラーを返します。 この動作は、JSON_QUERY
関数の動作に似ています。
Note
JSON プロパティから入れ子になった JSON フラグメントを返す場合は、 AS JSON
フラグを指定する必要があります。 このオプションを指定しないと、プロパティが見つからない場合、 OPENJSON
は参照先の JSON オブジェクトまたは配列の代わりに NULL
値を返すか、 strict
モードで実行時エラーを返します。
たとえば、次のクエリを返し、配列の要素の書式を設定します。
DECLARE @json NVARCHAR(MAX) = N'[
{
"Order": {
"Number":"SO43659",
"Date":"2011-05-31T00:00:00"
},
"AccountNumber":"AW29825",
"Item": {
"Price":2024.9940,
"Quantity":1
}
},
{
"Order": {
"Number":"SO43661",
"Date":"2011-06-01T00:00:00"
},
"AccountNumber":"AW73565",
"Item": {
"Price":2024.9940,
"Quantity":3
}
}
]'
SELECT *
FROM OPENJSON ( @json )
WITH (
Number VARCHAR(200) '$.Order.Number',
Date DATETIME '$.Order.Date',
Customer VARCHAR(200) '$.AccountNumber',
Quantity INT '$.Item.Quantity',
[Order] NVARCHAR(MAX) AS JSON
)
Results
Number | Date | Customer | Quantity | Order |
---|---|---|---|---|
SO43659 | 2011-05-31T00:00:00 | AW29825 | 1 | {"Number":"SO43659","Date":"2011-05-31T00:00:00"} |
SO43661 | 2011-06-01T00:00:00 | AW73565 | 3 | {"Number":"SO43661","Date":"2011-06-01T00:00:00"} |
Return value
OPENJSON
関数が返す列は、WITH
オプションによって異なります。
既定のスキーマで
OPENJSON
を呼び出すと(つまり、WITH
句で明示的なスキーマを指定しない場合)、関数は次の列を持つテーブルを返します。Key
. An nvarchar(4000) value that contains the name of the specified property or the index of the element in the specified array.key
列には BIN2 照合順序があります。Value
. An nvarchar(MAX) value that contains the value of the property. Thevalue
column inherits its collation from jsonExpression.Type
. An int value that contains the type of the value.Type
列は、既定のスキーマでOPENJSON
を使用する場合にのみ返されます。type
列には、次のいずれかの値があります。型の列の値 JSON データ型 0 null 値 1 文字列 2 number 3 true/false 4 アレイ 5 オブジェクト
最初のレベル プロパティのみが返されます。 JSON のテキストが正しくフォーマットされていない場合、ステートメントが失敗します。
OPENJSON
を呼び出し、WITH
句で明示的なスキーマを指定すると、WITH
句で定義したスキーマを持つテーブルが返されます。
Note
Key
、Value
、およびType
の列は、既定のスキーマでOPENJSON
を使用する場合にのみ返され、明示的なスキーマでは使用できません。
Remarks
json_path used in the second argument of OPENJSON
or in with_clause can start with the lax
or strict
keyword.
-
lax
モードでは、指定したパスのオブジェクトまたは値が見つからない場合、OPENJSON
はエラーを発生しません。 パスが見つからない場合、OPENJSON
は空の結果セットまたはNULL
値を返します。 -
strict
では、モードOPENJSON
はパスが見つからない場合にエラーを返します。
このページの一部の例では、パス モード、 lax
、または strict
を明示的に指定します。 パス モードの指定は必須ではありません。 パス モードを明示的に指定しない場合は、 lax
モードが既定です。 パス モードとパス式の詳細については、「 JSON パス式」を参照してください。
Column names in with_clause are matched with keys in the JSON text. 列名 [Address.Country]
を指定した場合は、Address.Country
キーと照合されます。 オブジェクト Country
内の入れ子になったキー Address
を参照する場合は、パス $.Address.Country
を列のパスに指定する必要があります。
json_path can contain keys with alphanumeric characters. Escape the key name in json_path with double quotes if you have special characters in the keys. たとえば、 $."my key $1".regularKey."key with . dot"
は、次の JSON テキスト内の値 1
と一致します。
{
"my key $1": {
"regularKey":{
"key with . dot": 1
}
}
}
Examples
例 2 - JSON 配列を一時テーブルに変換します。
次の例では、識別子の一覧を数値の JSON 配列として指定します。 このクエリは、JSON 配列を識別子のテーブルに変換し、すべての製品を指定の ID でフィルター処理します。
DECLARE @pSearchOptions NVARCHAR(4000) = N'[1,2,3,4]'
SELECT *
FROM products
INNER JOIN OPENJSON(@pSearchOptions) AS productTypes
ON product.productTypeID = productTypes.value
このクエリは、次の例と同等です。 ただし、次の例では、数値をパラメーターとして渡す代わりに、クエリに埋め込む必要があります。
SELECT *
FROM products
WHERE product.productTypeID IN (1,2,3,4)
例 3 - 2 つの JSON オブジェクトからのマージ プロパティ
次の例では、2 つの JSON オブジェクトのすべてのプロパティの和集合を選択します。 The two objects have a duplicate name property. 例では、キーの値を使って、結果から重複する行を除外しています。
DECLARE @json1 NVARCHAR(MAX),@json2 NVARCHAR(MAX)
SET @json1=N'{"name": "John", "surname":"Doe"}'
SET @json2=N'{"name": "John", "age":45}'
SELECT *
FROM OPENJSON(@json1)
UNION ALL
SELECT *
FROM OPENJSON(@json2)
WHERE [key] NOT IN (SELECT [key] FROM OPENJSON(@json1))
例 3 - CROSS APPLY を使用してテーブルのセルに格納されている JSON データを行と結合する
次の例では、SalesOrderHeader
テーブルには、SalesReason
の配列を JSON 形式で含んでいるSalesOrderReasons
テキスト列があります。 The SalesOrderReasons
objects contain properties like Quality and Manufacturer. 例では、すべての販売注文の行を、関連する販売理由と結合するレポートを作成しています。
OPENJSON
演算子は、理由が別の子テーブルに格納されているかのように、販売理由の JSON 配列を拡張します。 次に、 CROSS APPLY
演算子は、各販売注文行を、 OPENJSON
テーブル値関数によって返される行に結合します。
SELECT SalesOrderID,OrderDate,value AS Reason
FROM Sales.SalesOrderHeader
CROSS APPLY OPENJSON(SalesReasons)
Tip
個々のフィールドに格納されている JSON 配列を展開し、親行と結合する必要がある場合は、通常、Transact-SQL CROSS APPLY
演算子を使用します。 For more info about CROSS APPLY
, see FROM clause.
返される行の明示的に定義されたスキーマを指定した OPENJSON
を使用することで、同じクエリを書き直すことができます。
SELECT SalesOrderID, OrderDate, value AS Reason
FROM Sales.SalesOrderHeader
CROSS APPLY OPENJSON (SalesReasons) WITH (value NVARCHAR(100) '$')
この例では、$
パスは、配列内の各要素を参照します。 返される値を明示的にキャストする場合は、この種類のクエリを使用できます。
例 4 - CROSS APPLY とリレーショナル行と JSON の要素を結合する
次のクエリは、次の表に示すように、リレーショナル行と JSON 要素を結果内で結合します。
SELECT store.title, ___location.street, ___location.lat, ___location.long
FROM store
CROSS APPLY OPENJSON(store.jsonCol, 'lax $.___location')
WITH (street VARCHAR(500) , postcode VARCHAR(500) '$.postcode' ,
lon int '$.geo.longitude', lat int '$.geo.latitude')
AS ___location
Results
title | street | postcode | lon | lat |
---|---|---|---|---|
食品市場全体 | 17991 レドモンド・ウェイ | WA 98052 | 47.666124 | -122.10155 |
Sears | 148th Ave NE | WA 98052 | 47.63024 | -122.141246,17 |
例 5 - インポートには、SQL Server の JSON データ
次の例では、全体の JSON オブジェクトを SQL Server テーブルです。
DECLARE @json NVARCHAR(max) = N'{
"id" : 2,
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"dateOfBirth": "2015-03-25T12:00:00",
"spouse": null
}';
INSERT INTO Person
SELECT *
FROM OPENJSON(@json)
WITH (id INT,
firstName NVARCHAR(50), lastName NVARCHAR(50),
isAlive BIT, age INT,
dateOfBirth DATETIME, spouse NVARCHAR(50))
例 6 - JSON コンテンツを使用したシンプルな例
--simple cross apply example
DECLARE @JSON NVARCHAR(MAX) = N'[
{
"OrderNumber":"SO43659",
"OrderDate":"2011-05-31T00:00:00",
"AccountNumber":"AW29825",
"ItemPrice":2024.9940,
"ItemQuantity":1
},
{
"OrderNumber":"SO43661",
"OrderDate":"2011-06-01T00:00:00",
"AccountNumber":"AW73565",
"ItemPrice":2024.9940,
"ItemQuantity":3
}
]'
SELECT root.[key] AS [Order],TheValues.[key], TheValues.[value]
FROM OPENJSON ( @JSON ) AS root
CROSS APPLY OPENJSON ( root.value) AS TheValues