MSSQL 存储过程 select 所有列

MSSQL stored procedure select all columns

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

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

我在哪里创建它是这样的:

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

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

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

编辑: 不幸的是,我认为我的问题可能措辞不当。我正在寻找一种方法来查看我的存储过程是否可以判断我是否想要 select 来自 table 的所有记录,或者只是来自记录的特定列。我已经使用一些 NULL 检查和 if/else 语句解决了我自己的问题。

您可以使用动态查询:

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。但是不能将列名作为参数传递给动态查询,所以没有别的办法。

但是您可以 select 来自 INFORMATION_SCHEMA.COLUMNS table 以确保传递了有效的列名:

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)

尝试这样的事情:

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 的参数化会阻止您将 '*' 作为参数传递给存储过程...