我有一个存储过程,它有一个XML输入参数。我想在XML中使用null值,但是当我尝试使用OpenXML进行选择时,我收到转换错误。
Msg 8114,Level 16,State 5,Line 22 将数据类型nvarchar转换为数字时出错。
IF (OBJECT_ID('tempdb..#Migracio') IS NOT NULL)
DROP TABLE #Migracio
CREATE TABLE #Migracio
(
Fee DECIMAL(16, 4) NULL,
Percentage DECIMAL(6, 3)
)
DECLARE @XML XML =
<Elelments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Elelment>
<Fee xsi:nil="true"/>
<Percentage>50</Percentage>
</Elelment>
</Elelments>
DECLARE @h INT
EXEC sp_xml_preparedocument @h OUT, @XML
INSERT INTO [#Migracio] (Fee, Percentage)
SELECT Fee, Percentage FROM OPENXML(@h, '/Elelments/Elelment', 6)
WITH(Fee DECIMAL(16, 4), Percentage DECIMAL(6, 3))
EXEC sp_xml_removedocument @h
SELECT * FROM #Migracio
我该如何解决这个问题?
FROM OPENXML
,以及打开和删除XML的存储过程已经过时,不应再使用了...而是使用XML数据类型提供的native XML-methods。
这个NULL
标记与xsi:nil
不是真的需要。缺少的元素被隐含地视为NULL
值。如果元素的存在是由模式或任何类型的规则强制的,则可以用于区分空字符串或NULL
。看一下这个:
DECLARE @XML XML =
'<Elelments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- your example -->
<Elelment>
<Fee xsi:nil="true" />
<Percentage>50</Percentage>
</Elelment>
<!-- both values are set -->
<Elelment>
<Fee>100</Fee>
<Percentage>50</Percentage>
</Elelment>
<!-- Fee is missing -->
<Elelment>
<Percentage>50</Percentage>
</Elelment>
</Elelments>';
- 这将带回你想要的结果 - 没有任何关于NULL
值的麻烦
SELECT e.value('(Fee/text())[1]','decimal(10,4)') AS Fee
,e.value('(Percentage/text())[1]','decimal(10,4)') AS Percentage
FROM @XML.nodes('/Elelments/Elelment') A(e);
- 那么区别是什么呢?这将返回所有<Elelment>
节点,其中有一个<Fee>
节点。你得到两个节点。找不到丢失的<Elelment>
。
SELECT @XML.query('Elelments/Elelment[Fee]');
- 你可以找到所有<Fee>
,其显式值为xsi:nil="true"
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi)
SELECT @XML.query('Elelments/Elelment[Fee/@xsi:nil="true"]');
顺便问一下:你真的说出这个<Elelment>
吗?第二个“L”在某种程度上打扰了我......
我猜Google可以答案:
How to parse xml in sql server to process NULL value in DateTime DataType
“你需要做的就是省略那些会导致NULL值的属性。”
这可能是唯一的方法吗?