SQL Server 2016 JSON支持

SQL Server 2016 JSON支持

英文原文:

https://www.simple-talk.com/sql/learn-sql-server/json-support-in-sql-server-2016/


最近,SQL Server 跟上其他關係型數據庫的步伐,提供了有用的JSON支持的功能。這是一個好的開始,儘管它還不像已存在的XML支持那樣完善。對於許多應用,能夠滿足需求。


SQL Server 2016最後添加了JSON支持,它是一個在不同源類型之間交換數據的輕量格式,類似於XML。JSON是JavaScript對象表示(JavaScript Object Notation)的簡稱,基於JavaScript編程語言的子集,備註爲易讀、易於被計算機解析和生成。


根據微軟的說明,它是微軟connect網站排名最高的需求之一,他被包含在SQL Server是受歡迎的消息。也就是說,除非你期待和XML同樣健壯的支持。SQL Server 2016非常完善的支持JSON,也沒有像在PostgreSQL找到的功能。


SQL Server 2016沒有引入JSON專屬數據類型,因此沒有像XML數據類型大量可用方法。SQL Server 2016繼續使用NVARCHAR類型存儲JSON數據。然而,提供了一些重要的T-SQL語言元素,用於比以前更易於處理JSON,所以微軟至少在正確的方向前進,即使仍然要跟上步伐。


開始瞭解JSON


儘管JSON比我們涵蓋的內容更加複雜,在開始關於SQL Server支持之前,它有助於基本的理解JSON代碼片段的組成。最基本的,JSON片段可以包含對象、數組,或都包含。一個對象是一個爲排序的,一個或多個名稱/值對(屬性)的集合,用大括號括起來,像如下示例一樣顯示:

{"FirstName":"Terri", "Current":true, "Age":42, "Phone":null}

對於每個屬性,名稱組件(FirstName,Current,Age,Phone)用雙引號引起來,後面跟着逗號。名稱組件,有時被作爲鍵,總是一個字符串。屬性的值有稍微不同的規則。如果值是字符串,你應該用雙引號引用。如果是一個數字值、布爾值(true或false),或null值,不使用引號。

一個數組只是一個排序的值的集合,用中括號括起來,示例如下:

["Terri", true, 42, null]

數組支持和對象一樣的值類型:字符串、數字、true、false或null。對象和數組可以包含其他對象和數組作爲他們的值,像下面的示例一樣,提供了嵌套結構的方式:

{
   "Employees":[
      {
         "Name":{
            "First":"Terri",
            "Middle":"Lee",
            "Last":"Duffy"
         },
         "PII":{
            "DOB":"1971-08-01",
            "NatID":"245797967"
         },
         "LoginID":"adventure-works\\terri0"
      },
      {
         "Name":{
            "First":"Roberto",
            "Middle":null,
            "Last":"Tamburello"
         },
         "PII":{
            "DOB":"1974-11-12",
            "NatID":"509647174"
         },
         "LoginID":"adventure-works\\roberto0"
      }
   ]
}


在頂層,有一個包含單一屬性的JSON對象。屬性的名稱是Employees,值是一個數組,它包含兩個值。每個數組值是包含了Name,PII和LoginID屬性的一個JSON對象。Name和PII值也是JSON對象,包含他們自己的名稱/值對。


在完成本文中的示例後,你會更好的理解這些大量的組件是如何工作的。


格式化查詢結果爲JSON


在SQL Server 2016中支持的一個JSON相關的屬性是,可以通過添加FOR JSON從句到SELECT語句,來以JSON格式返回數據。我們來瀏覽下如何使用FOR JSON從句以JSON格式返回數據的基礎,使用AUTO參數或PATH參數。


首先,我們需要構造一些工作所需數據。下面的SELECT語句從AdventureWorks2016CTP3數據庫的vEmployee視圖返回兩行:

USE AdventureWorks2016CTP3;
go
SELECT FirstName, MiddleName, LastName,
EmailAddress, PhoneNumber
FROM HumanResources.vEmployee
WHERE BusinessEntityID in (2, 3);

