2012-04-10 16 views
21
create procedure sp_First 
@columnname varchar 
AS 
begin 
select @columnname from Table_1 
end 
exec sp_First 'sname' 

私の要件は、入力パラメータとして列名を渡すことです。 私はそれを試しましたが、間違った出力を出しました。SQLストアド・プロシージャの入力パラメータとして列名を渡すことはできますか?手順

だから助けてください

+3

この質問に対する最善の回答を選択してください。現在の最初の回答は誤解を招く可能性があります。 – ctbrown

答えて

5

これはできません。動的SQL(危険)または巨大なケース式(遅い)のいずれかを使用します。

+0

CASEがSELECTステートメント(JOIN、WHERE句、ORDER BYなどではない)にのみ存在する場合、このオプションは実際には遅くはありません。 – MatBailie

+1

どの具体的な列が要求されても、毎回すべての列が引き出されます。 – usr

9

いいえ、それはパラメータ値を選択するだけです。動的SQLを使用する必要があります。あなたは、次のを持っているでしょう、あなたの手順で

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

それは遅くなければなりません、そうですか?どれくらい?それは無視することができますか? –

+1

いいえ、それほど遅くはありません。遅い唯一の量は、文字列の連結オーバーヘッドです。 sp_executesqlは、他のコマンドと同様に、実行計画に変換される方法でテキストを実行します。 –

2

あなたは、列名を渡すことができますが、一つは、動的SQL文字列を構築することができ

Select @Columnname From Table 

ようなSQL statemntでそれを使用することはできませんそれを実行してくださいEXEC (@SQL)

詳細については、動的SQLに関するこの回答を参照してください。

Dynamic SQL Pros and Cons

8

、動的SQLを使用してみてください:

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

exec sp_First 'sname' 
go 
45

あなたはいくつかの方法でこれを行うことができます。

1つは、自分でクエリを構築して実行することです。

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 

これはもう少し長いったらしいが、全体の多くより安全です。

+9

+1、 'これはもう少し長いですが、ずっと安全です。 ' –

+0

別のテーブル「UpdateableColumns」から列を取得している場合は、何らかの検証を行うこともできます。 例:「列が存在する場所(UpdateableColumnsからColumnNameを選択)」 – EduLopez

-5

これを試してください。 私はそれがあなたのために働くことを願っています。

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 **/ 
+0

選択*は良い方法ではなく、これはユーザーの疑問ではありません – Tiago

2
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 = ''''[email protected]+ '''' 
     SET @cmd = N'SELECT * FROM ' + @TableName + ' WHERE ' + @ColumnName + ' = ' + @Value 
     EXEC(@cmd) 
     END 

私は1つの答えを試してきたように、それが正常に実行されつつあるが、MatBailie で述べたようにも、そのは正しい出力を与えない

0

を上記の作業を実行しながら、これははるかに安全ですこれは動的クエリではなく、SQLインジェクションの可能性が低いためです。私はwhere句を動的にしたいという状況を1つ追加しました。 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 
関連する問題