4

ユーザーが Web ページで選択した値を使用して文字列を作成する必要があります。

異なる検索条件で複数のマシンのファイルを表示する必要があるとします...

私は現在このコードを使用しています:

DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection();
connection.ConnectionString = ConfigurationManager
               .ConnectionStrings["DBConnectionString"].ConnectionString;
connection.Open();
SqlCommand sqlCmd = new SqlCommand
  ("SELECT FileID FROM Files
    WHERE MachineID=@machineID and date= @date", connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);

sqlCmd.Parameters.AddWithValue("@machineID", machineID);
sqlCmd.Parameters.AddWithValue("@date", date);

sqlDa.Fill(dt);

これは、ユーザーがマシンを 1 台だけ持っていて、日付を 1 つ選択するだけの固定クエリです...

ユーザーが選択したものに応じて必要に応じて、タイプやサイズなどの複数の検索オプションを持つクエリを作成したいと考えています。

また、複数のマシンを選択できる場合は...

SELECT FileID FROM Files
WHERE (MachineID=@machineID1 or MachineID = @machineID2...)
AND (date= @date and size=@size and type=@type... )

これはすべて実行時に発生します...それ以外の場合は、forループを作成して複数のマシンを 1 つずつ配置する必要があります...そして、ユーザーが選択したケースに応じて複数のクエリを実行する必要があります...

これは非常に興味深いものであり、私はいくつかの助けを借りることができます...

4

6 に答える 6

2

使用できますWHERE MachineID IN ('Machine1', 'Machine2', 'Machine3', ... 'MachineN')

次に、ループで 1..n マシンを追加します。IN 句は 1 要素または n 要素で機能するため、問題ないはずです。

ただし、アプリケーションに SQL をハードコーディングするのではなく、ストアド プロシージャを使用することを検討します。

于 2010-04-16T21:58:37.313 に答える
2

実際のテーブルを構築し、マシン ID をそこにロードします。

次に、SQLは次のようになります。

where MachineID in ( select MachineID from userMachine where userID = x)

完了したら、userID のすべての行を削除します。

delete from userMachine where userID = x.
于 2010-04-16T22:03:56.940 に答える
2

これを動的 SQL 経由で行う場合は、IN 関数への呼び出しを作成する必要があります。(例: In(id1, id2, id3...)

private string GetSql( IList<int> machineIds )
{
    var sql = new StringBuilder( "SELECT FileID FROM Files Where MachineID In(" );
    for( var i = 0; i < machineIds.Count; i++ )
    {
        if ( i > 0 )
            sql.Append(", ")
        sql.Append("@MachineId{0}", i);
    }

    sql.Append(" ) ");

    //additional parameters to query
    sql.AppendLine(" And Col1 = @Col1" );
    sql.AppendLine(" And Col2 = @Col2 ");
    ...

    return sql.ToString();
}

private DataTable GetData( IList<int> machineIds, string col1, int col2... )
{
    var dt = new DataTable();
    var sql = GetSql( machineIds );
    using ( var conn = new SqlConnection() )
    {
        conn.ConnectionString = ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString;
        using ( var cmd = new SqlCommand( sql, conn ) )
        {
            conn.Open();

            for( var i = 0; i < machineIds.Count; i++ )
            {
                var parameterName = string.Format("@MachineId{0}", i );
                cmd.Parameters.AddWithValue( parameterName, machineIds[i] );
            }

            cmd.Parameters.AddWithValue( "@Col1", col1 ); 
            cmd.Parameters.AddWithValue( "@Col2", col2 ); 
            ...

            using ( var da = new SqlDataAdapter( cmd ) )
            {
                da.Fill( dt );
            }
        }
    }

    return dt;
}
于 2010-04-16T22:06:39.230 に答える
1

通常、「検索」タイプのクエリを作成する場合は、オプションのパラメータを使用します。これにより、パラメータに何かまたは何も送信できなくなり、クエリがあいまいなものから非常に具体的なものになります。

例:

SELECT
  COL1,
  COL2,
  COL3
FROM TABLE
WHERE (@COL1 IS NULL OR @COL1 = '' OR @COL1 = COL1)

上記で気付くように、NULLまたはBLANKを渡しても、パラメータはクエリに追加されません。値を入力すると、その値が比較に使用されます。

于 2010-04-16T23:32:08.713 に答える
1

また、ストアド プロシージャを使用することをお勧めします。そうしないと、特にユーザー入力に基づいて文字列を作成する場合に、SQL インジェクション攻撃にさらされることになります。

何かのようなもの:

a' or 1=1; -- Do bad things

SQL で sp_executesql を使用して、@dcp が提案するような句で構築された SQL ステートメントを実行できますwhere。最適化はうまくいきませんが、とにかく実行するのはおそらく簡単なコマンドです。

例による SQL インジェクション攻撃

これを実現する 1 つの方法は、charindex を使用することです。この例は、スペースで区切られた ID のリストが渡されたときにストアド プロシージャを実行する方法を示しています。

declare @machine table (machineId int, machineName varchar(20))
declare @files table (fileId int, machineId int)

insert into @machine (machineId, machineName) values (1, 'machine')
insert into @machine (machineId, machineName) values (2, 'machine 2.0')
insert into @machine (machineId, machineName) values (3, 'third machine')
insert into @machine (machineId, machineName) values (4, 'machine goes forth')
insert into @machine (machineId, machineName) values (5, 'machine V')

insert into @files (fileId, machineId) values (1, 3)
insert into @files (fileId, machineId) values (2, 3)
insert into @files (fileId, machineId) values (3, 2)
insert into @files (fileId, machineId) values (4, 1)
insert into @files (fileId, machineId) values (5, 3)
insert into @files (fileId, machineId) values (6, 5)

declare @machineText1 varchar(100)
declare @machineText2 varchar(100)
declare @machineText3 varchar(100)

set @machineText1 = '1 3 4'
set @machineText2 = '1'
set @machineText3 = '5 6'

select * from @files where charindex(rtrim(machineId), @machineText1, 1) > 0
-- returns files 1, 2, 4 and 5

select * from @files where charindex(rtrim(machineId), @machineText2, 1) > 0
-- returns file 4

select * from @files where charindex(rtrim(machineId), @machineText3, 1) > 0
--returns file 6

したがって、このストアド プロシージャを作成して目的を達成できます。

create procedure FilesForMachines (@machineIds varchar(1000))
as
select * from [Files] where charindex(rtrim(machineId), @machineIds, 1) > 0

charindex のヒントはBugSplatからのものです。

于 2010-04-16T22:09:25.360 に答える
1

理想的には、「MachineID in (1, 2, 3, 4)」を動的に作成するのと同様のソリューションに到達しようとしています。

オプション1

コンマ区切りの文字列をストアド プロシージャに渡し、SQL 文字列を動的に構築してから "EXEC sp_executesql @sql" WHERE IN (ID の配列) を呼び出すことで、このタスクを完了する方法は多数あります。

オプション 2

コンマで区切られた値の文字列を渡し、値を解析して独自の一時テーブルに入れ、それに参加できます http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm

オプション 3 - 私の選択

XML を使用して値の配列を渡し、配列項目を簡単に選択できるようになりました。 http://support.microsoft.com/kb/555266

.

于 2010-04-16T22:03:04.803 に答える