SQL:根据变量选择动态列名

28

我有一个Microsoft SQL存储过程,我想通过传递给它的变量来设置其列名:

CREATE PROCEDURE [My_Procedure]
   @myDynamicColumn varchar(50)
AS BEGIN
   SELECT 'value' AS @myDynamicColumn
END

这个方法不起作用("语法不正确")。如果我使用 [ ] 把列名括起来:

SELECT 'value' AS [@myDynamicColumn]

列名字面上输出的是 '@myDynamicColumn' 而不是实际值。有没有什么办法可以解决这个问题?我已经看了动态SQL文章,但没有找到完全符合我的问题。


1
为什么?这不是 SQL 应该被使用的方式。 - gbn
@gbn: 没错。 @dotNewkow: 我确定这只是一个人为制造的例子来说明你的问题,但是 gbn 是正确的:这很复杂,因为它是错误的。如果您需要为存储过程的返回值设置别名,则只需在调用代码中进行别名设置,在那里您显然已经知道了 @myDynamicColumn 的值。如果您发布有关您的问题的更多详细信息,也许我们可以提供更多动态 SQL 以外的解决方案。 - nathan_jr
好问题。是的,我了解动态SQL的危险性。@Nathan Skerl,你是正确的,通常你会想通过调用代码来设置这个。然而,我正在Excel中作为数据连接运行此查询以进行报告。客户需要4个报告,其中包含相同的数据但具有不同的列名,因此我制作了一个存储过程以实现可重用性和遵循DRY原则。如果这是一个视图,我可以这样做:“SELECT [column] AS [My Dynamic column name] FROM [My View]”,但由于它是一个存储过程,我只能这样做:“EXEC My_Procedure 'My Column Name'”。 - dotNetkow
1
DRY 的做法是在客户端中使用别名,并保持 SQL 合同相同。这不是 SQL 的问题。DRY 还意味着无论如何都要使用相同的名称。一个属性有 4 个名称会令人困惑... - gbn
1
改变过程以接受@ReportId,然后在过程中模拟在视图中所做的操作怎么样?例如,如果@ReportId = 1,则选择'value'作为[MyDynamicColumn],否则如果@ReportId = 2 ...至少您不必承担动态SQL的负担。对于少量报告/列标题,我会选择这种方法。 - nathan_jr
@Nathan Skerl:谢谢,我喜欢这种方法。好多了。 - dotNetkow
3个回答

38
EXEC ('SELECT ''value'' AS ' + @myDynamicColumn)

谢谢,你比另一个人晚回答了45秒,所以我给你点赞! - dotNetkow
@dotNetkow:实际上,我比“那个人”领先9秒,15:49:30对15:49:39。 - Joe Stefanelli
38
永远当伴娘,永远不做新娘。 - Josh

22

您可以将查询构建为字符串并使用exec

CREATE PROCEDURE [My_Procedure]
   @myDynamicColumn varchar(50)
AS BEGIN
   EXEC('SELECT ''value'' AS ' + @myDynamicColumn)
END

6

这两个被赞同的答案都非常危险,容易受到注入攻击,不应使用。

当注入动态对象名称时,您必须确保正确引用对象名称。 SQL Server有一个内置函数QUOTENAME可供使用。因此,您实际上应该执行以下操作:

CREATE PROCEDURE [My_Procedure] @myDynamicColumn sysname
AS BEGIN
    DECLARE @SQL nvarchar(MAX) = N'SELECT ''value'' AS ' + QUOTENAME(@myDynamicColumn) + N';';
    EXEC sys.sp_executesql @SQL;
END

您会注意到我还将参数的数据类型更改为sysname,这是nvarchar(128) NOT NULL的同义词,在SQL Server内部用于对象名称的数据类型。


你好,未来的十年!你是正确的,这是我很久以前遇到问题时提出的创造性解决方案。虽然它在另一个评论中,但是:查询作为 Excel 中的数据连接运行,用于报告目的。客户想要 4 个报告,其中包含相同的数据但具有不同的列名,因此我创建了一个存储过程以实现可重用性和遵循 DRY 原则。仅在内部运行,并且在传递给客户之前从 Excel 中删除了 sprocs。干杯! - dotNetkow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接