我需要将XML文件发送给供应商,其中包含来自SQL Server数据库的特定数据。我知道SQL Server确实与XML集成,但我不熟悉它,所以我决定只是选择XML标签作为连接文本,我需要的字段。这有效,但我意识到解决方案不能满足我们的需求。
原因在于,对于给定的客户,可能会有多个结果。如果有多个结果,由于SQL Server为每个结果返回一个单独的行,它也会为每个客户生成多个文件。我们需要为每个客户提供一个文件。
这是SQL的一部分,它会为每个客户生成多个结果:
-- Carriage return in variable for repeated use
declare @cr varchar(2) = char(13) + char(10)`
'<activity>' + @cr +
'<activity_date>' + CONVERT(VARCHAR(10), GETDATE(), 101) + '</activity_date>' + @cr +
'<activity_desc>' + Term.Code + ' Remaining Balance' + '</activity_desc>' + @cr +
'<charge>' + bal.Balance + '</charge>' + @cr +
'</activity>'
我们需要完成的是如果有多个Term.Code字段,那么结果XML输出就是这样:
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>WINTER17D Remaining Balance</activity_desc>
<charge>50.00</charge>
</activity>
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>SPRING18A Remaining Balance</activity_desc>
<charge>15.00</charge>
</activity>
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>SPRING18B Remaining Balance</activity_desc>
<charge>20.00</charge>
</activity>`
三个单独的<activity>
标记,都在同一个文件中,但其余的XML每个客户只有一个标记。所以,完整的结果将是这样的:
<Billing>
<stmt_date>02/01/2018</stmt_date>
<id>987654</id>
<total_due>85.00</total_due>
<name>Test Person</name>
<message>You have an outstanding balance.</message>
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>WINTER17D Remaining Balance</activity_desc>
<charge>50.00</charge>
</activity>
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>SPRING18A Remaining Balance</activity_desc>
<charge>15.00</charge>
</activity>
<activity>
<activity_date>02/01/2018</activity_date>
<activity_desc>SPRING18B Remaining Balance</activity_desc>
<charge>20.00</charge>
</activity>
</Billing>
这可能吗?这是我们用来生成所有原始数据集的SQL查询:
SELECT RTRIM(Person.PersonID) AS PersonID,
CONVERT(VARCHAR(10), GETDATE(), 101) AS StatementDate,
bal.Balance,
RTRIM(Person.StuNum) AS PersonNum,
RTRIM(Person.Email) AS Email,
Person.Addr1,
Term.Code AS Term
FROM Person(nolock)
JOIN Enrollment(nolock)
ON Person.PersonID = Enrollment.PersonID
JOIN AcctStatus(nolock)
ON Enrollment.EnrollmentID = AcctStatus.EnrollmentID
AND AcctStatus.SaAcctStatusID NOT IN(5, 16)
JOIN
(
SELECT EnrollmentID,
TermID,
CAST(SUM(CASE Type
WHEN 'I'
THEN Amount
WHEN 'D'
THEN Amount
ELSE Amount * -1
END) AS VARCHAR(10)) AS Balance
FROM Ledger
GROUP BY EnrollmentID,
TermID
) AS bal
ON bal.EnrollmentID = Enrollment.EnrollmentID
AND bal.Balance <> '0.00'
JOIN Term(nolock)
ON Term.TermID = bal.TermID
AND Term.TermID NOT IN(105, 34, 60, 194, 193, 97, 74)
ORDER BY Person.PersonID,
bal.TermID
答案 0 :(得分:2)
有两个主要缺陷:
'Do & Co'
之类的数据。 &
会破坏XML的有效性!ISO8601
(特别是在XML中)!试试这样:
有一个模拟场景,你必须适应你的需求。基本的想法是使用FOR XML PATH()
作为结算数据,使用另一个子选择 - 再次使用FOR XML PATH(),TYPE
进行相关(嵌套)活动。
DECLARE @mockupBilling TABLE(StatementDate DATE, ID INT, Balance DECIMAL(10,4),Name VARCHAR(100),Msg VARCHAR(MAX));
INSERT INTO @mockupBilling VALUES(GETDATE(),987654,85.0,'Test Person','You have an outstanding balance.');
DECLARE @mockupActivity TABLE(BillingID INT, ActivityDate DATE, Activity VARCHAR(100), Charge DECIMAL(10,4));
INSERT INTO @mockupActivity VALUES
(987654,{d'2018-01-02'},'WINTER17D Remaining Balance',50.0)
,(987654,{d'2018-01-03'},'SPRING18A Remaining Balance',15.0);
SELECT b.StatementDate AS [stmt_date]
,b.ID AS [id]
,b.Balance AS [total_due]
,b.Name AS [name]
,b.Msg AS [messge]
,(
SELECT a.ActivityDate AS [activity_date]
,a.Activity AS [activity_desc]
,a.Charge AS [charge]
FROM @mockupActivity AS a
WHERE a.BillingID=b.ID
ORDER BY a.ActivityDate
FOR XML PATH('activity'),TYPE
)
FROM @mockupBilling AS b
FOR XML PATH('Billing');
结果
<Billing>
<stmt_date>2018-02-02</stmt_date>
<id>987654</id>
<total_due>85.0000</total_due>
<name>Test Person</name>
<messge>You have an outstanding balance.</messge>
<activity>
<activity_date>2018-01-02</activity_date>
<activity_desc>WINTER17D Remaining Balance</activity_desc>
<charge>50.0000</charge>
</activity>
<activity>
<activity_date>2018-01-03</activity_date>
<activity_desc>SPRING18A Remaining Balance</activity_desc>
<charge>15.0000</charge>
</activity>
</Billing>
答案 1 :(得分:0)
正确的答案是为您的查询使用常规的select语句,但在其中添加FOR XML PATH('ACTIVITY')
我很乐意帮助您,尽管您还没有提供完整的查询。添加它,然后我自己或其他人可以指导你。
在此处阅读
FOR XML
:https://docs.microsoft.com/en-us/sql/relational-databases/xml/for-xml-sql-server