它返回了以下結果,儘管你可能會看到與最後產品不同的結果,因爲數據和示例基於SQL Server 2016 CTP3版本:

FirstName

MiddleName

LastName

EmailAddress

PhoneNumber

Terri

Lee

Duffy

[email protected]

819-555-0175

Roberto

NULL

Tamburello

[email protected]

212-555-0187


AUTO模式


以JSON格式返回結果,爲了支持一個特定應用,我們只需添加FOR JSON從句到該語句,如下示例:

SELECT FirstName, MiddleName, LastName,
EmailAddress, PhoneNumber
FROM HumanResources.vEmployee
WHERE BusinessEntityID in (2, 3)
FOR JSON AUTO;

注意到從句包含AUTO參數,表明結果應該以AUTO模式返回。當你指定該模式,數據庫引擎自動決定JSON格式,基於SELECT列表和FROM從句中表中的列的字段順序。在這裏,FOR JSON AUTO從句導致SELECT語句返回如下結果。

[{"FirstName":"Terri","MiddleName":"Lee","LastName":"Duffy","EmailAddress":"[email protected]","PhoneNumber":"819-555-0175"},{"FirstName":"Roberto","LastName":"Tamburello","EmailAddress":"[email protected]","PhoneNumber":"212-555-0187"}]

從這些結果,你可以看到JSON的輸出包含含有兩個值的數組,每個值是一個JSON對象。毫不奇怪,因爲結果變得更加複雜,更加難懂。在這種情況下,你可以使用一個本地的或在線的JSON格式化/驗證工具將JSON片段轉換爲更加易讀。例如,我將之前的結果傳給格式化工具https://jsonformatter.curiousconcept.com/並獲得如下JSON:

[
   {
      "FirstName":"Terri",
      "MiddleName":"Lee",
      "LastName":"Duffy",
      "EmailAddress":"[email protected]",
      "PhoneNumber":"819-555-0175"
   },
   {
      "FirstName":"Roberto",
      "LastName":"Tamburello",
      "EmailAddress":"[email protected]",
      "PhoneNumber":"212-555-0187"
   }
]

如你所見,現在更容易看到頂層數組和包含的兩個對象值。每個對象屬於SELECT語句返回的一行。向前推進,我們將只顯示更加可讀的格式化結果,但是SQL Server以單行值返回數據,沒有所有的空格和空行,就像上面看到的。


現在你嘗試下FOR JSON AUTO從句,讓我們看看當連接表的時候發生了什麼:

SELECT e.BirthDate, e.NationalIDNumber, e.LoginID,
p.FirstName, p.MiddleName, p.LastName
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON AUTO;

因爲我們的SELECT語句變得更加複雜,輸出爲JSON格式,顯示爲如下結果:

[ 
   { 
      "BirthDate":"1971-08-01",
      "NationalIDNumber":"245797967",
      "LoginID":"adventure-works\\terri0",
      "p":[
         {
            "FirstName":"Terri",
            "MiddleName":"Lee",
            "LastName":"Duffy"
         }
      ]
   },
   {
      "BirthDate":"1974-11-12",
      "NationalIDNumber":"509647174",
      "LoginID":"adventure-works\\roberto0",
      "p":[
         {
            "FirstName":"Roberto",
            "LastName":"Tamburello"
         }
      ]
   }
]

來自Person表的信息是,現在它是p數組的一部分,它是父對象的一個值。我們重新調用,AUTO模式基於SELECT列表和FROM從句表中的字段順序格式化結果,所以讓我們混合列順序:

SELECT p.FirstName, p.MiddleName, p.LastName,
e.BirthDate, e.NationalIDNumber, e.LoginID
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON AUTO;

現在SELECT語句將會從Employee表以嵌套對象將數據返回爲JSON:

