我有一个存储过程,它返回一堆带编号的列(我知道这是一个坏主意,但这就是它的作用),例如问题1,答案1,...问题125,答案125。
现在,我的问题是,如果要将此过程的结果导出到Excel,则当多于256列时会出现错误。而且查询中有少数未编号的列,所以我总共有262个-但是其中一些是空白的,因为存储过程不一定需要填充所有125个问题和答案。
有什么方法可以编写一个SQL查询,该查询将根据参数有条件地返回许多列?我知道我可以在参数上写一个if语句来返回X的列数或Y,具体取决于是否设置了该参数,但是我想对其进行更细粒度的控制...因此,如果我要处理的数据例如,只有50个问题,那么它将达到Question50 / Answer50。
答案 0 :(得分:0)
您可以使用SQL Server的FOR XML忽略NULL值并建立非空列的动态列表。
您可以在SSMS中运行它:
-- Create a mock-up data table.
DECLARE @Data TABLE ( column_1 VARCHAR(10), column_2 VARCHAR(10), column_3 VARCHAR(10), column_4 VARCHAR(10), column_5 VARCHAR(10), pk INT IDENTITY(1,1) );
-- Insert values into every column except for column_4.
INSERT INTO @Data ( column_1, column_2, column_3, column_5 )
VALUES ( 'Value 1', 'Value 2', 'Value 3', 'Value 5' );
-- View @Data contents.
SELECT * FROM @Data ORDER BY pk;
-- Declare a variable to hold our non-null column list.
DECLARE @columns AS VARCHAR(MAX);
-- SQL/XML Hack: Build the non-null column list with XML's excluding of NULL values.
SELECT
@columns = STRING_AGG ( cols.column_name, ',' )
FROM (
SELECT CAST ( ( SELECT * FROM @Data FOR XML PATH ( '' ) ) AS XML ) AS non_null_columns
) AS x
CROSS APPLY (
SELECT
x.f.value('fn:local-name(.)','VARCHAR(255)') AS column_name
FROM non_null_columns.nodes('/*') x(f)
) AS cols;
-- View the column list.
SELECT @columns AS non_null_column_list;
-- Create an executable query with the updated column list.
DECLARE @sql VARCHAR(MAX) = FORMATMESSAGE ( 'SELECT %s FROM %s;', @columns, 'dbo.TableName' );
SELECT @sql AS MyNewSelect;
此区块:
-- View @Data contents.
SELECT * FROM @Data ORDER BY pk;
返回@Data的内容:
+----------+----------+----------+----------+----------+----+
| column_1 | column_2 | column_3 | column_4 | column_5 | pk |
+----------+----------+----------+----------+----------+----+
| Value 1 | Value 2 | Value 3 | NULL | Value 5 | 1 |
+----------+----------+----------+----------+----------+----+
此区块:
-- View the column list.
SELECT @columns AS non_null_column_list;
向我们显示变量 @columns 的内容
+----------------------------------------+
| non_null_column_list |
+----------------------------------------+
| column_1,column_2,column_3,column_5,pk |
+----------------------------------------+
最后,这个块:
-- Create an executable query with the updated column list.
DECLARE @sql VARCHAR(MAX) = FORMATMESSAGE ( 'SELECT %s FROM %s;', @columns, 'dbo.TableName' );
SELECT @sql AS MyNewSelect;
显示了如何完成可以用EXEC
调用的动态sql语句:
+-------------------------------------------------------------------+
| MyNewSelect |
+-------------------------------------------------------------------+
| SELECT column_1,column_2,column_3,column_5,pk FROM dbo.TableName; |
+-------------------------------------------------------------------+
这绝对是 hack ,但是它将把动态SQL中的列限制为包含值的列。您确实应该考虑标准化数据以提高效率。
注意:您将需要一种方法来将派生表的XML(在我的示例中为别名“ x”)限制为特定的行。