SQL Server 2016有望提供JSON操作原生支持。這一支持的首次迭代將作為SQL Server 2016 CTP 2的一部分發布。CTP又名社區技術預覽版,等同于微軟的公開Alpha測試,期間,開發者可以提出技術上的修改建議。
JSON導出
“格式化和導出”JSON是CTP 2的主要功能。這可以通過在SELECT語句的末尾增加FOR JSON子句實現。該功能基于FOR XML子句,并且與它類似,允許對結果JSON字符串進行自動和半手工格式化。
微軟希望這一語法可以提供與PostgreSQL的row_to_json和json_object函數相同的功能。
JSON轉換
大部分功能將在CTP 3中發布。這些功能中的第一項是FROM OPENJSON子句,這是一個表值函數(TFV),它接受一個JSON字符串作為輸入。它還需要一個數組或對象在被解析的JSON數據中的路徑。
默認情況下,OPENJSON返回一個鍵值對集合,但開發者可以使用WITH子句提供一個模式。由于JSON不支持日期或整數(它們分別表示為字符串和double類型),所以WITH子句可以減少稍后需要的類型轉換數量。
下面是Jovan Popovic博文中關于JSON支持的例子。
DECLARE @JSalestOrderDetails nVarCar(2000) = N ‘{"OrdersArray": [ {"Number":1, "Date": "8/10/2012", "Customer": "Adventure works", "Quantity": 1200}, {"Number":4, "Date": "5/11/2012", "Customer": "Adventure works", "Quantity": 100}, {"Number":6, "Date": "1/3/2012", "Customer": "Adventure works", "Quantity": 250}, {"Number":8, "Date": "12/7/2012", "Customer": "Adventure works", "Quantity": 2200} ]}‘; SELECT Number, Customer, Date, Quantity FROM OPENJSON (@JSalestOrderDetails, ‘$.OrdersArray‘) WITH ( Number varchar(200), Date datetime, Customer varchar(200), Quantity int ) AS OrdersArray
微軟宣稱,在PostgrSQL中實現同樣的功能需要綜合使用json_each、json_object_keys、json_populate_record和json_populate_recordset函數。
JSON存儲
正如所見,JSON數據存儲在NVARCHAR變量中。在表的列中存儲JSON數據也是這樣。關于為什么這么做,微軟有如下理由:
- 遷移——我們發現,人們早已將JSON存儲為文本,因此,如果我們引入一種單獨的JSON類型,那么為了使用我們的新特性,他們將需要修改數據庫模式,并重新加載數據。而采用現在這種實現方式,開發者不需要對數據庫做任何修改就可以使用JSON功能。
- 跨功能的兼容性——所有SQL Server組件均支持NVARCHAR,因此,JSON也將在所有的組件中得到支持。開發者可以將JSON存儲在Hekaton、時態表或列存儲表中,運用包括行級安全在內的標準安全策略,使用標準B樹索引和FTS索引,使用JSON作為參數或返回過程值,等等。開發者不需要考慮功能X是否支持JSON——如果功能X支持NVARCHAR,那么它也支持JSON。此外,該特性有一些約束——Hekaton及列存儲不支持LOB值,所以開發者只能存儲小JSON文檔。不過,一旦我們在Hekaton及列存儲中增加了LOB支持,那么開發者就可以在任何地方存儲大JSON文檔了。
- 客戶端支持——目前,我們沒有為客戶端應用程序提供標準JSON對象類型(類似XmlDom對象的東西)。自然地,Web和移動應用程序以及JavaScript客戶端將使用JSON文本,并使用本地解析器解析它。在JavaScript中,可以使用object類型表示JSON。我們不太可能實現一些僅在少數RDBMS中存在的JSON類型代理。在C#.Net中,許多開發者使用內置了JObject或JArray類型的JSON.Net解析器;不過,那不是一種標準,也不太可能成為ADO.NET的一部分。即便如此,我們認為,C#應用可以接受來自數據庫層的純字符串,并使用最喜歡的解析器解析它。我們所談論的內容不只是跟應用程序有關。如果開發者試圖在SSIS/SSRS、Tableau和Informatica ETL中使用JSON列,它們會將其視為文本。我們認為,即使我們增加了JSON類型,在SQL Server之外,它仍將被表示成字符串,并根據需要使用某個自定義的解析器解析它。因此,我們并沒有找到任何重大的理由將其實現為一種原生JSON類型。
在包含JSON的NVARCHAR列上使用新的ISJSON函數作為檢查約束是個不錯的主意。如果不這樣做,那么有缺陷的客戶端應用程序就可能插入不可解析的字符串,使開發者面臨數據污染的風險。
JSON查詢
如果直接對JSON進行標量查詢,可以使用JSON_VALUE函數。該函數使用一種類似JavaScript的符號定位JSON對象中的值。它使用$符號表示object的根,點號表示屬性,方括號表示數組索引。它與PostgreSQL中的json_extract_path_text函數等效。
JSON索引
JSON數據可以直接索引,但開發者可以毫不費力地在標量數據上實現同樣的效果。只需要使用JSON_VALUE函數創建一個計算列,然后在這個列上創建索引。
“缺失的”特性
微軟針對JSON的支持計劃中并沒有包含每一個開發者想要的功能。許多人認為,專用的JSONB列類型可以提供更好的性能。其他人希望支持JSON數據修補,而不是必須整個地替換文檔。