[
   {
      "FirstName":"Terri",
      "MiddleName":"Lee",
      "LastName":"Duffy",
      "e":[
         {
            "BirthDate":"1971-08-01",
            "NationalIDNumber":"245797967",
            "LoginID":"adventure-works\\terri0"
         }
      ]
   },
   {
      "FirstName":"Roberto",
      "LastName":"Tamburello",
      "e":[
         {
            "BirthDate":"1974-11-12",
            "NationalIDNumber":"509647174",
            "LoginID":"adventure-works\\roberto0"
         }
      ]
   }
]

如你所見,我們有兩個e數組,嵌入在外層對象中。我們可以繼續調整SELECT語句來嘗試獲得更加接近我們想要的JSON結果,或者我們可以使用PATH模式代替,它給予我們對於JSON格式化輸出的完全控制。對於最基本的SELECT語句,你可能想使用PATH模式。


PATH模式

爲了使用PATH模式,我們開始在FOR JSON從句中指定PATH,而不是AUTO,如下示例:

SELECT p.FirstName, p.MiddleName, p.LastName,
e.BirthDate, e.NationalIDNumber, e.LoginID
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON PATH;

當我們切換到PATH模式,數據庫引擎格式化我們的結果,並以兩個對象值在一個數組中返回數據:

[
   {
      "FirstName":"Terri",
      "MiddleName":"Lee",
      "LastName":"Duffy",
      "BirthDate":"1971-08-01",
      "NationalIDNumber":"245797967",
      "LoginID":"adventure-works\\terri0"
   },
   {
      "FirstName":"Roberto",
      "LastName":"Tamburello",
      "BirthDate":"1974-11-12",
      "NationalIDNumber":"509647174",
      "LoginID":"adventure-works\\roberto0"
   }
]

以這種方式使用PATH模式是相當直接的;然而,這是PATH的最基本用法。該模式讓我們有更多定製。例如,我們可以控制數據庫引擎如何通過指定列別名用於定義結構來嵌套JSON輸出,如下所示SELECT從句:

SELECT
p.FirstName AS [Name.First],
p.MiddleName AS [Name.Middle],
p.LastName AS [Name.Last],
e.BirthDate AS [PII.DOB],
e.NationalIDNumber AS [PII.NatID],
e.LoginID
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON PATH;

在這種情況下,我們定義Name對象,包含First,Middle和Last值;PII對象,包含DOB和NatID值;和LoginID名稱/值對,如下結果所示:

[
   {
      "Name":{
         "First":"Terri",
         "Middle":"Lee",
         "Last":"Duffy"
      },
      "PII":{
         "DOB":"1971-08-01",
         "NatID":"245797967"
      },
      "LoginID":"adventure-works\\terri0"
   },
   {
      "Name":{
         "First":"Roberto",
         "Last":"Tamburello"
      },
      "PII":{
         "DOB":"1974-11-12",
         "NatID":"509647174"
      },
      "LoginID":"adventure-works\\roberto0"
   }
]

在某些情況下,你想添加一個單一的,頂層元素到JSON輸出中作爲root元素。爲了這麼做,你必須指定它爲FOR JSON從句的一部分,如下示例:

SELECT
p.FirstName AS [Name.First],
p.MiddleName AS [Name.Middle],
p.LastName AS [Name.Last],
e.BirthDate AS [PII.DOB],
e.NationalIDNumber AS [PII.NatID],
e.LoginID
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON PATH, ROOT('Employees');

爲了指定root,我們添加ROOT選項到FOR JSON從句,在這裏,命名root爲Employees,得到如下結果:

{
   "Employees":[
      {
         "Name":{
            "First":"Terri",
            "Middle":"Lee",
            "Last":"Duffy"
         },
         "PII":{
            "DOB":"1971-08-01",
            "NatID":"245797967"
         },
         "LoginID":"adventure-works\\terri0"
      },
      {
         "Name":{
            "First":"Roberto",
            "Last":"Tamburello"
         },
         "PII":{
            "DOB":"1974-11-12",
            "NatID":"509647174"
         },
         "LoginID":"adventure-works\\roberto0"
      }
   ]
}

