对于某些字符串和数字元素,我有一些包含xsi:nil =“true”的XML。这是一个例子:
declare @data xml
set @data = '<?xml version="1.0" encoding="utf-8"?>
<collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<item>
<stringprop1>foo</stringprop1>
<stringprop2 xsi:nil="true" />
<decimalprop3 xsi:nil="true" />
</item>
</collection>'
我想在SQL Server 2008 R2中查询该XML。我正在使用OPENXML,但它不能很好地使用十进制类型。这是我想写的代码:
declare @doc int
exec sp_xml_preparedocument @doc OUTPUT, @data;
select
stringprop1,
stringprop2,
decimalprop3
from openxml(@doc, '/collection/item', 2)
with
(
stringprop1 nvarchar(50)
,stringprop2 nvarchar(50)
,decimalprop3 decimal(18, 5)
)
exec sp_xml_removedocument @doc;
这抱怨将nvarchar转换为十进制。经过一番黑客攻击后,我到达了这里:
exec sp_xml_preparedocument @doc OUTPUT, @data;
select
nullif(stringprop1, '') as stringprop1,
nullif(stringprop2, '') as stringprop2,
convert(decimal(18, 5), nullif(decimalprop3, '')) as decimalprop3
from openxml(@doc, '/collection/item', 2)
with
(
stringprop1 nvarchar(50)
,stringprop2 nvarchar(50)
,decimalprop3 nvarchar(50)
)
exec sp_xml_removedocument @doc;
我想这很好。但有没有办法告诉OPENXML xsi:nil意味着NULL,小数和字符串都可以吗?
答案 0 :(得分:2)
xsi:nil是一种XML Schema功能,OpenXML是在它存在之前设计的,不支持xsi:nil。由于您使用SQL Server 2008,因此使其工作的一种方法是:
使用适当的XML Schema约束XML,验证数据并识别xsi:nil并将其映射为空值。
使用nodes()和value()方法提取数据。
祝你好运 迈克尔
答案 1 :(得分:1)
这应该做:
声明@doc int
exec sp_xml_preparedocument @doc OUTPUT,@ data,'&lt; row xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”/&gt;'
select stringprop1, stringprop2, decimalprop3 from openxml(@doc, '/collection/item', 2) with ( stringprop1 nvarchar(50), stringprop2 nvarchar(50) 'stringprop2[not(@xsi:nil = "true")]', decimalprop3 nvarchar(50) 'decimalprop3[not(@xsi:nil = "true")]' ) exec sp_xml_removedocument @doc;
答案 2 :(得分:0)
不断创新。
这是对我有用的:
-- How to create the XML
/*
DECLARE @xml XML
SET @xml = ( SELECT (SELECT * FROM T_Benutzer FOR XML PATH('row'), ROOT('table'), ELEMENTS xsinil) AS outerXml )
-- SELECT @xml
*/
DECLARE @xml xml
SET @xml = '<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<PLK_UID>7CA68E6E-E998-FF92-BE70-126064765EAB</PLK_UID>
<PLK_Status>1</PLK_Status>
<BLA_UID>00000000-0000-0000-0000-000000000000</BLA_UID>
</row>
<row>
<PLK_UID>C8A19BB1-6B45-67A6-0417-1F455EE8D2E1</PLK_UID>
<PLK_Status>1</PLK_Status>
<BLA_UID xsi:nil="true" />
</row>
<row>
<PLK_UID>C8A19BB1-6B45-67A6-0417-1F455EE8D2E2</PLK_UID>
<PLK_Status xsi:nil="true" />
<BLA_UID xsi:nil="true" />
</row>
<row>
<PLK_UID>C8A19BB1-0000-67A6-0417-1F455EE8D2E3</PLK_UID>
<PLK_Status xsi:nil="true" />
<BLA_UID>C8A19BB1-1111-67A6-0417-1F455EE8D2E1</BLA_UID>
</row>
<row>
<PLK_UID>C8A19BB1-0001-67A6-0417-1F455EE8D2E4</PLK_UID>
<PLK_Status>666</PLK_Status>
<BLA_UID>C8A19BB1-1112-67A6-0417-1F455EE8D2E1</BLA_UID>
</row>
</table>'
DECLARE @handle INT
DECLARE @PrepareXmlStatus INT
EXEC @PrepareXmlStatus = sp_xml_preparedocument @handle OUTPUT, @XML
SELECT
PLK_UID
,PLK_Status
,BLA_UID
FROM OPENXML(@handle, '/table/row', 2) WITH
(
PLK_UID uniqueidentifier 'PLK_UID[not(@*[local-name()="nil" and . ="true"])]'
,PLK_Status int 'PLK_Status[not(@*[local-name()="nil" and . ="true"])]'
,BLA_UID uniqueidentifier 'BLA_UID[not(@*[local-name()="nil" and . ="true"])]'
)
WHERE (1=1) -- AND
EXEC sp_xml_removedocument @handle
如何创建字段列表:
SELECT
CASE WHEN ORDINAL_POSITION = 1 THEN N' ' ELSE N' ,' END
+ N'"' + COLUMN_NAME
+ N'" '
+
CASE
WHEN DATA_TYPE = 'nvarchar' THEN N'national character varying'
WHEN DATA_TYPE = 'varchar' THEN N'character varying'
ELSE DATA_TYPE
END
+
CASE
WHEN DATA_TYPE IN ('char', 'nchar', 'binary') THEN
N'('
+ CAST(CHARACTER_MAXIMUM_LENGTH AS nvarchar(36))
+ N')'
WHEN DATA_TYPE IN ('varchar', 'nvarchar', 'varbinary') THEN
N'(' +
CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN 'MAX' ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS nvarchar(36)) END
+ N')'
WHEN DATA_TYPE IN ('datetimeoffset', 'datetime2', 'time', 'smalldatetime') THEN
N'('
+ CAST(DATETIME_PRECISION AS nvarchar(36))
+ N')'
WHEN DATA_TYPE IN ('decimal', 'numeric') THEN
N'('
+ CAST(NUMERIC_PRECISION AS nvarchar(36))
+ N','
+ CAST(NUMERIC_SCALE AS nvarchar(36))
+ N')'
ELSE N'' -- N'(default)'
END
+ ' ''' + COLUMN_NAME + '[not(@*[local-name()="nil" and . ="true"])]'''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'T_Benutzer'
ORDER BY ORDINAL_POSITION