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