如果你將結果與之前的示例比較,將會看到外層元素從一個數組改變爲一個只包含Employees屬性的對象。Employees值現在之前示例中的外層元素。


你或許也注意到了第二個employee,Roberto,沒有包含中間名。那是因爲在原表中MiddleName列爲null。默認,數據庫引擎不包含值爲null的JSON元素。然而,你可以通過添加INCLUDE_NULL_VALUES選項到FOR JSON來重寫該行爲,如下SELECT語句所示:

SELECT
p.FirstName AS [Name.First],
p.MiddleName AS [Name.Middle],
p.LastName AS [Name.Last],
e.BirthDate AS [PII.DOB],
e.NationalIDNumber AS [PII.NatID],
e.LoginID
FROM HumanResources.Employee e INNER JOIN Person.Person p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE e.BusinessEntityID in (2, 3)
FOR JSON PATH, ROOT('Employees'), INCLUDE_NULL_VALUES;

現在結果將會顯示Roberto的中間名爲null,通過分配null值給Middle屬性:

{
   "Employees":[
      {
         "Name":{
            "First":"Terri",
            "Middle":"Lee",
            "Last":"Duffy"
         },
         "PII":{
            "DOB":"1971-08-01",
            "NatID":"245797967"
         },
         "LoginID":"adventure-works\\terri0"
      },
      {
         "Name":{
            "First":"Roberto",
            "Middle":null,
            "Last":"Tamburello"
         },
         "PII":{
            "DOB":"1974-11-12",
            "NatID":"509647174"
         },
         "LoginID":"adventure-works\\roberto0"
      }
   ]
}

當然,使用該從句時有些需要考慮的,參見SQL Server 2016文檔。與此同時,讓我們看看如何轉換JSON片段到傳統的行集數據。


使用OPENJSON函數轉換JSON到行集數據


爲了返回JSON片段爲行集數據,我們使用OPENJSON行集函數轉換數據爲關係型格式。該函數返回三個值:

. key:對象中的屬性名或者數組中元素的索引。

. value:對象中的屬性值或者通過指定索引的數組元素值。

. type:值的數據類型,以數字表示,如下表所描述:

Numeric value

Data type

0

null

1

string

2

int

3

true or false

4

array

5

object


爲了測試OPENJSON函數如何工作,讓我們分配一個JSON片段到一個變量,然後使用該函數去調用這個變量,如下示例所示:

DECLARE @json NVARCHAR(MAX) = N'
{
"FirstName":null,
"LastName":"Duffy",
"NatID":245797967,
"Current":false,
"Skills":["Dev","QA","PM"],
"Region":{"Country":"Canada","Territory":"North America"}
}';
SELECT * FROM OPENJSON(@json);

這個JSON片段包含對每個數據類型包含一個屬性的單一對象。SELECT語句在FROM從句中使用OPENJSON行集函數來獲取JSON數據爲行集,顯示爲如下結果:

key

value

type

FirstName

NULL

0

LastName

Duffy

1

NatID

245797967

2

Current

false

3

Skills

["Dev","QA","PM"]

4

Region

{"Country":"Canada","Territory":"North America"}

5


注意到結果中的type列對於每個值標識了數據類型。如所期待的,該列顯示Skills的值爲一個數組,將所有的數組元素包含在一行結果中。同樣看到Region的值,是一個對象。該行包含對象中的所有屬性。


在某些情況下,你會只想返回key和value列,因此你會指定這些列在SELECT列表中:

SELECT [key], value
FROM OPENJSON(@json);

注意到你必須限定key列,因爲微軟選擇返回一個列表也是一個T-SQL保留字。如下表所示,結果只包含兩列:

key

value

FirstName

NULL

LastName

Duffy

NatID

245797967

Current

false

Skills

["Dev","QA","PM"]

Region

{"Country":"Canada","Territory":"North America"}


