我有一个嵌套的XML,我想插入到SQL中。
导入XML:
.gitignore
我想通过XQuery将其转换为:
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
因此我可以将其导入SQL。
有什么想法吗?
答案 0 :(得分:0)
只需将每个RECORD
映射到一个新的映射,即可将所有FIELD
映射到名称从NAME到VALUE的元素:
RECORD !
<RECORD>
{
RECID,
FIELD ! element { NAME } { data(VALUE) }
}
</RECORD>
https://xqueryfiddle.liberty-development.net/nbUY4kB
对于XQuery 1,您需要使用for return
而不是地图运算符!
:
for $record in //RECORD
return
<RECORD>
{
$record/RECID,
for $field in $record/FIELD
return element { $field/NAME } { data($field/VALUE) }
}
</RECORD>
答案 1 :(得分:0)
我尝试过:
DECLARE @xml xml;
SET @xml =N'
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
';
SELECT @xml.query('
for $record in //RECORD
return
<RECORD>
{
$record/RECID,
for $field in $record/FIELD
return element { $field/NAME } { data($field/VALUE) }
}
</RECORD>
' ) as result
但是我在 return元素部分出现错误: XQuery [query()]:计算元素和属性构造函数的名称表达式仅支持常量表达式。
答案 2 :(得分:0)
正如Martin Honnen指出的那样,MS SQL Server XQuery不支持计算的 dynamic 元素名称,而仅支持文字。不幸的是,甚至包括最新的SQL Server2019。这是一个丑陋的解决方案。
SQL
DECLARE @xml XML = N'<root>
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99901</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2019</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>19</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE>wow</VALUE>
</FIELD>
</RECORD>
</root>';
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, RECID VARCHAR(10), [col_name] VARCHAR(20), [col_value] VARCHAR(100));
INSERT INTO @tbl
SELECT c.value('(../RECID/text())[1]', 'VARCHAR(100)') AS [RECID]
, c.value('(NAME/text())[1]', 'VARCHAR(30)') AS [name]
, c.value('(VALUE/text())[1]', 'VARCHAR(100)') AS [value]
FROM @xml.nodes('root/RECORD/FIELD') AS t(c);
DECLARE @RowCount INT = (SELECT MAX(ID) FROM @tbl)
, @recID varchar(10) = (SELECT TOP(1) RECID FROM @tbl WHERE ID = 1)
, @xml_data VARCHAR(MAX) = '<root><RECORD>';
WHILE @RowCount > 0 BEGIN
SELECT @xml_data += IIF(@recID != RECID, '</RECORD><RECORD>', '') +
--'<' + [col_Name] + '>' + COALESCE([col_value],'') + '</' + [col_Name] + '>'
CONCAT('<',[col_Name],'>',[col_value],'</',[col_Name],'>')
, @recID = RECID
FROM @tbl
ORDER BY ID DESC OFFSET @RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
SET @RowCount -= 1;
END;
SET @xml_data += '</RECORD></root>';
SELECT CAST(@xml_data AS XML);
答案 3 :(得分:0)
这是最终版本,可以选择将其插入SQL:
DECLARE @xml XML = N'
<AVXML>
<SIGNONMSGRS>
<DTSERVER>2019-09-10T15:54:32</DTSERVER>
<APPID>ACCOUNTVIEW</APPID>
<APPVER>0908-</APPVER>
</SIGNONMSGRS>
<EBUSMSGSRS>
<EBUSQRYRS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99901</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2019</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>19</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE>wow</VALUE>
</FIELD>
</RECORD>
</EBUSQRYRS>
</EBUSMSGSRS>
</AVXML>
';
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, RECID VARCHAR(10), [col_name] VARCHAR(20), [col_value] VARCHAR(100));
INSERT INTO @tbl
SELECT c.value('(../RECID/text())[1]', 'VARCHAR(100)') AS [RECID]
, c.value('(NAME/text())[1]', 'VARCHAR(30)') AS [name]
, c.value('(VALUE/text())[1]', 'VARCHAR(500)') AS [value]
FROM @xml.nodes('//RECORD/FIELD') AS t(c);
DECLARE @RowCount INT = (SELECT MAX(ID) FROM @tbl)
, @recID varchar(10) = (SELECT TOP(1) RECID FROM @tbl WHERE ID = 1)
, @xml_data VARCHAR(MAX) = '<root><RECORD>';
WHILE @RowCount > 0 BEGIN
SELECT @xml_data +=
IIF(@recID != RECID,
'<RECID>' + @recID + '</RECID>' +
'</RECORD><RECORD>',
'') +
CONCAT('<',[col_Name],'>',[col_value],'</',[col_Name],'>')
, @recID = RECID
FROM @tbl
ORDER BY ID DESC OFFSET @RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
SET @RowCount -= 1;
END;
SET @xml_data += '<RECID>' + @recID + '</RECID>' + '</RECORD></root>';
DECLARE @handler int;
exec sys.sp_xml_preparedocument @handler OUTPUT, @xml_data;
--print @xml_data
select *
from OPENXML(@handler,'/root/RECORD',11)
WITH
(
id nvarchar(50) 'RECID',
proj_code nvarchar(50) 'proj_code',
sub_nr nvarchar(50) 'sub_nr',
proj_desc nvarchar(1000) 'proj_desc',
pro_stat nvarchar(50) 'pro_stat',
comment nvarchar(50) 'comment'
)
exec sys.sp_xml_removedocument @handler