Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MSSQL存储过程选择所有列_Sql_Sql Server_Stored Procedures - Fatal编程技术网

MSSQL存储过程选择所有列

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语句如下所示:

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'