4

私は自分の SQL ロジックに助けが必要です。私はこれを 2 日間作業 (および調査) してきましたが、まったく成功しませんでした。

私の目標は、変数を ASP ページからストアド プロシージャに渡すことです。ストアド プロシージャは、その変数を where 句の列名の基準として利用しています。

たとえば(私のクエリの簡略版):

@strDept nvarchar(10), @strUser nvarchar(30)
-- The asp page will pass f18 to @strDept & Ted Lee to strUser
-- f18 is the column name in my database that I need in the where.

select x, y, z from table1 where @strDept in (@strUser)
-- and this is the select statement, notice the where clause.

ストアド プロシージャは実行されますが、値は返されず、@strDept を列名ではなくリテラル nvarchar として扱っていることがわかります。

私の質問は、SQL Server 2005 で @sqlDept 変数を列名として扱うにはどうすればよいでしょうか?

4

7 に答える 7

7

これを行う方法に関するガイダンスが見つからない理由は、それが本当に悪い考えだからです。

遅かれ早かれ、誰かが の「列名」を渡すことになり1 ;drop database badideaます。これは関係者全員にとって祝福となるでしょう。

SQL インジェクションについて読んで、設計を再考してください。

于 2013-08-21T14:46:06.240 に答える
5

これが社内アプリケーションである場合、なぜ誰もが SQL インジェクションを繰り返して打ち負かしているのですか...動的 SQL を使用するのは非常に簡単です。これらがこれを使用している内部ユーザーのみであることに満足している場合は、非常に簡単です。これがコンセプトです。本質的には、実際には SQL ステートメントである文字列を書き込む SQL ステートメントを作成し、それを実行します。

CREATE Procedure myDynamicProcedure
@strDept nvarchar(10), 
@strUser nvarchar(30)

as 

BEGIN

1. SQL ステートメントを格納する変数を宣言します。

 DECLARE @SQL varchar(max)

2. @SQL 変数を SELECT ステートメントに設定します。基本的にあなたはそれを構築しているので、あなたが書きたいものを返します。このような:

   SET @SQL = 'select x, y, z from table1 where' + @strDept + 
 ' in ' + @strUser

3. @SQL ステートメントを実行すると、実行したのとまったく同じになります。 SELECT x,y,z from table1 where f18 = 'Ted Lee'

EXEC (@SQL)
END
于 2013-08-21T17:20:36.777 に答える
3

なぜ列名を動的にしたいのですか? 何を達成する予定ですか?上記の回答のような動的クエリを使用できますが、インジェクション攻撃が開始される可能性があります。

あなたがそれで何をしたいのかを説明していただければ、別の解決策をお勧めできるかもしれません.

于 2013-08-21T14:35:51.910 に答える
1

たとえば、いくつかの動的SQLを使用できます

DECLARE @sqlDept VARCHAR(100)='CURRENT_TIMESTAMP';

EXEC('SELECT '+@sqlDept)

あなたの場合、これは

DECLARE @strDept nvarchar(10)='dept1'
,@strUser nvarchar(30)='user1';

DECLARE @DynamicSql nvarchar(1000);

SET @DynamicSql='select x, y, z from table where '+@strDept+' in ('''+@strUser+''')';

それで

SELECT @DynamicSql;

あなたに与えます:

dept1 in ('user1') のテーブルから x、y、z を選択します

このステートメントを実行するには、次のようにします。

EXEC(@DynamicSql);
于 2013-08-21T14:32:46.403 に答える
0

最善の方法は、動的 SQL を作成し、ルックアップを追加して列が存在するかどうかを確認し、列名での SQL インジェクションを防ぐことだと思います。

declare @strDept nvarchar(10), @strUser nvarchar(30), 
        @sql nvarchar(300), @found smallint
set @strDept = 'f18'
set @strUser = 'Ted Lee'

set @found = (SELECT count(*) 
              FROM syscolumns 
              WHERE id=OBJECT_ID('table1') AND name=''+@strDept+'')

set @sql = 'select x, y, z from table1 where ' + @strDept + ' in ('''+@strUser+''')'

if @found = 1 exec (@sql)

SQL インジェクション テスト: SQL FIDDLE を参照してください: http://www.sqlfiddle.com/#!6/df3f6/18/0

于 2013-08-21T15:30:45.023 に答える
0

もう 1 つの方法は、proc で少し置換を使用することです。これは引き続き動的 SQL を使用しますが、ユーザーが指定した値を実行することはありません。

DECLARE @userSuppliedValue VARCHAR(50) = 'JOHNNY DROP TABLES'


DECLARE @substValue VARCHAR(50)

IF @userSuppliedValue = 'Table1'
  SET @substValue = 'Table1'

IF @userSuppliedValue = 'Table2'
  SET @substValue = 'Table2'

/*Repeat for N permutations*/

/* Throw an error if you think its necessary to do so when no match is found*/
IF @substValue IS NULL
  RAISERROR(1,1,'errah')

EXEC ('SELECT * FROM ' + @substValue)
于 2013-08-21T17:15:28.907 に答える
0
DECLARE @value varchar(10)  
SET @value = 'intStep'  
DECLARE @sqlText nvarchar(1000); 

SET @sqlText = N'SELECT ' + @value + ' FROM dbo.tblBatchDetail'
Exec (@sqlText)
于 2015-01-03T11:25:26.333 に答える