我正在尝试从XML列中获取特定的属性值,但出现错误
XML解析:第1行,字符345,重复属性
我的代码:
select
ship_to_cust_num,
tank_num,
tank_capacity_qty,
tank_pkg_type_code,
COALESCE(REPLACE(CAST(CAST(b.tank_inspection AS NTEXT) AS XML).value('(/TankInspection/Questions/Question[@AASAQno="9"]/@QAns)[1]', 'VARCHAR(50)'), '#', ''), 0)
from
bulk_site_tank (nolock)b
where
convert(varchar, b.tank_inspection) != 'NULL'
答案 0 :(得分:1)
简单的答案是错误告诉您问题所在。但是要进一步解释。采取以下简单的声明:
DECLARE @xml varchar(MAX);
SET @XML = '
<root>
<child>
<element attribute="1">value</element>
<element attribute="2" attribute="2">Another Value</element>
</child>
</root>';
SELECT *
FROM (VALUES(CONVERT(xml, @XML)))V(X);
如果运行该命令,则会收到错误消息:
消息9437,级别16,状态1,第11行XML解析:第5行,字符46,重复属性
毫不奇怪,就像您看到的那样,第二个element
节点被attribute
声明了两次。
那么,如何解决这个问题?
首先,这意味着您将XML数据存储为xml
数据类型以外的数据类型。 XML应该使用xml
数据类型存储(这正是它的用途),并且只能在其中存储有效的XML。结果,您将无法在行中插入无效的XML,也不会处于该位置。就像你一样,你只能做一件事。找到所有“不良”行:
SELECT tank_inspection
FROM bulk_site_tank
WHERE TRY_CONVERT(xml,tank_inspection) IS NULL
AND tank_inspection IS NOT NULL;
然后检查上述数据集中返回的每一行并修复数据。使其成为有效的XML。然后,修复您的数据类型:
ALTER TABLE bulk_site_tank ALTER COLUMN tank_inspection xml;
现在所有内容都是有效的XML,您可以修复自己的查询:
SELECT ship_to_cust_num,
tank_num,
tank_capacity_qty,
tank_pkg_type_code,
REPLACE(b.tank_inspection.value('(/TankInspection/Questions/Question[@AASAQno="9"]/@QAns)[1]', 'varchar(50)'), '#', '') --AS ?
FROM bulk_site_tank b
WHERE b.tank_inspection IS NOT NULL;
请注意,我更改为ANSI_NULL
语法,并摆脱了NOLOCK
(因为我假设您不知道它在这里实际做什么)。 CAST
/ CONVERT
表达式也消失了,我已经删除了COALESCE
。当您的value
表达式返回varchar(50)
时,COALESCE
的第二个参数为0
。这样会将XML返回的值隐式转换为int
,并可能导致转换错误。
不过,恐怕要由您来清理数据,恐怕没有人可以帮助您。这只是为什么数据类型选择不当会成为问题的原因之一;就像我之前说过的,就好像使用了正确的数据类型一样,永远也不会插入无效的XML。
祝你好运!