Search code examples
delphiadotadoquery

TAdoquery date format


I am Java developer. I have some old program in Delphi. In old version they work with mdb. I fixed it for connection with SQL Server. All SQL queries are implemented with TAdoQuery.

qryTemp.SQL.Text:='select  sum(iif(ComeSumm>0,comesumm,0)),sum(iif(lostSumm>0,lostsumm,0)) from cash '+
   'where (IdCashClause is null or idcashclause<>8) '+
  ' and cashNum='+IntToStr(i)+
  ' and CashType=0'+
  ' and format(PayDate,"dd/mm/yyyy")=format('''+DateToStr(Date)+''',"dd/mm/yyyy") ';

The program throws an exception:

Invalid column name 'dd/mm/yyyy'.

I have fixed other query for comparison:

 qryTemp.SQL.Text:=' select top 1 iif(ComeSumm>0,comesumm,0) from cash '
                     +' where idCashReason=1 and idCashClause=8 and cashNum='+IntToStr(i)
                     +' and PayDate<:D'
                     +' order by payDate desc';
qryTemp.Parameters.ParamByName('D').Value:=DateTimeToStr(Date);

Can I quickly fix all queries for work with SQL Server without rewriting the whole project?


Solution

  • Assuming PayDate is defined as date/datetime in MSSQL you could use parameters as follow:

    qryTemp.SQL.Text:=' select top 1 iif(ComeSumm>0,comesumm,0) from cash '
                         +' where idCashReason=1 and idCashClause=8 and cashNum='+IntToStr(i)
                         +' and PayDate<:D'
                         +' order by payDate desc';
    qryTemp.Parameters.ParamByName('D').Value := Date;
    qryTemp.Parameters.ParamByName('D').DataType := ftDateTime;
    

    I'd also change cashNum to parameter i.e.:

    ...
    +' where idCashReason=1 and idCashClause=8 and cashNum=:cashNum'+
    ...
    qryTemp.Parameters.ParamByName('cashNum').Value := i;
    

    Always prefer to use compatible data types with your parameters, rather than formatting and using strings. SQL does not need to guess your data types if you can explicitly define them.

    Note: IIF was introduced in SQL Server 2012. for older version use CASE expression.


    In older Non-Unicode Delphi versions, Parameters have issue with Unicode.
    So, If you don't use Parameters you could use the following:

    function DateTimeToSqlDateTime(const DT: TDateTime): WideString;
    begin
      Result := FormatDateTime('yyyy-MM-dd', DT) + ' ' + FormatDateTime('hh:mm:ss', DT);
    end;
    
    function SqlDateTimeStr(const DT: TDateTime; const Is_MSSQL: Boolean): WideString;
    var
      S: WideString;
    begin
      S := DateTimeToSqlDateTime(DT);
      if Is_MSSQL then
        Result := Format('CONVERT(DATETIME, ''%s'', 102)', [S]) 
      else
        Result := Format('#%s#', [S]); // MS-ACCESS
    end;
    

    And your query will look as follow:

    ...
    +' and PayDate<' + SqlDateTimeStr(Date, True)
    ...