我正在努力使用带有FireDac的in运算符.
我使用的是oracle-database,无法进行简单的查询.
FDQuery1.SQL.Text := 'SELECT * FROM Customers WHERE Gender in (:Genders)';
FDQuery1.ParamByName('Genders').AsString:= 'M';
Run Code Online (Sandbox Code Playgroud)
它适用于一个参数,但这显然不是in运算符的目的.
但是,多个值不起作用:
FDQuery1.ParamByName('Genders').AsString:= 'M, F';
FDQuery1.ParamByName('Genders').AsString := '''M'', ''W''';
Run Code Online (Sandbox Code Playgroud)
可能是不支持in运算符?如果是这样的话会被替换掉什么?
如果您询问 MS Sql Server 或对“IN”具有类似支持的后端,则无法将一系列值指定为查询的 IN 子句的单个参数。然而,在不使用 ad-hoc Sql 的情况下执行此操作的通用(不是特定于 FireDAC 的)方法(除非您小心,否则会带来 Sql 注入的风险):
使用一系列插入(或.InsertRecords在 上TDataSet)将“IN”值插入到单列临时表中。这样做的优点是您的参数化不受 IN 列表中特定数量的值的限制。
然后执行“Select * from MyTable where SomeColumn in (Select ColumnValue from #MyTempTable)
当然,与仅在 ad hoc Sql 中指定 IN 列表值相比,这会带来一些性能提升,但从下面的示例中可以看出,性能并不高。使用TDFQuerys,创建 INList 表需要两个步骤,一是定义它,二是从中执行 Select *。使用TAdoQuerys 代替,可以将这两个步骤结合起来。
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;
Run Code Online (Sandbox Code Playgroud)
请注意,此实现根本不需要任何参数化或即席 Sql 查询。
| 归档时间: |
|
| 查看次数: |
2401 次 |
| 最近记录: |