You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何无法在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 = '&lt;!DOCTYPE replace [&lt;!ENTITY example &quot;Doe&quot;&gt; ]&gt;&lt;customer&gt;&lt;name&gt;John Doe&lt;/name&gt;&lt;address&gt;123 Main St, Anytown, USA&lt;/address&gt;&lt;salary&gt;&amp;example&lt;/salary&gt;&lt;/customer&gt;';

-- 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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:26:05