sql server表中未知行和列的“非法xml字符”错误消息

3vpjnl9f  于 2021-08-09  发布在  Java
关注(0)|答案(2)|浏览(581)

我试图解析SQLServer上数据表中的xml列,将内容转换为我试图创建的dataframe中的新列。我一直在犯错误
消息9420,16级,状态1,行1
xml解析:第20行,character 2005,非法的xml字符
我不知道怎么解决这个问题。并非每行的xml列中都存在此非法字符。
我的sql代码能够解析570000行,然后它碰到一个非法字符的行并停止运行。我的where子句应该解析并提取1200000行。因此,代码能够在退出之前成功地解析所需行的不到一半。xml列存储为varchar,因此我确实需要转换为xml来解析内容。
这个sql代码确实有效。它处理原始数据,其中包含生产数据和假测试数据的混合。我能够访问只用于生产的表,正是在这个表中我遇到了错误。数据传输到仅生产表时一定发生了什么。
我试着在帖子里搜索一些有用的东西,但什么也找不到。我不知道如何在我正在处理的1.2m记录中找到错误,也不知道是哪个解析列导致了问题。解析算法是否有方法跳过有问题的行并继续解析剩余的记录?
我的代码是:

SELECT [Id]
      ,[EventDateTime]
      ,[TenantId]
      ,[EventType]
      ,[EventXml]
      ,[InsertDateTime]
      ,[AppInstanceId]
      ,[TokenCorrelationId]
      ,[AuditCorrelationId]
      ,[AuditId]
      ,CAST([EventXml] as XML).value('/PrescriptionEvent [1]/DateTimeStamp[1]','NVARCHAR(max)') AS xml_DateTimeStamp 
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/AuditCorrelationId[1]','NVARCHAR(max)')) AS xml_AuditCorrelationId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/TokenCorrelationId[1]','NVARCHAR(max)')) AS xml_TokenCorrelationId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/ActingUserId[1]/Value[1]','NVARCHAR(max)')) AS xml_ActingUserId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/ActingUserId[1]/LegacyId[1]','NVARCHAR(max)')) AS xml_ActingUserId_LegacyId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/TenantId[1]/Value[1]','NVARCHAR(max)')) AS xml_TenantId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/TenantId[1]/LegacyId[1]','NVARCHAR(max)')) AS xml_TenantId_LegacyId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/AppInstanceId[1]/Value[1]','NVARCHAR(max)')) AS xml_AppInstanceId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/AppInstanceId[1]/LegacyId[1]','NVARCHAR(max)')) AS xml_AppInstanceId_LegacyId
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/ActionType[1]','NVARCHAR(max)')) AS xml_ActionType
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/Outcome[1]','NVARCHAR(max)')) AS xml_Outcome
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/OutcomeReason[1]','NVARCHAR(max)')) AS xml_OutcomeReason
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/RxSigningWorkflowActivity[1]','NVARCHAR(max)')) AS xml_RxSigningWorkflowActivity
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/Waypoint[1]','NVARCHAR(max)')) AS xml_Waypoint
      ,UPPER(CAST([EventXml] as XML).value('/PrescriptionEvent[1]/PrescriptionReferenceId[1]','NVARCHAR(max)')) AS xml_PrescriptionReferenceId
  FROM [EpcsAuditDB].[dbo].[EpcsAuditEventData]
  WHERE [EventType] = 4 AND [EventDateTime] >= '2020-03-24'

xml的例子(这个没有非法字符;不知道如何找到一个包含非法字符):

<?xml version="1.0" encoding="utf-8"?>  <PrescriptionEvent xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    <DateTimeStamp>2020-03-24T19:54:33.0169582Z</DateTimeStamp>    <Outcome>true</Outcome>    <OutcomeReason />    <AuditCorrelationId>3a4fb1cd-c39c-4e84-bfc4-dee98b29be2e</AuditCorrelationId>    <TokenCorrelationId>d80bbd23-2e1d-44b3-9452-972b54f35cc9</TokenCorrelationId>    <ActingUserId>      <Value>91f78a00-ce26-4088-88eb-11x5565910d7</Value>    </ActingUserId>    <TenantId>      <Value>00000000-0000-0000-0000-000000000000</Value>      <LegacyId>10051804</LegacyId>    </TenantId>    <AppInstanceId>      <Value>00000000-0000-0000-0000-000000000000</Value>      <LegacyId>Hospital</LegacyId>    </AppInstanceId>    <PrescriptionReferenceId>ecf5fd42-096e-ea11-a852-005056a9ea50</PrescriptionReferenceId>    <AdditionalPrescriptionReferenceId />    <ActionType>Received</ActionType>    <RxSigningWorkflowActivity>RxArchive</RxSigningWorkflowActivity>    <Waypoint>SMS</Waypoint>  </PrescriptionEvent>
yizd12fk

yizd12fk1#

错误不是由xml中的列引起的,而是因为xml无效。它被转换成xml。
根据您的sql server版本,您应该能够通过以下方式查找错误行:

select EventXml 
from [EpcsAuditDB].[dbo].[EpcsAuditEventData]
where try_cast([EventXml] as XML) is null
uxhixvfz

uxhixvfz2#

可以使用try\u convert查看无效xml内容的数据。下面的poc代码会有所帮助。

DECLARE @tableWithxml table(id int, xmlcontent varchar(500))

INSERT INTO @tableWithxml
values (1,'<x> 1</x>'), (2,'<x 1</x>')

SELECT id, xmlcontent
from
(SELECT id, xmlcontent, try_convert(xml,xmlcontent) as conversionsucceed
from @tableWithxml) as t
where conversionsucceed is null -- failed conversion
+----+------------+
| id | xmlcontent |
+----+------------+
|  2 | <x 1</x>   |
+----+------------+

相关问题