SQL准备参数FireDac使用“in”-clause

时间:2015-10-26 12:24:28

标签: delphi firedac

我正在努力使用带有FireDac的in运算符。

我使用的是oracle-database,无法使用简单的查询。

FDQuery1.SQL.Text := 'SELECT * FROM Customers WHERE Gender in (:Genders)';

FDQuery1.ParamByName('Genders').AsString:= 'M';

它适用于一个参数,但这显然不是in运算符的目的。

但是多个值不起作用:

FDQuery1.ParamByName('Genders').AsString:= 'M, F';
FDQuery1.ParamByName('Genders').AsString := '''M'', ''W''';

可能是不支持in运算符吗? 如果是这样,它会被替换为什么?

3 个答案:

答案 0 :(得分:3)

我刚刚在Embarcadero论坛上发现了this thread用户Serge Girard发布此解决方案:

使用宏而不是以一种不同的方式使用宏

SELECT * FROM `table` !mysel
and
Query.macrobyname('mysel').asraw:='WHERE Field in (1,2,3)';

SELECT * FROM table WHERE !mysel

no selection Query.MacroByName('mysel').asRaw:'1=1';
a selection Query.MacroByName('mysel').asRaw:'Field in (1,2,3)';

答案 1 :(得分:2)

如果您询问的是MS Sql Server或具有类似“IN”支持的后端,那么您不能将一系列值指定为查询的IN子句的单个参数。但是,一般(不是特定于FireDAC)的方法,不使用ad-hoc Sql(除非你小心,它具有Sql-Injection的风险)是

  • 使用一系列插入(或.InsertRecords上的TDataSet)将“IN”值插入到单列临时表中。这样做的好处是您不受参数化限制在IN列表中特定数量的值。

  • 然后执行“从MyTable中选择*,其中包含SomeColumn(从#MyTempTable中选择ColumnValue)

与仅在ad hoc Sql中指定IN列表值相比,它有点性能,当然,但从下面的示例中可以看出并不多。使用TDFQuery,创建INList表需要两个步骤,一个用于定义它,另一个用于从中执行Select *。使用TAdoQuery代替,可以组合这两个步骤。

TForm1 = class(TForm)
  FDQuery1: TFDQuery;
  qInlist: TFDQuery;
  [etc]

 const
  scCreateINListTable =
  'if object_id(''tempdb.dbo.#countrycodes'', ''U'') is not null drop table #countrycodes'#13#10
   + 'create table #countrycodes (ACode char(2))';

   scOpenINList = 'select * from #countrycodes';

   scGetClients = 'select * from client where country in (select ACode from #countrycodes)';

procedure TForm1.GetClients;
begin
  qINList.SQL.Text := scCreateINListTable;
  qINList.ExecSQL;

  qINList.SQL.Text := scOpenINList;
  qINList.Open;

  qINList.InsertRecord(['US']);
  qINList.InsertRecord(['GB']);
  qINList.InsertRecord(['IT']);

  FDQuery1.SQL.Text := scGetClients;
  FDQuery1.Open;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetClients;
end;

请注意,此实现根本不需要任何参数化或临时的Sql查询。

答案 2 :(得分:0)

如果您仍想对列表使用一个参数,则适用于SQL Server:

BCD
KLM

参数的值应该是由您知道不在字段中的字符(例如管道)分隔的任意数量的值:|

如果你通过'M | F',它将带回所有的M和F。

您也可以使用instr函数而不是charindex在Oracle中执行此操作。

我希望这会有所帮助。