Search code examples
delphifiredac

Error using datetime parameter on firedac stored procedure component


I have a FDStored procedure that has a datetime parameter:

create procedure [dbo].[p_gl_for_ap]
(@inMode        char(1),  --I=Invoice, C=Check
 @inId_Invoice  integer,  --reqd for invoice or credit memo maintenance, I  
 @inReg         char(3),  --reqd for check update or void, C
 @inCheckNo     integer,  --reqd for check update or void, C
@inIs_Reversal char,     --Y only if Invoice Delete or Check Void   
 @inDt_Rev      datetime, --reqd only for reversal
 @inDt          datetime, --optl G/L tran date; normally null
 @inId_glsrcjrn varchar(10),
 @inId_create   integer,        
 @ret           integer output)
AS
declare....

and I have a FDStoredProc component using the stored procedure: (following is from component to code)

var
  spGLForAP: TFDStoredProc;

  spGLForAP := TFDStoredProc.Create(Self);

  spGLForAP.Name := 'spGLForAP';
  spGLForAP.Connection := dmConnect.cnxData;
  with spGLForAP.FormatOptions.MapRules.Add do begin 
    SourceDataType := dtDateTime;
    TargetDataType := dtDateTimeStamp;
  end;
  spGLForAP.StoredProcName := 'p_gl_for_ap';
  with spGLForAP.ParamData.Add do begin 
    Position := 1;
    Name := 'RESULT';
    DataType := ftInteger;
    ParamType := ptResult;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 2;
    Name := 'inMode';
    DataType := ftFixedChar;
    ParamType := ptInput;
    Size := 1;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 3;
    Name := 'inId_Invoice';
    DataType := ftInteger;
    ParamType := ptInput;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 4;
    Name := 'inReg';
    DataType := ftFixedChar;
    ParamType := ptInput;
    Size := 3;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 5;
    Name := 'inCheckNo';
    DataType := ftInteger;
    ParamType := ptInput;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 6;
    Name := 'inIs_Reversal';
    DataType := ftFixedChar;
    ParamType := ptInput;
    Size := 1;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 7;
    Name := 'inDt_Rev';
    DataType := ftDateTime;
    FDDataType := dtDateTimeStamp;
    NumericScale := 3;
    ParamType := ptInput;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 8;
    Name := 'inDt';
    DataType := ftDateTime;
    FDDataType := dtDateTimeStamp;
    NumericScale := 3;
    ParamType := ptInput;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 9;
    Name := 'inId_glsrcjrn';
    DataType := ftString;
    ParamType := ptInput;
    Size := 10;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 10;
    Name := 'inId_create';
    DataType := ftInteger;
    ParamType := ptInput;
  end;
  with spGLForAP.ParamData.Add do begin 
    Position := 11;
    Name := 'ret';
    DataType := ftInteger;
    ParamType := ptInputOutput;
  end;

I am initializing with this code:

function tdmAP.DoGLForAP(whichInvoice: integer; hasDelete: Boolean): 

integer;
begin
   spGLForAP.Params.ClearValues;
   spGLForAP.ParamByName('inMode').AsString := 'I';
   spGLForAP.ParamByName('inId_Invoice').AsInteger := whichInvoice;
   spGLForAP.ParamByName('inReg').AsString := '';
   spGLForAP.ParamByName('inCheckNo').AsInteger := 0;
   if hasDelete then
   begin
      spGLForAP.ParamByName('inIs_Reversal').AsString := 'Y';
      spGLForAP.ParamByName('indt_Rev').value := Date;
   end
   else
   begin
      spGLForAP.ParamByName('inIs_Reversal').AsString := 'N';
      spGLForAP.ParamByName('indt_Rev').AsDateTime := Date;
   end;

   spGLForAP.ParamByName('indt').AsDateTime := Date;
   spGLForAP.ParamByName('inId_glsrcjrn').AsString := '';
   spGLForAP.ParamByName('inId_create').AsInteger := LoginRec.LoginUserId;;

   try
      spGLForAP.Prepare;
      spGLForAP.Execute;
      Result := spGLForAP.ParamByName('ret').AsInteger;
   except
      on E:Exception do
      begin
         ShowMessage('Error executing stored procedure p_gl_for_ap: ' + e.Message);
         result := -1;
      end;
   end;


end;

but I keep getting error back from firedac complaining about the parameter type changing: error on execute I have tried using the datatype mapping. I have tried using this code: spGLForAP.ParamByName('indt_Rev').value = 0;

and spGLForAP.ParamByName('indt_Rev').AsDateTime := Date;

and spGLForAP.ParamByName('indt_Rev').AsDateTime := now;

I have also tried changing the datatypes on the two date parameters from ftTimeStamp to ftDateTime, repreparing the query after setting the parameters types, and just about anything else I can think of. obviously, I'm missing something...

using Delphi 10.2.2 Tokyo, against mssql server 2008R2.

note: in this particular case, I'm trying to set the inDt_rev and inDt to 0. but can't seem to successfully set them to any value.


Solution

  • Try to change this part of your code:

      with spGLForAP.ParamData.Add do begin 
        Position := 7;
        Name := 'inDt_Rev';
        DataType := ftDateTime;
        FDDataType := dtDateTimeStamp;
        NumericScale := 3;
        ParamType := ptInput;
      end;
      with spGLForAP.ParamData.Add do begin 
        Position := 8;
        Name := 'inDt';
        DataType := ftDateTime;
        FDDataType := dtDateTimeStamp;
        NumericScale := 3;
        ParamType := ptInput;
      end;
    

    to this one:

      with spGLForAP.Params.Add do begin
        Name := '@inDt_Rev';
        DataType := ftTimeStamp;
        ParamType := ptInput;
      end;
      with spGLForAP.Params.Add do begin
        Name := '@inDt';
        DataType := ftTimeStamp;
        ParamType := ptInput;
      end;
    

    and use Value property instead of .AsDateTime accessor like:

    spGLForAP.Params.ParamByName('@inDt').Value := Now;
    

    or use AsSQLTimeStamp accessor:

    // uses Data.SqlTimSt;
    spGLForAP.Params.ParamByName('@inDt').AsSQLTimeStamp := DateTimeToSQLTimeStamp(Now);
    

    because FireDAC maps such parameter as dtDateTimeStamp type (for which is the AsSQLTimeStamp accessor for).