MSSQL存储过程选择所有列

时间:2015-06-04 14:19:49

标签: sql sql-server stored-procedures

我有一个存储过程,其中SELECT语句如下所示:

SELECT @KeyName FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = @IssuerKey

我在这里创建它:

CREATE PROCEDURE GET_FICONFIG
   @IssuerKey INT,
   @KeyName NVARCHAR(100)

KeyName是我要从中检索数据的列名。

我的问题:是否可以传递*来选择所有列,尽管该过程要求特定的列名称?

编辑: 不幸的是,我觉得我的问题可能很糟糕。我正在寻找一种方法来查看我的存储过程是否可以告诉我是否要从表中选择所有记录,或者只是从记录中选择特定列。我使用一些NULL检查和if / else语句解决了我自己的问题。

2 个答案:

答案 0 :(得分:2)

您可以使用动态查询:

CREATE PROCEDURE GET_FICONFIG
   @IssuerKey INT,
   @KeyName NVARCHAR(100)
AS
declare @s varchar(500) = 'SELECT ' + @KeyName + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + CAST(@IssuerKey as VARCHAR(10))
exec(@s)

你在这里应该小心。可能Sql Injection。但是你不能将列名作为参数传递给动态查询,所以没有别的办法。

但您可以从INFORMATION_SCHEMA.COLUMNS表中进行选择,以确保传递了有效的列名:

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
          WHERE TABLE_NAME = 'FiConfig' AND COLUMN_NAME = @KeyName)
BEGIN
    declare @s varchar(500) = 'SELECT ' + @KeyName + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + CAST(@IssuerKey as VARCHAR(10))
    exec(@s)
END
ELSE
    THROW...

修改

用户@Lamak表示更好地使用QUOTENAME功能。它会自动在变量值周围添加括号:

CREATE PROCEDURE GET_FICONFIG
   @IssuerKey INT,
   @KeyName NVARCHAR(100)
AS
declare @s varchar(500) = 'SELECT ' + QUOTENAME(@KeyName) + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + CAST(@IssuerKey as VARCHAR(10))
exec(@s)

答案 1 :(得分:0)

尝试这样的事情:

DECLARE @SqlCommand nvarchar(max)

SELECT @SqlCommand = 'SELECT ' + @keyname + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + cast(@IssuerKey as varchar(10))

EXEC sp_executeSQL @SqlCommand

这将允许您传入列名或任意表达式(例如*或聚合函数,如sum()

请记住,这是危险的,因为@keyname上没有验证,所以如果有人传入,它很容易进行SQL注入,例如字符串''; DELETE FROM USERS; --

但是,您可以参数化sp_executesql来缓解此问题;此存储过程的文档位于: https://msdn.microsoft.com/en-gb/library/ms188001.aspx

sp_executesql的参数化会阻止您将'*'作为参数传递给存储过程......