时间:2021-07-01 10:21:17 帮助过:4人阅读
那我们现在先来通过例子来看一下query()和value 两个方法是如何使用XML数据的。需要注意的是我接下来的测试环境是SQLServer2008 R2。实例中包含了ClientDB
数据库、ClientInfoCollection 的
XML数据以及ClientInfo
表。
- USE master;
- GO
- IF DB_ID(‘ClientDB‘) IS NOT NULL
- DROP DATABASE ClientDB;
- GO
- CREATE DATABASE ClientDB;
- GO
- USE ClientDB;
- GO
- IF OBJECT_ID(‘ClientInfoCollection‘) IS NOT NULL
- DROP XML SCHEMA COLLECTION ClientInfoCollection;
- GO
- CREATE XML SCHEMA COLLECTION ClientInfoCollection AS
- ‘<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns="urn:ClientInfoNamespace"
- targetNamespace="urn:ClientInfoNamespace"
- elementFormDefault="qualified">
- <xsd:element name="People">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="Person" minOccurs="1" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="FirstName" type="xsd:string" minOccurs="1" maxOccurs="1" />
- <xsd:element name="LastName" type="xsd:string" minOccurs="1" maxOccurs="1" />
- <xsd:element name="FavoriteBook" type="xsd:string" minOccurs="0" maxOccurs="5" />
- </xsd:sequence>
- <xsd:attribute name="id" type="xsd:integer" use="required"/>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>‘;
- GO
- IF OBJECT_ID(‘ClientInfo‘) IS NOT NULL
- DROP TABLE ClientInfo;
- GO
- CREATE TABLE ClientInfo
- (
- ClientID INT PRIMARY KEY IDENTITY,
- Info_untyped XML,
- Info_typed XML(ClientInfoCollection)
- );
- INSERT INTO ClientInfo (Info_untyped, Info_typed)
- VALUES
- (
- ‘<?xml version="1.0" encoding="UTF-8"?>
- <People>
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
- <Person id="5678">
- <FirstName>Jane</FirstName>
- <LastName>Doe</LastName>
- </Person>
- </People>‘,
- ‘<?xml version="1.0" encoding="UTF-8"?>
- <People xmlns="urn:ClientInfoNamespace">
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
- <Person id="5678">
- <FirstName>Jane</FirstName>
- <LastName>Doe</LastName>
- </Person>
- </People>‘
- );
Listing 1: 创建测试环境和数据
query方法,通常被用来返回一个指定XML子集的无类型的XML实例,如下,用括号加单引号来实现表达式,语法:
db
_object
.query(‘
xquery_exp
‘)
当我们调用这个方法时,用真实数据库对象替换掉引号内的表达式。通过实例来比较一下结果有什么不一样。
- SELECT Info_untyped.query(‘/People‘)
- AS People_untyped
- FROM ClientInfo;
Listing 2: 使用query(
)
来获得<People>元素中的值
在这种情况下,将返回标签下所有的元素,包括子元素属性以及它们的值。
- <People>
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
- <Person id="5678">
- <FirstName>Jane</FirstName>
- <LastName>Doe</LastName>
- </Person>
- </People>
Listing 3: 结果集返回了/People
的内容
假如打算检索类型化的列中的<People>
元素的内容,我需要修改XQuery的表达式。如Listing 4
- SELECT Info_typed.query(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- /ns:People‘) AS People_typed
- FROM ClientInfo;
Listing 4: 使用query(
)
来检索类型化的XML列,然后你运行这个语句,就会得到结果如Listing5
- <People xmlns="urn:ClientInfoNamespace">
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
- <Person id="5678">
- <FirstName>Jane</FirstName>
- <LastName>Doe</LastName>
- </Person>
- </People>
Listing 5: 展示结果
如上,我们发现两种结果是很接近的,唯一的区别就是类型化的列里面包含了涉及的命名空间。
如果我们打算获得子下一级,子元素的内容,我们需要修改表达式,通过添加/Person
到路径名称中,如下:
- SELECT
- Info_untyped.query(
- ‘/People/Person‘) AS People_untyped,
- Info_typed.query(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- /ns:People/ns:Person‘) AS People_typed
- FROM ClientInfo;
Listing 6: 检索 <Person>
元素
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
- <Person id="5678">
- <FirstName>Jane</FirstName>
- <LastName>Doe</LastName>
- </Person>
Listing 7: 这个结果集是非类型化数据的结果
- <ns:Person xmlns:ns="urn:ClientInfoNamespace" id="1234">
- <ns:FirstName>John</ns:FirstName>
- <ns:LastName>Doe</ns:LastName>
- </ns:Person>
- <ns:Person xmlns:ns="urn:ClientInfoNamespace" id="5678">
- <ns:FirstName>Jane</ns:FirstName>
- <ns:LastName>Doe</ns:LastName>
- </ns:Person>
Listing 8: 这个结果集是类型化数据的结果
如果我们打算去得到指定的<Person>下面的某一个元素,需要加入涉及的id属性。下面对比类型和非类型的两种情况下指定元素属性时如何获取。
- SELECT
- Info_untyped.query(
- ‘/People/Person[@id=1234]‘) AS People_untyped,
- Info_typed.query(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- /ns:People/ns:Person[@id=5678]‘) AS People_typed
- FROM ClientInfo;
Listing 9: 检索数据,指定元素
前面的没有变化,按照元素来添加表达式,然后用中括号,在中括号内添加了@id的值,结果如下
- <Person id="1234">
- <FirstName>John</FirstName>
- <LastName>Doe</LastName>
- </Person>
Listing 10: id为1234非类型化数据结果返回值。
对于类型化的列,我使用的id为5678.注意,这次不再需要在属性名称前加上命名空间的前缀了,只需要在元素名字前引用就足够了。
- <ns:Person xmlns:ns="urn:ClientInfoNamespace" id="5678">
- <ns:FirstName>Jane</ns:FirstName>
- <ns:LastName>Doe</ns:LastName>
- </ns:Person>
Listing 11: id为5678的数据结果
更进一步的展示结果,向下一级
- SELECT
- Info_untyped.query(
- ‘/People/Person[@id=1234]/FirstName‘) AS People_untyped,
- Info_typed.query(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- /ns:People/ns:Person[@id=5678]/ns:FirstName‘) AS People_typed
- FROM ClientInfo;
结果
- <FirstName>John</FirstName>
- <ns:FirstName xmlns:ns="urn:ClientInfoNamespace">Jane</ns:FirstName>
Listing 14: 名字的结果的展示
当然还可以通过数字索引的方式展示:
- SELECT
- Info_untyped.query(
- ‘/People/Person[1]/FirstName‘) AS People_untyped,
- Info_typed.query(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- /ns:People/ns:Person[2]/ns:FirstName‘) AS People_typed
- FROM ClientInfo;
Listing 15: 使用数字索引来引用元素下的结果
就如同query()方法一样简便,很多时候当你想去检索一个特定的元素或属性的时候,而不是获取XML的元素,那就可以使用value()了。这种方法只会返回一个特定的值,不作为数据类型。因此一定要传递两个参数XQuery表达式和T-SQL数据类型。下面看语法:
db
_object
.value(‘
xquery_exp
‘, ‘
sql_type
‘)
- SELECT
- Info_untyped.value(
- ‘(/People/Person[1]/FirstName)[1]‘,
- ‘varchar(20)‘) AS Name_untyped,
- Info_typed.value(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- (/ns:People/ns:Person[2]/ns:FirstName)[1]‘,
- ‘varchar(20)‘) AS Name_typed
- FROM ClientInfo;
Listing 16: 检索<FirstName>
的值
在Listing16中,我指定了[1]在Xquery表达式的后面,所以结果集将只返回第一个人的名字。
- Name_untyped Name_typed
- -------------------- --------------------
- John Jane
Listing 17: <FirstName>的两个结果
当然,我们也可以检索每个实例的id的属性值,并且指定Int类型返回。
- SELECT
- Info_untyped.value(
- ‘(/People/Person/@id)[1]‘,
- ‘int‘) AS Name_untyped,
- Info_typed.value(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- (/ns:People/ns:Person/@id)[2]‘,
- ‘int‘) AS Name_typed
- FROM ClientInfo;
Listing 19: 检索两个实例的id属性值
- Name_untyped Name_typed
- -------------------- --------------------
- 1234 5678
Listing 20: 返回两个id的属性
除了在表达式中定义你的XQuery表达式,你也能聚合的功能来进一步定义你的查询和操作数据。例如,count()功能,我们来获取每个列中<Person>
元素的个数。
- SELECT
- Info_untyped.value(
- ‘count(/People/Person)‘,
- ‘int‘) AS Number_untyped,
- Info_typed.value(
- ‘declare namespace ns="urn:ClientInfoNamespace";
- count(/ns:People/ns:Person)‘,
- ‘int‘) AS Number_typed
- FROM ClientInfo;
Listing 21: 使用count功能来检索元素个数
结果如下:
- Number_untyped Number_typed
- -------------- ------------
- 2 2
Listing 22: 每列数据中<Person>
元素的数量
另外一个常用的功能是concat(
)
, 它可以连接两个或多个XML元素下的数据。你可以指定你想连接的每一个部分。示例:
- SELECT
- Info_untyped.value(
- ‘concat((/People/Person/FirstName)[2], " ",
- (/People/Person/LastName)[2])‘,
- ‘varchar(25)‘) AS FullName
- FROM ClientInfo;
Listing 23: 使用concat(
)来连接数值
- FullName
- -------------------------
- Jane Doe
Listing 24: 连接后的返回值
名和姓被连接起来,组成一个单一的值。都来自于同一个<Person>
下,当然也可以来自不同。
我们基本上了解了XML在SQLServer 中的简单应用,从定义到使用方法。也看到了query()检索子集,也能使用value()检索独立的元素属性的值。当然除此之外还有向exist(
)
andnodes()
这样方法,配合语法都以应用,这部分就不再展开讲了,大同小异。有不明白的可以私聊。更多使用方法还请访问MSDN来获取(搜索XQuery language reference)。
XML 在SQLServer中的使用
标签: