【问题标题】:SQL Server : generate select statement dynamically inside a stored procedure with dynamic column namesSQL Server:在具有动态列名的存储过程中动态生成选择语句
【发布时间】:2013-10-19 13:11:39
【问题描述】:

我想在 SQL Server 存储过程中生成一个 select 语句。我在 SQL 参数中有列名。

我正在尝试使用选定的列名以编程方式生成 select 语句,但似乎无法在存储过程中找到正确的语法。

CREATE PROCEDURE dbo.aProc
     @testCondition int,
     @colCount int,
     @column_1 varchar(100) = null,
     ....
    @column_40 varchar(100) null
AS
  DECLARE @qry nvarchar(3000)
  DECLARE @Iterator int

  SET @testtype = 2
  SET @Iterator = 0
  SET @qry  ='SELECT '

  WHILE (@Iterator < @colCount-1)
    BEGIN
        SET @qry = @qry + ''+@column_''+CAST(@Iterator as varchar(2))+',''
        Set @Iterator = @Iterator + 1
    END


  SET @qry = @qry + ''@column_+CAST(@colCount as varchar(2)) FROM aTable where aCol = @testCondition 

【问题讨论】:

  • 为什么需要 + '' + 部分?您在冒号后也有 2 个引号而不是 1 个引号。你能解释一下你想在你的过程中实现什么吗?
  • 我想根据想要查看的列生成一个 SELECT stmnt,所以对我来说最简单的方法是在 sql para 中传递列名,并根据它们在存储中动态生成 sql select stmnt过程。
  • 好吧,我想说改变你的 proc 签名更容易,如果你真的确定要执行此任务,你可以传递像'column1,column2,column3'之类的字符串
  • 它已经有了这个签名,我正在尝试通过循环以最小的努力、代码行来“构建”查询字符串
  • 堆栈溢出语法高亮显示已经向您显示错误:字符串文字。 SQL Server 也会通过它的消息告诉你。

标签: sql stored-procedures sql-server-2008-r2


【解决方案1】:

这看起来是个坏主意 (obligatory sql injection link) 有可能的替代方案

要回答问题,请执行以下操作。

DECLARE @sql VARCHAR(MAX)

SET @sql = 'SELECT ' + 
               ISNULL(@col1, '') + ', ' +
               ISNULL(@col2, '') + ', ' +
               ISNULL(@col3, '') + ', ' +
               ISNULL(@col4, '') + ', ' +
               ISNULL(@col5, '') + ', ' +
               -- ...
           'FROM tbl WHERE ' ...

这样做——或者也许正如 cmets 所建议的那样——比搞乱循环更省力(顺便说一句,你很不擅长)。

说实话,虽然使用内联函数似乎会更好

CREATE FUNCTION dbo.vSomeTable
    (@id INT)
RETURNS TABLE
AS
RETURN (
    SELECT * FROM tbl WHERE condition = @id
)

然后让用户去做

SELECT col1, col2, col2 FROM dbo.vSomeTable(4)

EXEC dbo.aProc @condition=1, @col1='col1', @col2='col2'

【讨论】:

    【解决方案2】:
    CREATE PROCEDURE dbo.aProc
        @tablename varchar(100),
         @testCondition int,
         @colCount int,
         @column_1 varchar(100) = '',
         ....
        @column_40 varchar(100) ''
    AS
    BEGIN
    if object_id('tempdb..#t') is not null
    drop table #t
    
    
    select 
    table_name
    ,column_name
    into #t
    from information_schema.columns
    where table_name=@tablename
    and column_name in 
    (@column_1,@column_2,@column_3,@column_4,@column_5
    .....
    @column_36,@column_37,@column_38,@column_39,@column_40)
    
    select 
      'select '+
      stuff((
        select ', ' + 'isnull('+t2.column_name+','''') as' +t2.column_name+CHAR(10)
        from #t t2
        where t2.table_name = #t.table_name
        for xml path (''))
    ,1,2,'')+' from ' +#t.table_name
    from #t
    group by #t.table_name
    
    END
    

    我不是 LOOP 的崇拜者。事实上我讨厌循环查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多