跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何在SQL Server中通过XML格式批量插入多条数据_使用OPENXML函数

能,但需三步:准备文档句柄、用OPENXML解析为结果集、再INSERT SELECT导入;必须显式清理句柄,且XML结构与WITH子句映射须严格一致。 OPENXML 能不能直接批量插入多条数据? 能,但不是“开箱即用”的批量插入——
OPENXML
本身不执行插入,它只是把 XML 解析成一个临时结果集(类似表),你得再写
INSERT ... SELECT
把它导进去。很多人卡在这一步,以为调了
sp_xml_preparedocument
和
OPENXML
就完事了,结果查不到数据,其实是漏了后续的 INSERT 动作。 必须走三步:准备 → 查询 → 清理 这是
OPENXML
的固定生命周期,跳过任意一步都可能出问题(比如内存泄漏、重复解析、或查不到数据):
sp_xml_preparedocument
返回一个文档句柄(
@hdoc
),必须存为
INT
变量,不能直接嵌套在
OPENXML
里
OPENXML(@hdoc, N'/root/item', 2)
中的
2
表示“属性为中心”模式(attribute-centric),如果 XML 是元素型(如
1
),得改用
1
(元素为中心) 用完必须显式调用
sp_xml_removedocument @hdoc
,否则句柄一直占着,下次
sp_xml_preparedocument
可能返回 0 或报错
XML parsing: line xxx, character yyy, unable to switch the encoding
XML 结构和字段映射对不上,INSERT 就会插空值 常见错误是 XML 标签名和
WITH
子句里的列别名不一致,或者数据类型不兼容(比如 XML 里是字符串
"2024-01-01"
,但目标列是
DATE
,SQL Server 不会自动转换):
DECLARE @hdoc INT; EXEC sp_xml_preparedocument @hdoc OUTPUT, N' '; INSERT INTO users (id, name, created_at) SELECT id, name, CAST(created AS DATE) FROM OPENXML(@hdoc, N'/root/item', 2) WITH ( id INT '@id', name NVARCHAR(50) '@name', created NVARCHAR(10) '@created' ); EXEC sp_xml_removedocument @hdoc;
注意:
@id
中的
@
表示取属性值;如果是子元素,就得写
id INT 'id'
(无
@
);类型要跟
WITH
里声明的一致,不然字段全为 NULL。 比 OPENXML 更简单可靠的替代方案是什么? SQL Server 2005 以后,原生 XML 类型 +
.nodes()
和
.value()
组合更轻量、无需句柄管理、支持索引和类型推导:
DECLARE @xml XML = N' 1Alice 2Bob '; INSERT INTO users (id, name) SELECT T.item.value('(id/text())[1]', 'INT'), T.item.value('(name/text())[1]', 'NVARCHAR(50)') FROM @xml.nodes('/root/item') AS T(item);
这个写法没有句柄泄漏风险,调试也直观;只有当你必须兼容极老版本(SQL Server 2000)或 XML 极大需流式解析时,才值得回到
OPENXML
。实际项目中,90% 的所谓“XML 批量导入”需求,用
.nodes()
就够了。 真正容易被忽略的是:XML 编码声明(如
)如果和实际字节流不匹配,
sp_xml_preparedocument
会静默失败或报编码错误——建议统一用 UTF-16 且省略声明,或用
CONVERT(XML, ...)
预处理校验。

相关文章