天天看點

SQLServer · 特性分析 · XML與JSON應用比較

sql server是一種強大的資料庫引擎,不僅性能卓越,穩定,功能還很強大,sql server 2016中已經支援json。這讓我想到以前工作中經常使用的sql xml,也對比一下他們幾個關鍵領域的應用方法。這兩種sql特性,在實際的工作中也是常用的功能,特别是json在最近發展非常火爆,sql server也不落後,很快就在sql server2016支援。

使用 xml 資料類型,可以将 xml 文檔和片段存儲在 sql server 資料庫中,可以建立 xml 類型的列和變量,并存儲 xml 執行個體。可以選擇性地将 xml 架構集合與 xml 資料類型的列、參數或變量進行關聯。json是一種文本化的資料格式,與xml作為一種資料類型不同,json本身在sql server中隻是一種字元串,用于存儲非結構化的資料。根據以前的經驗,在sql server t-sql應用中,xml應用主要在下面幾個方面:

1. 路徑表達式;

2. 查詢解析;

3. 生成執行個體;

4. 執行個體更改;

5. 索引。

而json其實也是類似的應用。下面将介紹sql xml和sql json具體在這幾個方面的應用,請注意,下面的示例請在sql server 2016 rc3以上版本運作。

xml資料類型自己是沒有路徑表達式,但sql server實作了xquery語言,該語言支援sql server xml資料類型的操作。路徑表達式是xquery最重要的表達式之一,xquery 路徑表達式用于定位文檔中的節點,如元素節點、屬性節點和文本節點。言歸正傳,您需要了解以下概念:

