13

整数または文字列のリストがあり、それを Delphi DataSet のパラメータとして渡す必要があります。どうやってするの?

ここに例があります。MyQuery は次のようなものです。

select * from myTable where intKey in :listParam

パラメータをリストまたは配列などとして設定します。

MyQuery.ParamByName('listParam').AsSomething := [1,2,3];

そして、次のクエリが SQL サーバーに送信されます。

select * from myTable where intKey in (1, 2, 3)

ソリューションが文字列でも機能し、次のクエリを作成するとさらに良いでしょう。

select * from myTable where stringKey in :listParam

なる:

select * from myTable where stringKey in ('a', 'b', 'c')

これは簡単な質問だと思いますが、「IN」は Web を検索するための適切なキーワードではありません。

IDEでパラメータを設定する方法、クエリ、およびパラメータを渡す方法に答えてください。

Delphi 7 を使用しています。

編集済み:答えは「直接行うことはできない」と考えています。誰かがハックではない回答をくれた場合、受け入れられた回答が変更されます。

4

7 に答える 7

11

私の知る限り、直接はできません。

リストをプレーンテキストの SQL リストに変換する必要があります。

例えば:

function ListToText(const Args: array of string): string; overload;
var i: integer;
begin
  result := '(';
  for i := 0 to high(Args) do 
    result := result+QuotedStr(Args[i])+',';
  result[length(result)] := ')';
end;


function ListToText(const Args: array of integer): string; overload;
var i: integer;
begin
  result := '(';
  for i := 0 to high(Args) do 
    result := result+IntToStr(Args[i])+',';
  result[length(result)] := ')';
end;

そのように使用するには:

SQL.Text := 'select * from myTable where intKey in '+ListToText([1,2,3]);
SQL.Text := 'select * from myTable where stringKey in '+ListToText(['a','b','c']);
于 2012-04-10T15:40:03.517 に答える
4

SQLはパラメーターとして単一の値のみを受け入れるため、指定した例のように、可変数の値にマップできる1つのパラメーターを持つステートメントを作成することはできません.

ただし、この状況でもパラメーター化された SQL を使用できます。解決策は、SQL にパラメーター マーカーを追加し、各値のパラメーター リストにパラメーターを追加して、値のリストを反復処理することです。

これは、名前付きパラメータではなく位置パラメータで行うのが最も簡単ですが、名前付きパラメータにも適用できます (Delphi を使用できず、パラメータ作成構文を覚えていないため、このコードを調整する必要がある場合があります)。

 //AValues is an array of variant values
 //SQLCommand is some TDataSet component with Parameters.
 for I := Low(AValues) to High(AValues) do
 begin

    if ParamString = '' then
       ParamString = '?'
    else
      ParamString = ParamString + ', ?';

    SQLCommand.Parameters.Add(AValues[I]);

  end

  SQLCommand.CommandText = 
     'SELECT * FROM MyTable WHERE KeyValue IN (' + ParamString + ')';

これにより、インジェクション セーフなパラメーター化されたクエリが生成されます。

于 2012-04-10T18:38:59.930 に答える
3

いくつかのオプションがありますが、基本的には値をテーブルに入れる必要があります。そのためのテーブル変数をお勧めします。

これは int リストを展開するバージョンです。

declare @IDs varchar(max)
set @IDs = :listParam

set @IDs = @IDs+','

declare @T table(ID int primary key)

while len(@IDs) > 1
begin
  insert into @T(ID) values (left(@IDs, charindex(',', @IDs)-1))
  set @IDs = stuff(@IDs, 1, charindex(',', @IDs), '')
end

select *
from myTable
where intKey in (select ID from @T)

複数ステートメントのクエリを使用することができます。パラメータ:listParamは文字列でなければなりません:

MyQuery.ParamByName('listParam').AsString := '1,2,3';

文字列にも同じ手法を使用できます。IDのデータ型をたとえばに変更するだけですvarchar(10)

while ループでアンパックする代わりに、分割関数を利用できます

declare @T table(ID varchar(10))

insert into @T 
select s
from dbo.Split(',', :listParam)

select *
from myTable
where  charKey in (select ID from @T)

文字列パラメーターは次のようになります。

MyQuery.ParamByName('listParam').AsString := 'Adam,Bertil,Caesar';
于 2012-04-10T19:08:50.053 に答える
1

一時テーブルを作成し、そこに値を挿入します。次に、そのテーブルをサブクエリの一部として使用します。

たとえば、データベースに MyListTable を作成します。値を MyListTable に挿入します。それからする

select * from myTable where keyvalue in (select keyvalue from MyListTable)

これにより、SQL インジェクション攻撃を回避できます。ただし、クエリを実行する前にレコードを挿入する必要があり、同時実行の問題が発生する可能性があるため、エレガントではなく、パフォーマンスに優しくありません。

あなたの状況に対処するための私の最初の選択ではありませんが、SQL インジェクションに関する懸念に対処します。

于 2012-04-10T18:19:47.400 に答える
0

動的SQLを作成してみませんか:

クイックで汚れていますが、まだパラメーターを使用しています。10個の要素をチェックしてください。これがどれだけスケールするかはわかりません。

    MyQuerySQL.Text:='SELECT * FROM myTable WHERE intKey in (:listParam0'
    for i := 1 to 9 do begin
      MyQuerySQL.Text := MyQuerySQL.Text + ',:listParam'+IntToStr(i)
    end;
    MyQuerySQL.Text := MyQuerySQL.Text+')';
    for i:=0 to 9 do begin
      MyQuery.ParamByName('listParam'+IntToStr(i)).AsInteger := ArrayofInt[0];
    end;
于 2012-04-11T07:20:16.100 に答える
0

私はいくつかの「IN」置換を使用します。私が使用するクエリは次のとおりです。

SELECT * FROM MyTable WHERE CHARINDEX(','+cast(intKey as varchar(10))+',', :listParam) > 0

パラメータを送信するコード:

MyQuery.ParamByName('listParam').AsString := ',1,2,3,';  

配列項目の値は、他の値と部分的に一致する場合があります。たとえば、「1」は「100」の一部になることがあります。それを防ぐために、区切り文字としてコンマを使用します

于 2012-04-10T18:25:04.813 に答える