解決 SQL Server 中的 JSON 常見問題
適用於: SQL Server 2016 (13.x) 以上版本 Azure SQL 資料庫Azure SQL 受控執行個體Azure Synapse Analytics (僅無伺服器 SQL 集區)
在此處尋找關於 SQL Server 中內建 JSON 支援的一些常見問題解答。
FOR JSON 和 JSON 輸出
FOR JSON PATH 或 FOR JSON AUTO?
問: 我想要透過單一資料表上的簡易 SQL 查詢,建立 JSON 文字結果。 FOR JSON PATH 與 FOR JSON AUTO 產生相同的輸出。 我該使用哪一個選項?
答: 使用 FOR JSON PATH。 JSON 輸出並無任何差異,但 AUTO 模式會套用某些額外邏輯,其可檢查是否應將資料行執行巢狀處理。 請考慮使用 PATH 做為預設選項。
建立巢狀的 JSON 結構
問: 我想要在相同層級產生具有數個陣列的複雜 JSON。 FOR JSON PATH 可使用路徑建立巢狀物件,而 FOR JSON AUTO 會針對每個資料表建立額外巢狀層級。 這兩個選項都無法產生我想要的輸出。 如何建立現有選項未直接支援的自訂 JSON 格式?
答: 您可以新增 FOR JSON 查詢作為傳回 JSON 文字的資料行運算式,以建立任何資料結構。 您也可以使用 JSON_QUERY 函數手動建立 JSON。 下列範例會示範這些技術。
SELECT col1, col2, col3,
(SELECT col11, col12, col13 FROM t11 WHERE t11.FK = t1.PK FOR JSON PATH) as t11,
(SELECT col21, col22, col23 FROM t21 WHERE t21.FK = t1.PK FOR JSON PATH) as t21,
(SELECT col31, col32, col33 FROM t31 WHERE t31.FK = t1.PK FOR JSON PATH) as t31,
JSON_QUERY('{"'+col4+'":"'+col5+'"}') as t41
FROM t1
FOR JSON PATH
資料行運算式中的所有 FOR JSON 查詢或 JSON_QUERY 函數結果,皆會格式化為個別的巢狀 JSON 子物件並包含於主要結果。
避免在 FOR JSON 輸出中產生雙逸出 JSON
問: 我已將 JSON 文字儲存於資料表資料行。 我想要將其包含在 FOR JSON 輸出中。 FOR JSON 會逸出 JSON 中的所有字元,因此我會收到 JSON 字串而非巢狀物件,如下列範例所示。
SELECT 'Text' AS myText, '{"day":23}' AS myJson
FOR JSON PATH
此查詢會產生下列輸出。
[{"myText":"Text", "myJson":"{\"day\":23}"}]
如何防止此行為? 我想讓 {"day":23}
以 JSON 物件形式傳回而非逸出的文字。
答: 儲存於文字資料行的 JSON 或常值,其處理方式與任何文字相似。 也就是說,它會以雙引號括住並逸出。 若您想要傳回未逸出的 JSON 物件,則必須將 JSON 資料行以引數形式傳送至 JSON_QUERY 函數,如下列範例所示。
SELECT col1, col2, col3, JSON_QUERY(jsoncol1) AS jsoncol1
FROM tab1
FOR JSON PATH
JSON_QUERY 若無選用的第二參數,則僅會傳回第一個引數做為結果。 由於 JSON_QUERY 永遠會傳回有效的 JSON,因此 FOR JSON 知道此結果無須逸出。
使用 WITHOUT_ARRAY_WRAPPER 子句產生的 JSON,會在 FOR JSON 輸出中逸出
問: 我嘗試使用 FOR JSON 和 WITHOUT_ARRAY_WRAPPER 選項,格式化資料行運算式。
SELECT 'Text' as myText,
(SELECT 12 day, 8 mon FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) as myJson
FOR JSON PATH
FOR JSON 查詢傳回的文字似乎會逸出為純文字。 僅在指定 WITHOUT_ARRAY_WRAPPER 時才會發生此情況。 為何不會將它視為 JSON 物件,並將它以未逸出方式包含在結果中?
答: 如果您在內部 FOR JSON
中指定 WITHOUT_ARRAY_WRAPPER
選項,產生的 JSON 文字不一定是有效的 JSON。 因此,外部 FOR JSON
會假定此為純文字並逸出字串。 若您確定 JSON 輸出有效,請使用 JSON_QUERY
函數將其包裝以升級為正確格式的 JSON,如下列範例所示。
SELECT 'Text' as myText,
JSON_QUERY((SELECT 12 day, 8 mon FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)) as myJson
FOR JSON PATH
OPENJSON 和 JSON 輸入
使用 OPENJSON 從 JSON 文字傳回巢狀 JSON 子物件
問: 無法使用具明確結構描述的 OPENJSON,開啟包含純量值、物件和陣列的複雜 JSON 物件陣列。 參考 WITH 子句中的索引鍵時,僅會傳回純量值。 物件和陣列會以 Null 值形式傳回。 如何以 JSON 物件的形式擷取物件或陣列?
答: 若您想要傳回物件或陣列作為資料行,請在資料行定義中使用 AS JSON 選項,如下列範例所示。
SELECT scalar1, scalar2, obj1, obj2, arr1
FROM OPENJSON(@json)
WITH ( scalar1 int,
scalar2 datetime2,
obj1 NVARCHAR(MAX) AS JSON,
obj2 NVARCHAR(MAX) AS JSON,
arr1 NVARCHAR(MAX) AS JSON)
使用 OPENJSON 傳回長文字值,而不要用 JSON_VALUE
問: 在包含長文字的 JSON 文字當中具有描述索引鍵。 JSON_VALUE(@json, '$.description')
傳回 NULL 而非值。
答: JSON_VALUE 設計為傳回小純量值。 函數通常會傳回 NULL 而非溢位錯誤。 若您想要傳回整數值,請使用支援 NVARCHAR(MAX) 值的 OPENJSON,如下列範例所示。
SELECT myText FROM OPENJSON(@json) WITH (myText NVARCHAR(MAX) '$.description')
使用 OPENJSON 處理重複的索引鍵,而不要用 JSON_VALUE
問: 在 JSON 文字中具有重複的索引鍵。 JSON_VALUE 僅傳回在路徑上找到的第一個索引鍵。 如何傳回所有具相同名稱的索引鍵?
答: 內建 JSON 純量函數僅會傳回第一次出現的參考物件。 若您需要多個索引鍵,請使用 OPENJSON 資料表值函式,如下列範例所示。
SELECT value FROM OPENJSON(@json, '$.info.settings')
WHERE [key] = 'color'
OPENJSON 需要相容性層級 130
問: 我嘗試在 SQL Server 2016 中執行 OPENJSON,結果收到下列錯誤。
Msg 208, Level 16, State 1 'Invalid object name OPENJSON'
答: OPENJSON 函式僅適用於相容性等級 130。 若您的資料庫相容性等級低於 130,則會隱藏 OPENJSON。 其他 JSON 函數適用於所有的相容性層級。
其他問題
在 JSON 文字中包含非英數字元的參考索引鍵
問: 在 JSON 文字的索引鍵中具有非英數字元。 如何參考這些屬性?
答: 您必須在 JSON 路徑中使用引號將其括住。 例如: JSON_VALUE(@json, '$."$info"."First Name".value')
。
深入了解 SQL Server 和 Azure SQL Database 中的 JSON
Microsoft 影片
注意
本節中的部分影片連結目前可能無法運作。 Microsoft 正在將先前在 Channel 9 上的內容移轉至新的平台。 我們會在影片移轉至新平台時更新連結。
如需 SQL Server 和 Azure SQL Database 中內建 JSON 支援的觀看式簡介,請參閱下列影片:
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應