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

Posted

技术标签:

【中文标题】SQL:根据变量选择动态列名【英文标题】:SQL: Select dynamic column name based on variable 【发布时间】:2011-04-12 15:45:06 【问题描述】:

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

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

这不起作用(“语法错误”)。如果我用 [ ] 包装列名:

SELECT 'value' AS [@myDynamicColumn]

列名按字面意思输出为“@myDynamicColumn”,而不是实际值。有没有办法做到这一点?我查看了动态 SQL 文章,但没有什么是我想要的。

【问题讨论】:

为什么?这不是应该使用 SQL 的方式 @gbn:马上。 @dotNewkow:我确定这只是一个人为的例子来说明你的问题,但 gbn 是正确的:这很复杂,因为它是错误的。如果您需要对存储过程的返回值进行别名处理,那么只需在调用代码中进行别名处理,您显然已经知道@myDynamicColumn 的值。如果您发布有关您的问题的更多详细信息,也许我们可以提供的不仅仅是动态 sql。 好问题。是的,我了解动态 SQL 的危险。 @Nathan Skerl,你是对的,通常你想通过调用代码来设置它。但是,出于报告目的,我将此查询作为 Excel 中的数据连接运行。客户想要 4 个具有相对相同数据但具有不同列名的报告,因此我制作了一个存储过程以实现可重用性并遵循 DRY 原则。如果这是一个视图,我可以这样做:“SELECT [column] AS [My Dynamic column name] FROM [My View]”,但由于它是一个存储过程,我只能执行“EXEC My_Procedure 'My Column Name'”。跨度> DRY 将在客户端中使用别名并保持 SQL 合约相同。这不是 SQL 问题。 DRY 也意味着无论如何都要使用相同的名称。一个属性有 4 个名称令人困惑…… 如何更改过程以接收@ReportId,然后在过程中模拟您在视图中将执行的操作...即,如果 @ReportId = 1 然后选择“值”作为 [MyDynamicColumn] 否则如果@ReportId = 2 ...至少您不必承担动态sql的包袱。对于少数报告/列标题,我会走这条路。 【参考方案1】:
EXEC ('SELECT ''value'' AS ' + @myDynamicColumn)

【讨论】:

谢谢,您比其他人晚了 45 秒才回答,所以点个赞吧! @dotNetkow:实际上,我在 15:49:30 和 15:49:39 之间比“另一个人”领先 9 秒。 永远是伴娘,永远不是新娘。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

两个被赞成的答案在这里都是非常危险的,两者都容易受到注入攻击,应该使用。

在注入动态对象名称时,您必须确保正确引用您的对象名称。 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 在内部用于对象名称的数据类型。

【讨论】:

未来10年你好!你是对的,这是我很久以前遇到的一个问题的创造性解决方案。它在不同的评论中,但是:查询是作为 Excel 中的数据连接运行的,用于报告目的。客户想要 4 个具有相对相同数据但具有不同列名的报告,因此我制作了一个存储过程以实现可重用性并遵循 DRY 原则。只在内部运行,存储过程从 Excel 中剥离,然后传递给客户端。干杯!

以上是关于SQL:根据变量选择动态列名的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 动态列选择

DataGridView绑定DataTable动态生成列 并且将列名中文显示

有没有办法动态更改 JQwidget 网格列的数据源以及列名

根据列值动态获取列名

具有可变列名的动态更新语句

如何使用小部件在 Dataframe 选择语句中传递动态列名