【问题标题】:Can I pass column name as input parameter in SQL stored Procedure我可以在 SQL 存储过程中将列名作为输入参数传递吗
【发布时间】:2012-04-22 23:40:40
【问题描述】:
create procedure sp_First
@columnname varchar
AS
begin
select @columnname from Table_1
end 
exec sp_First 'sname'

我的要求是将列名作为输入参数传递。 我试过这样,但它给出了错误的输出。

帮帮我

【问题讨论】:

  • 能否请您选择此问题的最佳答案,当前第一个答案具有误导性。

标签: sql stored-procedures


【解决方案1】:

这是不可能的。要么使用动态 SQL(危险),要么使用巨大的 case 表达式(慢)。

【讨论】:

  • 如果 CASE 仅在 SELECT 语句中(而不在 JOIN、WHERE 子句、ORDER BY 等中),那么这个选项实际上并没有那么慢。
  • 无论请求什么具体的列,每次都会拉出所有列。
【解决方案2】:

没有。那只会选择参数值。您需要使用动态 sql。

在您的程序中,您将拥有以下内容:

DECLARE @sql nvarchar(max) = 'SELECT ' + @columnname + ' FROM Table_1';
exec sp_executesql @sql, N''

【讨论】:

  • 不,不会慢很多。唯一变慢的是字符串连接开销。 sp_executesql 将以一种将文本转换为执行计划的方式执行文本,就像任何其他命令一样。
【解决方案3】:

您可以传递列名,但不能在 sql statemnt 中使用它,例如

Select @Columnname From Table

可以构建一个动态 sql 字符串并像 EXEC (@SQL) 一样执行它

有关更多信息,请参阅此关于动态 sql 的答案。

Dynamic SQL Pros and Cons

【讨论】:

    【解决方案4】:

    尝试使用动态 SQL:

    create procedure sp_First @columnname varchar 
    AS 
    begin 
        declare @sql nvarchar(4000);
        set @sql='select ['+@columnname+'] from Table_1';
        exec sp_executesql @sql
    end 
    go
    
    exec sp_First 'sname'
    go
    

    【讨论】:

      【解决方案5】:

      您可以通过多种方式做到这一点。

      一是自己构建查询并执行。

      SET @sql = 'SELECT ' + @columnName + ' FROM yourTable'
      sp_executesql @sql
      

      如果您选择该方法,请务必确认您的输入。即使您知道您的应用程序只会给出“真实”的列名,如果有人发现您的安全漏洞并能够直接执行 SP 怎么办?然后他们可以执行他们喜欢的任何事情。使用动态 SQL,总是,总是,验证参数。

      或者,您可以编写 CASE 语句...

      SELECT
        CASE @columnName
          WHEN 'Col1' THEN Col1
          WHEN 'Col2' THEN Col2
                      ELSE NULL
        END as selectedColumn
      FROM
        yourTable
      

      这有点冗长,但更安全。

      【讨论】:

      • +1, This is a bit more long winded, but a whole lot more secure.
      • 如果您从另一个表“UpdateableColumns”中获取列,您也可以使用它进行某种验证。示例:“列存在的位置(从 UpdateableColumns 中选择 ColumnName)”
      【解决方案6】:

      请试试这个。 我希望它对你有用。

      Create Procedure Test
      (
          @Table VARCHAR(500),
          @Column VARCHAR(100),
          @Value  VARCHAR(300)
      )
      AS
      BEGIN
      
      DECLARE @sql nvarchar(1000)
      
      SET @sql = 'SELECT * FROM ' + @Table + ' WHERE ' + @Column + ' = ' + @Value
      
      --SELECT @sql
      exec (@sql)
      
      END
      
      -----execution----
      
      /** Exec Test Products,IsDeposit,1 **/
      

      【讨论】:

      • 选择 * 不是一个好习惯,这不是用户的疑惑
      【解决方案7】:
         Create PROCEDURE USP_S_NameAvilability
           (@Value VARCHAR(50)=null,
            @TableName VARCHAR(50)=null,
            @ColumnName VARCHAR(50)=null)
              AS
              BEGIN
              DECLARE @cmd AS NVARCHAR(max)
              SET @Value = ''''+@Value+ ''''
              SET @cmd = N'SELECT * FROM ' + @TableName + ' WHERE ' +  @ColumnName + ' = ' + @Value
              EXEC(@cmd)
            END
      

      因为我已经尝试了一个答案,它正在成功执行,但是在运行时它没有给出正确的输出,上面的效果很好

      【讨论】:

        【解决方案8】:

        正如 MatBailie 所说 这更安全,因为它不是动态查询,而且 sql 注入的机会更小。我添加了一种情况,您甚至希望 where 子句是动态的。 XX YY 是列名

                    CREATE PROCEDURE [dbo].[DASH_getTP_under_TP]
            (
            @fromColumnName varchar(10) ,
            @toColumnName varchar(10) , 
            @ID varchar(10)
            )
            as
            begin
        
            -- this is the column required for where clause 
            declare @colname varchar(50)
            set @colname=case @fromUserType
                when 'XX' then 'XX'
                when 'YY' then 'YY'
                end
                select SelectedColumnId  from (
               select 
                    case @toColumnName 
                    when 'XX' then tablename.XX
                    when 'YY' then tablename.YY
                    end as SelectedColumnId,
                From tablename
                where 
                (case @fromUserType 
                    when 'XX' then XX
                    when 'YY' then YY
                end)= ISNULL(@ID , @colname) 
            ) as tbl1 group by SelectedColumnId 
        
            end
        

        【讨论】:

          【解决方案9】:

          第一次运行;

          CREATE PROCEDURE sp_First @columnname NVARCHAR(128)--128 = SQL Server Maximum Column Name Length
          AS
          BEGIN
          
              DECLARE @query NVARCHAR(MAX)
          
              SET @query = 'SELECT ' + @columnname + ' FROM Table_1'
          
              EXEC(@query)
          
          END
          

          第二次运行;

          EXEC sp_First 'COLUMN_Name'
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-07-09
            • 1970-01-01
            • 2021-07-19
            • 2012-03-15
            • 1970-01-01
            相关资源
            最近更新 更多