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