Additional
Polls
What you would like to see in next AnyDAC versions ?
 
The parameterized SQL queries for the lazy
Posted by Diman [Sep 19, 2009]
I have seen many times, that programmers use the literals instead of the parameters in the SQL commands. Why it is so and how to change the situation ?

 

Why ? The answer is simple - the parameterized SQL query usage requires more coding. Compare:

 

ADOQuery1.SQL.Text := 'select * from tab where f1 = :p1';
ADOQuery1.Params[0].AsInteger := 10;
ADOQuery1.Open;

 

and

 

ADOQuery1.SQL.Text := 'select * from tab where f1 = ' + IntToStr(10);
ADOQuery1.Open;

 

So, it is much more simple to substitute a constant directly, right in the place where it is needed. And, I should agree, such code is more readable. But, I believe, the lazy is the primary factor :)

 

Note, I am writing about ADO and not about AnyDAC in this post. This post has a less value for AnyDAC, because in AnyDAC you can write using the "Less coding" approach.

 

For the funny, I have decided to help to the other DAC users too :) And using the class helpers and the IProviderSupport interface, which each good TDataSet descendant should implement, that may be implemented very easy. Using the next code, you can write using the lazy approach and still use the parameters !

 

unit LazyParams;
 
interface
 
uses
  DB;
 
type
  TDatasetHelper = class helper for TDataSet
  public
    function P(const AValue: Variant; ADataType: TFieldType = ftUnknown): String;
  end;
 
implementation
 
// TDatasetHelper
 
uses
  SysUtils;
 
function TDatasetHelper.P(const AValue: Variant; ADataType: TFieldType): String;
var
  oPSIntf: IProviderSupport;
  oParams: TParams;
  i: Integer;
begin
  oPSIntf := Self as IProviderSupport;
  oParams := oPSIntf.PSGetParams;
  i := oParams.Count + 1;
  while True do begin
    Result := ':P' + IntToStr(i);
    if oParams.FindParam(Result) = nil then
      Break;
    Inc(i);
  end;
  with TParam(oParams.Add) do begin
    Name := Result;
    if ADataType <> ftUnknown then
      DataType := ADataType;
    Value := AValue;
  end;
  oPSIntf.PSSetParams(oParams);
end;
 
end.

 

And the example of how to use that. Actually the mix of lazy and parameterized approaches:

 

uses
  ADODB, LazyParams, ...;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  with ADODataSet1 do begin
    CommandText := 'SELECT * FROM MyTab WHERE f1 = ' + P(10) + ' and f2 = ' + P(Date());
    Open;
  end;
end;

 

Disclaimer: The right parameters usage is to use the parameters explicitly !

Add Comments