【问题标题】:Select not null columns as a comma separated string from dynamic sql从动态 sql 中选择非空列作为逗号分隔的字符串
【发布时间】:2019-08-27 03:47:59
【问题描述】:

我正在尽力避免使用游标。 nvarchar 变量中有一个逗号分隔的列列表,如下所示:

@columnList = 'col1,col2,col5'

有一张表有很多 varchar 列:

myTable: [col1],[col2],[col3],[col4],[col5],[col6],[col7]

这就是我使用动态 sql 选择数据的方式:

exec ('select ' + @columnList + ' from myTable')

此查询返回以下结果:

[col1], [col2] , [col5]
 null , "txt1" ,  null
"txt2",  null  ,  null
 null , "txt3" , "txt4"

这是我需要得到的:

@resultList = "txt1,txt2,txt3,txt4"

如何选择仅包含非空值的逗号分隔字符串?我知道如何将表格转换为逗号分隔的字符串,所以得到类似:

 [column]
  "txt1"
  "txt2"
  "txt3"
  "txt4"

也不错。有什么建议?随意提出一个基本的方法,我不希望你为我编写实际的代码。

【问题讨论】:

  • 联合所有非空值以获得第二个选项。
  • exec ('select ' + @columnList + ' from myTable') 是个坏主意。 SQL 注入不是你的朋友。
  • 哪个 sql server 版本?
  • @columnList 正在使用另一个查询的服务器上生成。没有人可以在那里注入一些东西。请随意提出更好的方法。
  • Mssql 2016 v13.0.x

标签: sql sql-server tsql sql-server-2016 dynamic-sql


【解决方案1】:

您可以使用如下解决方案,仅使用 REPLACE 来创建 SQL 查询:

DECLARE @columnList VARCHAR(100)
SET @columnList = 'col1,col2,col5'
SET @columnList = REPLACE(@columnList, ',', ' AS colName FROM myTable UNION ALL SELECT ');

EXEC('SELECT * FROM (SELECT ' + @columnList + ' AS colName FROM myTable)t WHERE NOT t.colName IS NULL');

您也可以使用UNPIVOT 的解决方案:

DECLARE @columnList VARCHAR(100);
SET @columnList = 'col1,col2,col5';

EXEC('SELECT colName FROM (SELECT ' + @columnList + ' FROM myTable) t1 UNPIVOT (colName FOR columnNames IN (' + @columnList + ')) AS t2');

demo on dbfiddle.uk

【讨论】:

    【解决方案2】:

    既然你提到你已经知道如何聚合成逗号分隔,这里是如何使用交叉应用取消透视表:

    select unpivoted.*
    from myTable
    cross apply
    ( values
         ('col1',col2)
        ,('col2',col2)
        ,('col3',col3) -- etc
    )unpivoted(colname,colval)
    

    【讨论】:

      【解决方案3】:

      这适用于 SQL Server 2017,在早期版本中,STRING_AGG 的用法应替换为 XML-based solution

      您可以先将结果连接成一行,然后使用STRING_AGG 将它们聚合成一个字符串:

      ;with t as
      (
      SELECT * FROM (VALUES
         (null  , 'txt1' ,  null),
         ('txt2',  null  ,  null),
         (null  , 'txt3' , 'txt4')) x(col1, col2, col5) 
      )
      SELECT STRING_AGG(STUFF(CONCAT(',' + col1, ',' + col2, ',' + col5), 1, 1, ''), ',')
        FROM t
      

      CTE 仅用于展示,您可以在动态查询中简单地进行:

      DECLARE @columnList NVARCHAR(MAX) = 'col1,col2,col5'
      DECLARE @query NVARCHAR(MAX) = ''
      SELECT @query = 'SELECT STRING_AGG(STUFF(CONCAT('','' + ' + REPLACE(@columnList, ',', ', '','' + ') + '), 1, 1, ''''), '','') from mytable'
      
      EXEC sp_executesql @query
      

      Working example on dbfiddle

      【讨论】:

      • 值得一提的是,STRING_AGG() 需要 2017+ 版本。 OP 在评论中声明,正在使用 v2016....
      • 哦,对了...我什至会问他们正在使用哪个版本,并牢记STRING_AGG,但我将 2016 年与 2017 年混淆了。我会添加一个注释我的回答。
      猜你喜欢
      • 2021-07-28
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多