MSSQL存储过程选择所有列
我有一个存储过程,其中SELECT语句如下所示:MSSQL存储过程选择所有列,sql,sql-server,stored-procedures,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) DECLARE @SqlCommand nvarchar(max) SELECT @SqlCommand = 'SELECT ' + @ke
SELECT @KeyName FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = @IssuerKey
CREATE PROCEDURE GET_FICONFIG
@IssuerKey INT,
@KeyName NVARCHAR(100)
DECLARE @SqlCommand nvarchar(max)
SELECT @SqlCommand = 'SELECT ' + @keyname + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + cast(@IssuerKey as varchar(10))
EXEC sp_executeSQL @SqlCommand
我是这样创建的:
SELECT @KeyName FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = @IssuerKey
CREATE PROCEDURE GET_FICONFIG
@IssuerKey INT,
@KeyName NVARCHAR(100)
DECLARE @SqlCommand nvarchar(max)
SELECT @SqlCommand = 'SELECT ' + @keyname + ' FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = ' + cast(@IssuerKey as varchar(10))
EXEC sp_executeSQL @SqlCommand
其中,KeyName
是我从中检索数据的列名
我的问题:尽管过程要求特定的列名,但是否可以传入*
以选择所有列
编辑:
不幸的是,我想我的问题措辞可能很糟糕。我正在寻找一种方法,看看我的存储过程是否能够判断我是要从表中选择所有记录,还是只从记录中选择特定列。我已经用一些空检查和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注入
。但您不能将列名作为参数传递给动态查询,所以没有其他方法
但您可以从信息\u 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)
试着这样做:
SELECT @KeyName FROM dbo.FiConfig WITH (NOLOCK) WHERE IssuerKey = @IssuerKey
CREATE PROCEDURE GET_FICONFIG
@IssuerKey INT,
@KeyName NVARCHAR(100)
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注入;从用户中删除--代码>
但是,您可以通过参数化sp_executesql
来缓解这一问题;此存储过程的文档如下所示:
但是,sp_executesql
的参数化会阻止您将'*'
作为参数传递给存储过程…sp可能“询问”特定的列名,但是SELECT
的结果实际上是列名,而不是列名的值感谢您的澄清,这是我期待的行为。我对SQL相当陌生!任何特定查询都将返回具有固定“形状”的结果集,即结果集中列的数量、名称和类型。如果要更改生成的列,则需要在运行时构造新的查询—也称为动态SQL。@T.s.不,它不容易进行SQL注入。op真正想要做的(使用动态SQL)可以be@Lamak因此,如果有人将另一个select放入@KeyName
,它将不起作用?您应该在@KeyName
上使用QUOTENAME
,以避免使用某些列名发出。此外,如果您明确地将@IssuerKey
转换为varcharI,则会更好。我还建议您在查询信息\u SCHEMA.COLUMNS
时检查表\u SCHEMA='dbo'
。