相對路徑表達式由一個或多個步驟組成,步驟間以單斜杠或雙斜杠(/ 或 //)分隔。例如:

child::features 是相對路徑表達式,其中 child 僅指上下文節點的子節點。例如:

表達式 /child::productdescription 中的起始斜杠表示它是一個絕對路徑表達式。 因為表達式開始處的斜杠傳回上下文節點的文檔根節點。

軸包含六個概念child,parent,attribute,seft,descendant-or-self,descendant,其中parent是逆向的,其餘都是正向的。從名字上能夠區分它們的用途。你甚至不必去了解其中含義,看看下面的示例就明白:

上面使用了xml資料類型的操作方法query和value,應用路徑表達式的軸節步驟得到不同結果,對比一下結果,就很清晰了。其中*表示以一個節點測試表示節點名稱。

節點測試是一個條件,并且是路徑表達式中的軸步驟的第二個元件。 在步驟中標明的所有節點都必須滿足此條件,他有兩種節點測試條件:

節點名

節點名包括屬性節點名稱和元素節點名稱。

節點類型

節點類型包括comment(),node(),text(),processing-instruction() ,具體含義你也不必深入下去,有興趣的可自查。

下面用一個示例來說明節點名和節點類型:

在實際應用中,節點測試用得最多的是節點名和text()類型,需要指出的是在處理大量的xml執行個體時,如果解析節點文本,不添加text()節點測試,性能會有所影響,可簡單自測性能。

可能你會在寫路徑表達式的時候會感覺到很繁瑣,那麼,上面兩個執行個體換種方式,就清晰了:

child被省略掉了,這是預設行為,你也不必寫parent節點,直接用兩點代替”..”,屬性用@表示

謂詞通過應用指定的測試來篩選節點序列。 謂詞表達式用方括号括起來并綁定到路徑表達式中的最後一個節點。有點類似我們基礎sql中的謂詞邏輯,比如where條件,你可簡單了解為一種條件關系,看下面的示例:

軸、節點測試和謂詞是軸步驟的要素,還有一般步驟,這個很少用,有興趣可以自行了解。

json中的路徑表達式非常簡單,你隻需要了解下列兩個核心概念就可以随心應手:

json的路徑模式有兩種,一種是lax,另外一種是strict,預設的方式是lax。lax模式在路徑表達式遇到錯誤時傳回為空,而strict模式會抛出錯誤,請運作下列語句:

json資料的上下文引用使用美元符号$表示,json中的各屬性作為路徑關鍵名稱,比如 $.type,如果屬性名稱有空格,需要用雙引号括起來。如果是數組,需要使用方括号表示位置。“.”表示對象的一個成員。例如:

現在我準備了兩個執行個體,一個是xml,一個是json,他們表達的内容是一樣的,以這個執行個體來對比一下查詢解析功能。

xml :

json :

在sql server中,解析經常使用這些方法:query(),nodes(),value(),openxml,有時也用到exist方法來判定條件。

得到執行個體片段非常簡單,使用query方法就好。例如得到customerid=“lilas”的片段customers資訊:

得到元素文本值是最基本的操作,現在要獲得 customerid=”vinet” 的employeeid:

屬性值在路徑表達式說過,可以使用attribute或者@辨別。比如要得到contactname:

現在需要将訂單細節和其他資訊都生成一個結果集,這個可能覺得很麻煩,其實也不難,隻要充分了解路徑表達式,看看可以怎麼做到?有兩種方法:

第一種:nodes()方法

第二種:openxml 方法

如果你對xquery感興趣,你還可以從過這種方式來處理,不過這種方式會比較複雜一點,sql server是支援xquery語言操作,請讀者自行嘗試。

假如你的xml片段存在表中,如果要解析處理,隻需要使用cross apply生成一個多列的結果,用nodes方法就可以了,如果遇到條件,并且與列結合,你可能會用到exist方法和sql:column()來處理,上面的結果已經較複雜,這裡不需要示範了。有興趣可自己實戰一下。

json解析相對xml要簡單得多,沒有屬性值,沒有文本之類。會使用到的方法有:json_query(),json_value,isjson(),openjson() 。

得到執行個體片段,使用json_query方法。例如customerid=“lilas”的片段customers資訊,這裡沒有xml那麼強大,可以通過謂詞來過濾,至少現在沒有看到這個功能。是以隻能指定簡單的數組值。

得到json的某個值,使用json_value方法就好:

得到結果集,json隻提供一種方法openjson,沒有豐富的路徑表達式,是以解析會比較麻煩,下面示例示範與xml生成一樣的結果集:

表列如果存放的是json格式資料,你隻需要注意所有列資料需要用cross join得到所要處理的json對象,其他的也沒有特别的。有興趣可以自己去測試。

生成xml有多種方式,常見的有:常量直接指派,for xml子句,大容量加載:

聲明一個xml資料類型變量,直接給指派,這個是最常見的:

例如:

如何驗證這是一個可用的xml,很簡單,執行一下這個語句,變量是xml,如果你的指派不是xml, 檢查是通不過去的,這個有自檢查機制保證,如果不是合規的,就會抛錯:

for xml子句可以将表内資料直接生成xml執行個體,for xml子句有四種方式:for xml auto,for xml path,for xmlexplicit,for xml raw。

raw 模式

将為 select 語句所傳回行集中的每行生成一個 元素。

auto 模式

将基于指定 select 語句的方式來使用試探性方法在 xml 結果中生成嵌套。 您對生成的 xml 的形狀具有最低限度的控制能力。 除了 auto 模式的試探性方法生成的 xml 形狀之外,還可以編寫 for xml 查詢來生成 xml 層次結構。

explicit 模式

允許對 xml 的形狀進行更多控制。 您可以随意混合屬性和元素來确定 xml 的形狀。 由于執行查詢而生成的結果行集需要具有特定的格式。 此行集格式随後将映射為 xml 形狀。 使用 explicit 模式能夠随意混合屬性和元素、建立包裝和嵌套的複雜屬性、建立用空格分隔的值(例如 orderid 屬性可能具有一列排序順序 id 值)以及混合内容。

path 模式

與嵌套 for xml 查詢功能一起以較簡單的方式提供了 explicit 模式的靈活性。

實際上,用的最多的是auto和path模式,就我個人習慣,一直用path模式。下面一個示例,看看如何建構一個複雜的xml,請注意構造時屬性,元素以及文本的方法:

将下列清單(其實是上面的示例結果)生成一個xml執行個體:

SQLServer · 特性分析 · XML與JSON應用比較

将這個結果集放在一個表中tb_xml_sample。然後需構造為:

下面實作:

關于path(n’’),root(n’’),type等指令,請g一下就明白,主要是生成層次結構及xml正确性驗證。

如果xml是一個檔案,也可以通過openrowset将檔案讀取到sql server中,如果事先不知道 xml 文檔的編碼方式,并且資料在轉換到 xml 之前被作為字元串或二進制資料而不是 xml 資料來傳遞,則建議将資料作為 varbinary 處理。

例如,上面的xml儲存到檔案,然後在sql server中讀出來:

與xml一樣,生成json有多種方式,但常見的有常量直接指派,for json子句,大容量加載。

這個最常用,也是最簡單,但json在sql server是沒有類型存在的,要驗證json是否是合規的,使用isjoin判斷,isjoin為1表示是合規的,為0表示不合規:

for json 有兩種模式,一種是for json auto,另一種是for json path,for json有幾個重要的參數:root(json資料的根節點),include_null_values (處理空間節點時如何顯示),without_array_wrapper(是否使用方括号将對象包起來)。

for json auto模式

for json子句在使用path模式時,可以控制json格式的輸出,可以建立複雜的json對象。

for json path模式

for json子句在使用auto模式時,json輸出的格式是查詢語句自動完成,是以不能靈活控制json的格式。

同樣地,我們以查詢分析語句那示例來構造json對象:

SQLServer · 特性分析 · XML與JSON應用比較

json對象生成,依然用這個表tb_xml_sample:

大容量加載也是通過openrowset ,與xml一樣:

執行個體修改在實際應用中會很少,這裡的修改包括dml_xml,使用modify方法,包括删除,更新和插入。下列一個示例表示所有資訊:

插入 insert

可以插入xml片段,可以插入屬性,文本,注釋,指令,cdata部分資料,請看下面示例:

删除 delete

删除 xml 執行個體的節點。這個非常的簡單:

替代 replace value of 在文檔中更新節點的值。

json的對象修改使用json_modify方法,同樣具有更新,插入,删除等操作,裡面列舉一示例:

文法:json_modify ( expression , path , newvalue ),特别留意path中可以指定lax,strict這個上面已經說過。另外還append關鍵字,表示追加一個新的值到數組中。

上面是sql server在xml和json方面的簡單應用,也是日常工作中經常遇到了,你不必要去了解複雜的xml,xquery,也不必了解那些深奧難懂大概念,用最簡單的執行個體,處理工作總最需要的知識。希望對大家有用。