SQLSERVER FOR XML PATH-将属性名称视为变量

时间:2019-08-21 14:40:54

标签: sql-server xml tsql

SELECT field1 as "@q1_12"
FROM table1
FOR XML PATH ('qt'),TYPE

我需要在xml中调整此查询的结果,但字段的别名“ @ q1_12”应根据不同和复杂的条件而更改。

因此,是否可以将此属性的名称放入变量中并在查询中使用它(如某种动态sql) 有技巧或解决方法吗?

SELECT field1 as @attributename  <-- this is a variable
FROM table1
FOR XML PATH ('qt'),TYPE

我知道,这里的字符“ @”令人困惑,它具有不同的含义,即被视为变量还是被视为文字(在此示例中,“ XML FOR”命令将使用该字段将字段的值放入属性中而不是元素)

此外,此查询用作子查询,因此使用CASE / IF非常困难,有什么主意吗?

2 个答案:

答案 0 :(得分:2)

您的问题清楚地表明,您了解动态SQL,并获得了一些有关REPLACE()的提示,可以在字符串级别解决此问题。

建议1

但是可能有一种方法,尤其是在可能的名称都已知并且列表不大的情况下:

DECLARE @mockupTable TABLE(ID INT IDENTITY,SomeValue VARCHAR(100));
INSERT INTO @mockupTable VALUES('Row 1'),('Row 2');

-如您所知,使用变量列别名是不可能的 ...
-您可以使用动态语句,但这会涉及一些主要缺点...(无特殊要求,难以进行输出...)

-但是您可以尝试一下
-为了模拟您的复杂条件,我只检查一个值(但是您会得到ghist):

DECLARE @SomeCondition INT=2;

SELECT CASE WHEN @SomeCondition=1 THEN SomeValue END AS [@q1_01]
      ,CASE WHEN @SomeCondition=2 THEN SomeValue END AS [@q1_02]
      ,CASE WHEN @SomeCondition=3 THEN SomeValue END AS [@q1_03]
      --add all possible attribute names here...
FROM @mockupTable t
FOR XML PATH('qt'),TYPE;

背后的魔力:如果未明确指定(请参阅ELEMENTS XSINIL,则使用FOR XML PATH()创建的XML将忽略NULL值。
您可以声明所有可能的列名,如果不满足条件,则将全部省略。

建议2

这是相反的方法:

DECLARE @KeepThis VARCHAR(100)='q1_02';
SELECT
(
    SELECT SomeValue AS [@q1_01]
          ,SomeValue AS [@q1_02]
          ,SomeValue AS [@q1_03]
    FROM @mockupTable t
    FOR XML PATH('qt'),TYPE
).query('for $qt in /qt
         return
         <qt>
         { 
         for $a in $qt/@*[local-name(.)=sql:variable("@KeepThis")]
         return $a
         }
         </qt>');

将以所有属性 by-by-side 来创建XML,而XQuery将仅返回我们要保留的属性。

答案 1 :(得分:0)

唯一的方法是使用动态SQL。您不能使用变量来替换对象,别名等的值。因此,您需要安全将其注入到语句中:

DECLARE @attributename sysname = N'@q1_12';

DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT field1 AS ' + QUOTENAME(@attributename) + NCHAR(13) + NCHAR(10) +
           N'FROM table1' + NCHAR(13) + NCHAR(10) +
           N'FOR XML PATH ('qt'),TYPE;';

EXEC sp_executesql @SQL;