计算函数中的变量数

时间:2016-07-13 23:27:59

标签: sql-server xml tsql export

我有以下SQL函数,它使用多个表返回XML。这里的问题是,当导出到XML时,路径将SELECT中的所有变量作为兄弟节点放在CUSTOM_DATA_ITEM下。

ALTER FUNCTION [dbo].[GetXML]
(
@Id UNIQUEIDENTIFIER
)
RETURNS XML
        AS
BEGIN
RETURN (
    SELECT 
    (
        SELECT
        [Address] = [Property].[Address],
        [Name] = [Person].[Name]
        ...
       FOR XML PATH('CUSTOM_DATA_ITEM'), ROOT('CUSTOM_DATA_ITEMS'), TYPE 
    )
    FROM [Property] LEFT JOIN
         [Person] ON [Person].[ID] = [Property].[ID]
    WHERE   ([Property].[ID] = @Id)
   FOR XML PATH('OTHER'), ROOT('EXTENSION'), TYPE 
);

我希望为每个变量返回的xml如下所示:

<CUSTOM_DATA_ITEM>
    <DataItemName>Address</DataItemName> (variable name)
    <DataItemValue>AddressValue</DataItemValue> (value inside table column)
</CUSTOM_DATA_ITEM>
<CUSTOM_DATA_ITEM>
    <DataItemName>Name</DataItemName>
    <DataItemValue>NameValue</DataItemValue>
</CUSTOM_DATA_ITEM>

我在考虑使用[cte]然后执行COUNT([cte].[*])来包围变量,但这似乎不起作用。从那里我想有一个while循环并坚持每个变量的路径。

我目前的解决方案是拥有这样的东西,但我必须为每个变量做到这一点。

SELECT [DataItemName] = CASE WHEN [Property].[Address] IS NOT NULL THEN 'Address' END,
       [DataItemValue] = [Property].[Address]
FOR XML PATH('CUSTOM_DATA_ITEM'), TYPE), 

1 个答案:

答案 0 :(得分:0)

你试图将你的问题简化为必要的,这很好,但我必须承认,我并不完全理解这一点......我必须承认,我不喜欢实体 - 价值对

我的理解是你的问题: ...将所有变量放在SELECT中作为CUSTOM_DATA_ITEM下的兄弟节点

这是一个简单的技巧:在它们之间放置一个节点。这将告诉引擎完成当前元素并开始一个新元素。

以下是一些建议:

DECLARE @tbl TABLE ([Name] VARCHAR(100),[Address] VARCHAR(100),SomeNumber INT);
INSERT INTO @tbl VALUES
 ('John','John''s street',100) 
,('Steve','Steve''s street',300);

SELECT 'Name' AS [CUSTOM_DATA_ITEM/DataItemName]
      ,[Name] AS [CUSTOM_DATA_ITEM/DataItemValue]
      ,''
      ,'Address' AS [CUSTOM_DATA_ITEM/DataItemName]
      ,[Address] AS [CUSTOM_DATA_ITEM/DataItemValue]
      ,''
      ,'SomeNumber' AS [CUSTOM_DATA_ITEM/DataItemName]
      ,SomeNumber AS [CUSTOM_DATA_ITEM/DataItemValue]
FROM @tbl
FOR XML PATH('DataRow'),ROOT('EXTENSION')

结果

<EXTENSION>
  <DataRow>
    <CUSTOM_DATA_ITEM>
      <DataItemName>Name</DataItemName>
      <DataItemValue>John</DataItemValue>
    </CUSTOM_DATA_ITEM>
    <CUSTOM_DATA_ITEM>
      <DataItemName>Address</DataItemName>
      <DataItemValue>John's street</DataItemValue>
    </CUSTOM_DATA_ITEM>
    <CUSTOM_DATA_ITEM>
      <DataItemName>SomeNumber</DataItemName>
      <DataItemValue>100</DataItemValue>
    </CUSTOM_DATA_ITEM>
  </DataRow>
  <DataRow>
    <CUSTOM_DATA_ITEM>
      <DataItemName>Name</DataItemName>
      <DataItemValue>Steve</DataItemValue>
    </CUSTOM_DATA_ITEM>
    <CUSTOM_DATA_ITEM>
      <DataItemName>Address</DataItemName>
      <DataItemValue>Steve's street</DataItemValue>
    </CUSTOM_DATA_ITEM>
    <CUSTOM_DATA_ITEM>
      <DataItemName>SomeNumber</DataItemName>
      <DataItemValue>300</DataItemValue>
    </CUSTOM_DATA_ITEM>
  </DataRow>
</EXTENSION>

我宁愿将内容作为属性放入元素中,但这是一个品味问题:

SELECT 'Name' AS [CUSTOM_DATA_ITEM/@DataItemName]
      ,[Name] AS [CUSTOM_DATA_ITEM/@DataItemValue]
      ,''
      ,'Address' AS [CUSTOM_DATA_ITEM/@DataItemName]
      ,[Address] AS [CUSTOM_DATA_ITEM/@DataItemValue]
      ,''
      ,'SomeNumber' AS [CUSTOM_DATA_ITEM/@DataItemName]
      ,SomeNumber AS [CUSTOM_DATA_ITEM/@DataItemValue]
FROM @tbl
FOR XML PATH('DataRow'),ROOT('EXTENSION')

结果

<EXTENSION>
  <DataRow>
    <CUSTOM_DATA_ITEM DataItemName="Name" DataItemValue="John" />
    <CUSTOM_DATA_ITEM DataItemName="Address" DataItemValue="John's street" />
    <CUSTOM_DATA_ITEM DataItemName="SomeNumber" DataItemValue="100" />
  </DataRow>
  <DataRow>
    <CUSTOM_DATA_ITEM DataItemName="Name" DataItemValue="Steve" />
    <CUSTOM_DATA_ITEM DataItemName="Address" DataItemValue="Steve's street" />
    <CUSTOM_DATA_ITEM DataItemName="SomeNumber" DataItemValue="300" />
  </DataRow>
</EXTENSION>

但是 - 说实话 - 我根本不会这样做。我把它放在一个修复结构中:

SELECT [Name] 
      ,[Address] 
      ,SomeNumber
FROM @tbl
FOR XML PATH('DataRow'),ROOT('EXTENSION')

结果

<EXTENSION>
  <DataRow>
    <Name>John</Name>
    <Address>John's street</Address>
    <SomeNumber>100</SomeNumber>
  </DataRow>
  <DataRow>
    <Name>Steve</Name>
    <Address>Steve's street</Address>
    <SomeNumber>300</SomeNumber>
  </DataRow>
</EXTENSION>