現在讓我們繼續一個更爲複雜的JSON片段,我們將在這篇文章中作爲保留示例:

{
   "Employees":[
      {
         "Name":{
            "First":"Terri",
            "Middle":"Lee",
            "Last":"Duffy"
         },
         "PII":{
            "DOB":"1971-08-01",
            "NatID":"245797967"
         },
         "LoginID":"adventure-works\\terri0"
      },
      {
         "Name":{
            "First":"Roberto",
            "Middle":null,
            "Last":"Tamburello"
         },
         "PII":{
            "DOB":"1974-11-12",
            "NatID":"509647174"
         },
         "LoginID":"adventure-works\\roberto0"
      }
   ]
}

這裏顯示的JSON輸出來自於上一個示例中的相應部分產生的。你重新調用,數據庫引擎實際上會比這裏顯示的更不易閱讀的格式輸出JSON,當分配JSON到一個變量時它更容易工作。因此這就是我們將會在接下來示例中採取的措施:

DECLARE @json NVARCHAR(MAX) = N'{"Employees":[{"Name":{"First":"Terri","Middle":"Lee","Last":"Duffy"},"PII":{"DOB":"1971-08-01","NatID":"245797967"},"LoginID":"adventure-works\\terri0"},{"Name":{"First":"Roberto","Middle":null,"Last":"Tamburello"},"PII":{"DOB":"1974-11-12","NatID":"509647174"},"LoginID":"adventure-works\\roberto0"}]}';

如果你計劃去嘗試下一批示例,你將對每個使用變量定義,避免了所有當通過分析器運行結果時獲得空格。現在讓我們使用OPENJSON函數去變量中轉換JSON:

SELECT [key], value
FROM OPENJSON(@json);

這個示例最基本的使用OPENJSON,不用定義其他參數。結果,SELECT語句對於Employees數組只返回單一行,如下表所示:

key

value

Employees

[{"Name":{"First":"Terri","Middle":"Lee","Last":"Duffy"},"PII":{"DOB":"1971-08-01","NatID":"245797967"},"LoginID":"adventure-works\\terri0"},{"Name":{"First":"Roberto","Middle":null,"Last":"Tamburello"},"PII":{"DOB":"1974-11-12","NatID":"509647174"},"LoginID":"adventure-works\\roberto0"}]


爲了更好的控制我們的結果,我們需要傳遞第二個參數到OPENJSON函數。該參數是一個JSON路徑,命令數據庫引擎如何解析數據。例如,下面的路徑命令數據庫引擎基於Employees屬性返回數據:

SELECT [key], value
FROM OPENJSON(@json, '$.Employees');

當你指定一個JSON路徑時,你使用一個美元符號($)開始以表明這個條目存在於當前的上下文中。你然後指定一個或更多元素,因爲它們分等級的出現在JSON片段中,使用階段分割元素。在這種情況下,路徑只指定了根元素,Employees,將結果顯示在如下表中:

key

value

0

{"Name":{"First":"Terri","Middle":"Lee","Last":"Duffy"},"PII":{"DOB":"1971-08-01","NatID":"245797967"},"LoginID":"adventure-works\\terri0"}

1

{"Name":{"First":"Roberto","Middle":null,"Last":"Tamburello"},"PII":{"DOB":"1974-11-12","NatID":"509647174"},"LoginID":"adventure-works\\roberto0"}


這次,我們對Employees數組中的每個元素獲得一行。如果我們想就愛那個結果進一步分割,我們必須逐步減少層次結構。例如,參考Employees數組中的一個元素,我們必須指定該元素的索引,因爲它存在於數組中。一個數組的索引是以零開始的,意味着索引計數以0開始,因此如果我們想獲取Employees數組中的第一個元素,我們必須在root名稱後在中括號中指定0,顯示爲如下語句:

SELECT [key], value
FROM OPENJSON(@json, '$.Employees[0]');

