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:根据变量选择动态列名的主要内容,如果未能解决你的问题,请参考以下文章
DataGridView绑定DataTable动态生成列 并且将列名中文显示