提问人:Nelson 提问时间:5/6/2022 最后编辑:James ZNelson 更新时间:5/6/2022 访问量:93
在没有循环的情况下将 Xml 数据转换为 sql server 中的表?
Convert Xml data into a table in sql server without loop?
问:
我有xml格式的数据。我需要插入到员工和工资表中
DECLARE @XmlInput XML = '<Office>
<Employee>
<EUID>xyz</EUID>
<FirstName>Ram</FirstName>
<MiddleName>J</MiddleName>
<LastName>D</LastName>
<Salary>
<Monthly>
<Year>2022</Year>
<Month>01</Month>
<Day>31</Day>
<Sal>
<Amt>100000</Amt>
</Sal>
</Monthly>
<Monthly>
<Year>2022</Year>
<Month>02</Month>
<Day>28</Day>
<Sal>
<Amt>90000</Amt>
</Sal>
</Monthly>
</Salary>
<Dept>CSE</Dept>
</Employee>
<Employee>
<EUID>abc</EUID>
<FirstName>Krishna</FirstName>
<MiddleName>R</MiddleName>
<LastName>G</LastName>
<Salary>
<Monthly>
<Year>2022</Year>
<Month>01</Month>
<Day>31</Day>
<Sal>
<Amt>50000</Amt>
</Sal>
</Monthly>
<Monthly>
<Year>2022</Year>
<Month>02</Month>
<Day>28</Day>
<Sal>
<Amt>60000</Amt>
</Sal>
</Monthly>
</Salary>
<Dept>ECE</Dept>
</Employee>
</Office>' ;
我能够使用以下逻辑获取 Employee 表的输出
SELECT
[Table].[Column].value('EUID[1]', 'varchar(MAX)') as 'EID',
[Table].[Column].value('FirstName [1]', 'varchar(50)') as ' FirstName ',
[Table].[Column].value(' MiddleName[1]', 'varchar(50)') as ' MidName',
[Table].[Column].value(' LastName [1]', 'varchar(50)') as ' LastName',
[Table].[Column].value('(./Dept/text())[1]','Varchar(50)') as [DName]
FROM
@XmlInput.nodes('/Office/Employee') as [Table]([Column])
输出:
EID EUID FirstName MiddleName LastName Dept
1 xyz Ram J D CSE
2 abc Krishna R G ECE
但是我无法找到任何在不使用循环的情况下将 EUID 插入工资表的逻辑
输出应采用以下格式:
ID SalaryDate SalAmt EUID
1 2022-01-31 100000 xyz
2 2022-02-28 90000 xyz
3 2022-01-31 50000 abc
4 2022-02-28 60000 abc
我是 xml 解析的新手
答:
1赞
Yitzhak Khabinsky
5/6/2022
#1
请尝试以下解决方案。
SQL格式
-- DDL and sample data population, start
DECLARE @Employee TABLE (
EID INT IDENTITY PRIMARY KEY,
EUID VARCHAR(50),
FirstName VARCHAR(50),
MidName VARCHAR(50),
LastName VARCHAR(50),
Dept VARCHAR(50)
);
DECLARE @Salary TABLE (
ID INT IDENTITY PRIMARY KEY,
EUID VARCHAR(50),
SalaryDate DATE,
SalAmt DECIMAL(10,2)
);
DECLARE @XmlInput XML =
N'<Office>
<Employee>
<EUID>xyz</EUID>
<FirstName>Ram</FirstName>
<MiddleName>J</MiddleName>
<LastName>D</LastName>
<Salary>
<Monthly>
<Year>2022</Year>
<Month>01</Month>
<Day>31</Day>
<Sal>
<Amt>100000</Amt>
</Sal>
</Monthly>
<Monthly>
<Year>2022</Year>
<Month>02</Month>
<Day>28</Day>
<Sal>
<Amt>90000</Amt>
</Sal>
</Monthly>
</Salary>
<Dept>CSE</Dept>
</Employee>
<Employee>
<EUID>abc</EUID>
<FirstName>Krishna</FirstName>
<MiddleName>R</MiddleName>
<LastName>G</LastName>
<Salary>
<Monthly>
<Year>2022</Year>
<Month>01</Month>
<Day>31</Day>
<Sal>
<Amt>50000</Amt>
</Sal>
</Monthly>
<Monthly>
<Year>2022</Year>
<Month>02</Month>
<Day>28</Day>
<Sal>
<Amt>60000</Amt>
</Sal>
</Monthly>
</Salary>
<Dept>ECE</Dept>
</Employee>
</Office>';
-- DDL and sample data population, end
INSERT INTO @Employee (EUID, FirstName, MidName, LastName, Dept)
SELECT EUID = c.value('(EUID/text())[1]', 'varchar(50)'),
FirstName = c.value('(FirstName/text())[1]', 'varchar(50)'),
MidName = c.value('(MiddleName/text())[1]', 'varchar(50)'),
LastName = c.value('(LastName/text())[1]', 'varchar(50)'),
Dept = c.value('(Dept/text())[1]','Varchar(50)')
FROM @XmlInput.nodes('/Office/Employee') as t(c);
INSERT INTO @Salary (EUID, SalaryDate, SalAmt)
SELECT EUID = c.value('(../../EUID/text())[1]', 'varchar(50)'),
SalaryDate = c.value('(Year/text())[1]', 'CHAR(4)') + '-' +
c.value('(Month/text())[1]', 'CHAR(2)') + '-' +
c.value('(Day/text())[1]', 'CHAR(2)'),
SalAmt = c.value('(Sal/Amt/text())[1]', 'DECIMAL(10,2)')
FROM @XmlInput.nodes('/Office/Employee/Salary/Monthly') as t(c);
-- test
SELECT * FROM @Employee;
SELECT * FROM @Salary;
评论
0赞
Charlieface
5/6/2022
CROSS APPLY
可能比 .否则好答案../../
0赞
Yitzhak Khabinsky
5/6/2022
我同意。但这种情况与性能无关。一个似乎是一次易。
评论