Employees數組中的第一個元素是一個包含三個屬性的JSON對象,那是SELECT語句返回的,顯示爲如下結果:

key

value

Name

{"First":"Terri","Middle":"Lee","Last":"Duffy"}

PII

{"DOB":"1971-08-01","NatID":"245797967"}

LoginID

adventure-works\terri0


因爲前兩個值是對象,這些對象的完整內容返回。然後,我們可以通過指定對象名稱只返回這些對象中的一個:

SELECT [key], value
FROM OPENJSON(@json, '$.Employees[0].Name');

現在SELECT語句只返回Name對象中的三個屬性:

key

value

First

Terri

Middle

Lee

Last

Duffy


我們看到的OPENJSON示例,當返回數據爲行集時,使用了默認的架構,但是有些限制有關如何控制結果。幸運的是,OPENJSON函數也讓我們添加一個WITH從句到我們的SELECT語句爲了定義一個顯式架構。在下面的示例中,該架構格式化我們的數據,因此我們可以很容易對每個employee看到詳細信息:

SELECT *
FROM OPENJSON(@json, '$.Employees')
WITH([Name.First] NVARCHAR(25), [Name.Middle] NVARCHAR(25),
[Name.Last] NVARCHAR(25), [PII.DOB] DATE, [PII.NatID] INT);

WITH從句指定每個列,使用關聯到原始JSON的名字。例如,Name.First列返回employee的名字。該列名稱基於Name對象的First屬性。對於每個列,我們也提供了一個T-SQL數據類型。SELECT語句現在返回結果顯示在如下表中:

Name.First

Name.Middle

Name.Last

PII.DOB

PII.NatID

Terri

Lee

Duffy

1971-08-01

245797967

Roberto

NULL

Tamburello

1974-11-12

509647174


如果我們想定義更多可讀的列名稱,我們可以替代創建列定義,每個包含新名稱,跟隨數據類型和路徑參照,如下示例所示:

SELECT *
FROM OPENJSON(@json, '$.Employees')
WITH(FirstName NVARCHAR(25) '$.Name.First',
MiddleName NVARCHAR(25) '$.Name.Middle',
LastName NVARCHAR(25) '$.Name.Last',
BirthDate DATE '$.PII.DOB',
NationalID INT '$.PII.NatID');

注意到,對於路徑,我們不需要參照Employees數組自身。讓我們關注OPENJSON函數。但是我們仍需要指定美元符號去顯示當前上下文。我們然後跟隨Name或PII對象名稱,然後屬性名稱。SELECT語句現在返回結果顯示在如下表中:

FirstName

MiddleName

LastName

BirthDate

NationalID

Terri

Lee

Duffy

1971-08-01

245797967

Roberto

NULL

Tamburello

1974-11-12

509647174


接下來的示例將會給出一個基本的關於如何將JSON片段轉換爲行集數據的方法。再一次,參考SQL Server 2016文檔去獲取更多關於如何使用OPENJSON函數的規範。


在SQL Server 2016中更多JSON函數


除了OPENJSON,SQL Server 2016包含其他一些函數用於處理JSON數據。我們將學習如何使用ISJSON,JSON_VALUE和JSON_QUERY函數。


ISJSON

ISJSON函數讓你測試一個字符串是否正確的以JSON格式化。這是一個特別重要的函數,考慮到SQL Server 2016不支持JSON數據類型。至少這種方式,你有方法驗證你的數據。


如果一個字符串是有效的JSON值,ISJSON函數返回1,否則返回0。唯一的異常是,如果字符串爲null,此時函數返回null。下面的SELECT語句測試普遍存在的@json變量來驗證是否有效:

SELECT CASE
WHEN ISJSON(@json) > 0
THEN 'The variable value is JSON.'
ELSE 'The variable value is not JSON.'
END;

如我們所希望的,SELECT語句返回如下結果:

The variable value is JSON.

現在讓我們通過不賦值標記Age元素來傳遞無效的JSON到文本:

