使用 SQL 服务器中的 OPENXML 解析具有内联模式的 XML 文件
Parsing XML file with inline schema using OPENXML in SQL Server
我正在尝试从 XML 文件中提取数据并使用 SQL 服务器中的 OPENXML 存储到 SQL table。但是,查询 returns 没有。
XML数据
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1"/>
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>
SQL查询
DECLARE @xmlStr xml;
DECLARE @idoc INT
SELECT @xmlStr = BulkColumn FROM OPENROWSET(
BULK 'D:\ogridroles.xml',
SINGLE_BLOB) AS DATA;
EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlStr;
SELECT *
FROM OPENXML (@idoc, '/root/ogridroles',2)
WITH (
ogrid_cde int 'ogrid_cde',
role varchar(1) 'role')
EXEC sp_xml_removedocument @idoc
我想提取元素的所有行值
ogrid_cde
角色
我不太擅长模式,所以我使用另一种方法来解码 XML:
DECLARE @x XML = 'bla bla bla'
DECLARE @idoc INT
EXEC sp_xml_preparedocument @idoc OUTPUT ,@x
SELECT * INTO #t
FROM OPENXML (@idoc, '/',2)
EXEC sp_xml_removedocument @idoc
SELECT [ogrid_cde] = t3.text, [role] = t4.text
FROM #t as t1
INNER JOIN #t as t2 ON t1.parentid = t2.parentid
INNER JOIN #t as t3 ON t1.id = t3.parentid
INNER JOIN #t as t4 ON t2.id = t4.parentid
WHERE t1.localname = 'ogrid_cde' and t2.localname = 'role'
通过 FROM OPENXML
的方法(连同准备和删除文档的过程)已经过时,不应再使用。
native methods of the XML-type 要好得多。试试这个:
你的XML
DECLARE @xml XML=
N'<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1" />
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>';
--查询
WITH XMLNAMESPACES(DEFAULT 'urn:schemas-microsoft-com:sql:SqlRowSet1')
SELECT OgrRol.value('(ogrid_cde/text())[1]','int') AS ogrid_cde
,OgrRol.value('(role/text())[1]','nvarchar(10)') AS [role]
FROM @xml.nodes('/*:root/ogridroles') A(ogrRol);
结果
ogrid_cde role
28 T
75 T
93 O
135 O
简短说明
您可以忽略此处的 XML-schema。这对于检查数据完整性和有效性很有用。但假设数据是正确的,我们就可以读取它。
有一个(重复定义的)默认命名空间。但是 - 这很重要! - 元素 <root>
本身 不存在 在这个命名空间中!
随和,我刚刚使用 命名空间通配符 来使用 *:root
来处理这个元素。一般来说,最好避免通配符,但在这种情况下,这似乎是 acceptable.
我们使用 .nodes()
得到所有 <ogridroles>
元素的派生 table。然后我们使用.value()
读取代码的text()
节点和角色元素。
希望这对您有所帮助,编码愉快!
我正在尝试从 XML 文件中提取数据并使用 SQL 服务器中的 OPENXML 存储到 SQL table。但是,查询 returns 没有。
XML数据
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1"/>
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>
SQL查询
DECLARE @xmlStr xml;
DECLARE @idoc INT
SELECT @xmlStr = BulkColumn FROM OPENROWSET(
BULK 'D:\ogridroles.xml',
SINGLE_BLOB) AS DATA;
EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlStr;
SELECT *
FROM OPENXML (@idoc, '/root/ogridroles',2)
WITH (
ogrid_cde int 'ogrid_cde',
role varchar(1) 'role')
EXEC sp_xml_removedocument @idoc
我想提取元素的所有行值
ogrid_cde
角色
我不太擅长模式,所以我使用另一种方法来解码 XML:
DECLARE @x XML = 'bla bla bla'
DECLARE @idoc INT
EXEC sp_xml_preparedocument @idoc OUTPUT ,@x
SELECT * INTO #t
FROM OPENXML (@idoc, '/',2)
EXEC sp_xml_removedocument @idoc
SELECT [ogrid_cde] = t3.text, [role] = t4.text
FROM #t as t1
INNER JOIN #t as t2 ON t1.parentid = t2.parentid
INNER JOIN #t as t3 ON t1.id = t3.parentid
INNER JOIN #t as t4 ON t2.id = t4.parentid
WHERE t1.localname = 'ogrid_cde' and t2.localname = 'role'
通过 FROM OPENXML
的方法(连同准备和删除文档的过程)已经过时,不应再使用。
native methods of the XML-type 要好得多。试试这个:
你的XML
DECLARE @xml XML=
N'<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1" />
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>';
--查询
WITH XMLNAMESPACES(DEFAULT 'urn:schemas-microsoft-com:sql:SqlRowSet1')
SELECT OgrRol.value('(ogrid_cde/text())[1]','int') AS ogrid_cde
,OgrRol.value('(role/text())[1]','nvarchar(10)') AS [role]
FROM @xml.nodes('/*:root/ogridroles') A(ogrRol);
结果
ogrid_cde role
28 T
75 T
93 O
135 O
简短说明
您可以忽略此处的 XML-schema。这对于检查数据完整性和有效性很有用。但假设数据是正确的,我们就可以读取它。
有一个(重复定义的)默认命名空间。但是 - 这很重要! - 元素 <root>
本身 不存在 在这个命名空间中!
随和,我刚刚使用 命名空间通配符 来使用 *:root
来处理这个元素。一般来说,最好避免通配符,但在这种情况下,这似乎是 acceptable.
我们使用 .nodes()
得到所有 <ogridroles>
元素的派生 table。然后我们使用.value()
读取代码的text()
节点和角色元素。
希望这对您有所帮助,编码愉快!