带参数的存储过程返回特定的多列,而不是全部(*)

时间:2016-05-13 13:06:11

标签: c# sql sql-server sql-server-2008 stored-procedures

目前,我有一个存储过程,它返回所有列Example。我正在使用此存储过程从多个表中检索数据,每个表具有不同的列数和明显不同的列名,因此(Select *)很方便。但是,现在我只需要检索每个表中的特定列,所以我想传递这样的参数:

Select *

此处的问题是未设置要为列传递的参数数量,因为该表可以包含任意数量的列。有没有办法使用某种循环或动态赋值,以便我可以传递任意数量的参数作为列名?

我知道我只能过滤掉我想要使用的列,而忽略其余的,但这在我的情况下不起作用。我需要存储过程不返回一些包含敏感数据的特定列。

我在我的应用程序中使用SQL Server 2008,ASP.NET MVC 4和C#。

4 个答案:

答案 0 :(得分:0)

如果您能够修改存储过程,则可以轻松地将所需的列定义作为参数并使用自动创建的临时表:

CREATE PROCEDURE sp_GetDiffDataExample
      @columnsStatement NVARCHAR(MAX) -- required columns statement (e.g. "field1, field2")
AS
BEGIN
    DECLARE @query NVARCHAR(MAX)
    SET @query = N'SELECT ' + @columnsStatement + N' INTO ##TempTable FROM dbo.TestTable'
    EXEC sp_executeSql @query
    SELECT * FROM ##TempTable
    DROP TABLE ##TempTable
END

在这种情况下,您不需要手动创建临时表 - 它是自动创建的。

希望这有帮助。

答案 1 :(得分:0)

您只需传递一个参数,该参数是您要选择的列的逗号分隔字符串,并构建动态sql字符串。

@sql = 'SELECT ' + @param + ' FROM MyTable...';
EXECUTE (@sql);

如果您使用动态SQL解决方案,则应注意防范SQL注入攻击。

您可能还会考虑继续从存储过程中获取所有列,并仅显示用户在前端所需的列。

答案 2 :(得分:0)

虽然我真的不喜欢这个问题的存储过程方法(我同意@Gusman在C#中构建查询是一种更好的方法),但是你可以使存储过程工作而不会打开SQL注入攻击。以下示例是一种简单的方法:

假设有问题的表格中包含名为COL1COL2COL3的列。存储过程将接受名为varchar(max)的{​​{1}}参数,其代码如下:

@IncludeCols

是的,将返回每个名称的列,但数据将仅来自名称在参数中的列。例如,如果您想要SELECT CASE WHEN @IncludeCols LIKE '%#COL1#%' THEN COL1 ELSE '' END AS COL1, CASE WHEN @IncludeCols LIKE '%#COL2#%' THEN COL2 ELSE '' END AS COL2, CASE WHEN @IncludeCols LIKE '%#COL3#%' THEN COL3 ELSE '' END AS COL3 FROM <Table name> WHERE <Where clause> COL1,则参数值为COL3#COL1#COL3#很重要,必须位于每个列名的每一侧,否则任何#子句都可能会出现误报。

答案 3 :(得分:0)

如果要将数据导出到Excel,那么最好的方法可能是有一个存储过程可以返回所有列,而不是从不导出的列(密码,其他受保护的数据,也许是时间戳)然后过滤掉前端的任何其他不需要的列。

您应该从不使用SELECT *有几个原因。定义您的应用程序需要的内容并对其进行编程。