DECLARE @json2 NVARCHAR(MAX) = N'
{"First":"Terri","Middle":"Lee","Last":"Duffy","Age"}';
SELECT CASE
WHEN ISJSON(@json2) > 0
THEN 'The variable value is JSON.'
ELSE 'The variable value is not JSON.'
END;

如我們所希望的,我們得到第二種結果:

The variable value is not JSON.


JSON_VALUE

SQL Server 2016中另一個手頭JSON相關的函數是JSON_VALUE,讓我們從一個JSON片段中抽取一個標量值,如下示例所示:

SELECT JSON_VALUE(@json, '$.Employees[0].Name.First');

JSON_VALUE函數傳入兩個參數。第一個是JSON自身,第二個是一個定義了我們想獲取的元素的值的路徑。在這裏,路徑指定了Name對象的First屬性,它是Employees數組的第一個元素的一部分。如我們所期待,SELECT語句返回了值Terri。


我們可以容易的對第二個employee返回NatID值。

SELECT JSON_VALUE(@json, '$.Employees[1].PII.NatID');

現在這個SELECT語句返回509647174。假設,我們而是去獲取一些非標量值。例如,如下路徑對第二個employee只指定PII對象:

SELECT JSON_VALUE(@json, '$.Employees[1].PII');

這次,SELECT語句返回一個null值。默認,如果路徑不存在或者不匹配當前情況,數據庫引擎返回null值。在這個例子中,我們指定了一個不能返回標量值的元素,因此數據引擎返回了null值。


當在JSON相關表達式中指定一個路徑,你可以通過使用lax或strict選項處理路徑來控制結果。lax選項是默認值,如果沒有指定,會被隱式指定,意思是如果一個問題觸發,數據庫引擎返回null值。例如,如下路徑限制包含lax選項:

SELECT JSON_VALUE(@json, 'lax $.Employees[1].PII');

輸出語句再次返回null值,因爲我們指定了一個不能返回標量值的元素。我們替代指定了strict選項,這這裏,如果問題出現,數據庫引擎將報錯:

SELECT JSON_VALUE(@json, 'strict $.Employees[1].PII');

這次我們收到了非常不一樣的結果:

Property cannot be found in specified path.


JSON_QUERY

另一個JSON相關的工具是JSON_QUERY函數,從一個JSON片段中抽取了一個對象或數組。例如,以下SELECT語句對第二個employee獲取PII對象:

SELECT JSON_QUERY(@json, 'strict $.Employees[1].PII');

像JSON_VALUE函數一樣,JSON_QUERY函數傳入兩個參數:JSON源和包含要抽取數據的路徑。SELECT語句返回的結果如下:

{"DOB":"1974-11-12","NatID":"509647174"}

如果我們想去返回一個Employees數組,我們只需要指定$.Employees作爲我們的路徑:

SELECT JSON_QUERY(@json, 'strict $.Employees');

現在SELECT語句只返回JSON片段中的內容:

[{"Name":{"First":"Terri","Middle":"Lee","Last":"Duffy"},"PII":{"DOB":"1971-08-01","NatID":"245797967"},"LoginID":"adventure-works\\terri0"},{"Name":{"First":"Roberto","Middle":null,"Last":"Tamburello"},"PII":{"DOB":"1974-11-12","NatID":"509647174"},"LoginID":"adventure-works\\roberto0"}]


總結:JSON和SQL Server 2016


本文開始讓你在SQL Server中使用JSON數據。然而,如你所見,JSON支持不如XML支持那樣完善。如果你也正在維護其他數據庫管理系統,你會很快發現在SQL Server 2016中的JSON屬性還有很多工作要迎頭趕上在其他產品中已經實現的。


即便如此,SQL Server 2016聊勝於無,JSON支持被證明是很實用的。事實上,對一些組織,在SQL Server 2016中已經實現的屬性將足夠滿足他們的需求。首先,JSON相關的功能簡單、易用,你應該相對不用什麼煩惱就能應用到你的工作中。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章