如何使内部连接 SELECT 的 FOR XML AUTO 输出将两个表输出到各自的元素?
How to make a FOR XML AUTO output of an Inner Joined SELECT output both tables to their own respective Elements?
我正在尝试创建一个存储过程,它使用 BIT 变量打印出内部连接 Select 语句的 2 个可能的 FOR XML 结果之一。这是该过程的当前形式:
CREATE PROCEDURE dbo.CustomerAddress_Get
@IsAuto BIT = 0
AS
BEGIN
--@IsAuto If's
IF (@IsAuto == 0)
BEGIN
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML RAW ('CustomerAccount'), ELEMENTS, ROOT('CustomerAccountDetails')
END
ELSE
BEGIN
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs Customer
INNER JOIN dbo.Accounts Account
ON Account.CustNo = Customer.CustNo
FOR XML AUTO, ELEMENTS, ROOT
END
END;
我特别尝试更改的代码是这样的:
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML AUTO, ELEMENTS, ROOT
Else SELECT...FOR AUTO 的当前 XML 输出示例;因此声明是:
<Customer>D<Surname>Grayson</Surname><DOB>1940-04-01T00:00:00</DOB><Account><AccountId>159</AccountId><Type>Chequing</Type><Balance>0.0000</Balance></Account><Account><AccountId>160</AccountId><Type>Savings </Type><Balance>500.0000</Balance></Account></Customer>
但是,我要求它更像这样:
<cu>
<FirstName>Catherine</FirstName>
<LastName>Abel</LastName>
<EmailAddress>catherine0@adventure-works.com</EmailAddress>
<ca>
<AddressType>Main Office</AddressType>
<ad>
<City>Van Nuys</City>
<StateProvince>California</StateProvince>
</ad>
我认为 FOR XML AUTO 的用途是什么,但它似乎并没有真正格式化结果 XML.
现在,与此相关的问题是,我如何才能将此 SELECT 放入客户(GivenName、Surname 和 DOB/DateOfBirth)和帐户(AccountId、Type 和 Balance)在 XML AUTO 输出中各自的元素中各自的详细信息?
这是根据您的标题使用动态创建的语句对问题的回答:
CREATE PROCEDURE dbo.CustomerAddress_Get
@IsAuto BIT = 0
AS
BEGIN
--@IsAuto If's
DECLARE @cmd NVARCHAR(MAX)=
(
N'SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML '
);
IF @IsAuto = 0
SET @cmd=@cmd+N'RAW (''CustomerAccount''), ELEMENTS, ROOT(''CustomerAccountDetails'')';
ELSE
SET @cmd=@cmd+N'AUTO, ELEMENTS, ROOT';
EXEC (@cmd);
END;
更新:你的第二个问题
如果您使用 FOR XML PATH
,您可以控制 XML
的最终格式
在不了解您的表格的情况下,很难提出正确的解决方案(给定的数据和示例不匹配!),但应该是这样的:
SELECT LEFT(cu.GivenName,1) AS [cu/FirstLetter]
,cu.GivenName AS [cu/FirstName]
,cu.Surname AS [cu/LastName]
,cu.DOB AS [cu/Birthdate]
,cu.City AS [ad/City]
,cu.StateProvinve AS [ad/StateProvince]
,ac.AccountId AS [ac/AccountId]
,ac.Type AS [ac/Type]
,Balance AS [ac/Balance]
FROM Custs AS cu
INNER JOIN dbo.Accounts AS ac
ON ac.CustNo = cu.CustNo
FOR XML PATH('Customer'),ROOT('root')
在这种情况下,我建议不要使用上面给出的动态创建 SQL 的方法,而是坚持使用现有的 IF ... ELSE ...
更新 2:Sub-select 而不是加入
您可以试试这样的方法。该代码将创建嵌入式 XML 作为 sub-select:
SELECT Custs.*
,(
SELECT Accounts.*
FROM dbo.Accounts
WHERE Accounts.CustNo = Custs.CustNo
FOR XML AUTO, ELEMENTS,TYPE
) AS [ad]
FROM Custs AS [cu]
FOR XML AUTO, ELEMENTS, ROOT
我正在尝试创建一个存储过程,它使用 BIT 变量打印出内部连接 Select 语句的 2 个可能的 FOR XML 结果之一。这是该过程的当前形式:
CREATE PROCEDURE dbo.CustomerAddress_Get
@IsAuto BIT = 0
AS
BEGIN
--@IsAuto If's
IF (@IsAuto == 0)
BEGIN
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML RAW ('CustomerAccount'), ELEMENTS, ROOT('CustomerAccountDetails')
END
ELSE
BEGIN
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs Customer
INNER JOIN dbo.Accounts Account
ON Account.CustNo = Customer.CustNo
FOR XML AUTO, ELEMENTS, ROOT
END
END;
我特别尝试更改的代码是这样的:
SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML AUTO, ELEMENTS, ROOT
Else SELECT...FOR AUTO 的当前 XML 输出示例;因此声明是:
<Customer>D<Surname>Grayson</Surname><DOB>1940-04-01T00:00:00</DOB><Account><AccountId>159</AccountId><Type>Chequing</Type><Balance>0.0000</Balance></Account><Account><AccountId>160</AccountId><Type>Savings </Type><Balance>500.0000</Balance></Account></Customer>
但是,我要求它更像这样:
<cu>
<FirstName>Catherine</FirstName>
<LastName>Abel</LastName>
<EmailAddress>catherine0@adventure-works.com</EmailAddress>
<ca>
<AddressType>Main Office</AddressType>
<ad>
<City>Van Nuys</City>
<StateProvince>California</StateProvince>
</ad>
我认为 FOR XML AUTO 的用途是什么,但它似乎并没有真正格式化结果 XML.
现在,与此相关的问题是,我如何才能将此 SELECT 放入客户(GivenName、Surname 和 DOB/DateOfBirth)和帐户(AccountId、Type 和 Balance)在 XML AUTO 输出中各自的元素中各自的详细信息?
这是根据您的标题使用动态创建的语句对问题的回答:
CREATE PROCEDURE dbo.CustomerAddress_Get
@IsAuto BIT = 0
AS
BEGIN
--@IsAuto If's
DECLARE @cmd NVARCHAR(MAX)=
(
N'SELECT LEFT(GivenName,1), Surname, DOB, AccountId, Type, Balance FROM Custs
INNER JOIN dbo.Accounts
ON Accounts.CustNo = Custs.CustNo
FOR XML '
);
IF @IsAuto = 0
SET @cmd=@cmd+N'RAW (''CustomerAccount''), ELEMENTS, ROOT(''CustomerAccountDetails'')';
ELSE
SET @cmd=@cmd+N'AUTO, ELEMENTS, ROOT';
EXEC (@cmd);
END;
更新:你的第二个问题
如果您使用 FOR XML PATH
,您可以控制 XML
在不了解您的表格的情况下,很难提出正确的解决方案(给定的数据和示例不匹配!),但应该是这样的:
SELECT LEFT(cu.GivenName,1) AS [cu/FirstLetter]
,cu.GivenName AS [cu/FirstName]
,cu.Surname AS [cu/LastName]
,cu.DOB AS [cu/Birthdate]
,cu.City AS [ad/City]
,cu.StateProvinve AS [ad/StateProvince]
,ac.AccountId AS [ac/AccountId]
,ac.Type AS [ac/Type]
,Balance AS [ac/Balance]
FROM Custs AS cu
INNER JOIN dbo.Accounts AS ac
ON ac.CustNo = cu.CustNo
FOR XML PATH('Customer'),ROOT('root')
在这种情况下,我建议不要使用上面给出的动态创建 SQL 的方法,而是坚持使用现有的 IF ... ELSE ...
更新 2:Sub-select 而不是加入
您可以试试这样的方法。该代码将创建嵌入式 XML 作为 sub-select:
SELECT Custs.*
,(
SELECT Accounts.*
FROM dbo.Accounts
WHERE Accounts.CustNo = Custs.CustNo
FOR XML AUTO, ELEMENTS,TYPE
) AS [ad]
FROM Custs AS [cu]
FOR XML AUTO, ELEMENTS, ROOT