为何无法在T-SQL中启用DTD支持?修复尝试无效求帮助
解决T-SQL中DTD解析报错及数据插入问题
问题根源
- DTD解析时机错误:直接将包含内部子集DTD的字符串赋值给
XML类型变量时,SQL Server会立即尝试解析XML,触发"不允许内部子集DTD"的报错,后续CONVERT操作无法回退这一步的错误。 - XQuery路径不匹配:原XML的根节点是
<customer>,但代码中使用/customers/customer路径,导致无法匹配到任何数据节点。 - 数据类型冲突:XML中
&example;实体解析后是字符串Doe,无法直接转换为DECIMAL(18,2)类型,会引发转换错误。
修正后的完整代码
USE customers; -- 1. 先将XML内容以字符串形式存储,避免提前触发XML解析 DECLARE @xmlContent NVARCHAR(MAX); SET @xmlContent = '<!DOCTYPE replace [<!ENTITY example "Doe"> ]><customer><name>John Doe</name><address>123 Main St, Anytown, USA</address><salary>&example</salary></customer>'; -- 2. 使用CONVERT加style参数2启用DTD支持,转换为XML类型 DECLARE @xmlData XML; SET @xmlData = CONVERT(XML, @xmlContent, 2); -- 3. 修正XQuery路径,并处理salary字段的类型转换问题 INSERT INTO customers (name, address, salary) SELECT T.c.value('(name/text())[1]', 'NVARCHAR(MAX)'), T.c.value('(address/text())[1]', 'NVARCHAR(MAX)'), -- 根据实际业务逻辑调整:这里示例将无效字符串转为NULL,可替换为合理数值或报错处理 CASE WHEN ISNUMERIC(T.c.value('(salary/text())[1]', 'NVARCHAR(MAX)')) = 1 THEN CAST(T.c.value('(salary/text())[1]', 'NVARCHAR(MAX)') AS DECIMAL(18,2)) ELSE NULL END AS salary FROM @xmlData.nodes('/customer') AS T(c); -- 修正路径为根节点<customer>
核心要点
- 启用DTD支持的正确方式:必须先将XML内容保存为
NVARCHAR类型变量,再通过CONVERT(XML, 变量名, 2)完成转换,style参数2专门用于允许内部子集DTD的有限解析。 - XQuery路径匹配:严格对应XML的节点结构,根节点是
<customer>就用/customer,多一层customers会导致无匹配结果。 - 数据类型兼容处理:确保XML中解析后的内容与目标字段类型匹配,对于不兼容的内容,需要添加判断逻辑避免转换报错。
内容的提问来源于stack exchange,提问作者André
相关产品推荐
相关产品推荐

