Delphi 在firedac存储过程组件上使用datetime参数时出错

Delphi 在firedac存储过程组件上使用datetime参数时出错,delphi,firedac,Delphi,Firedac,我有一个具有datetime参数的存储过程: 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 @inC

我有一个具有datetime参数的存储过程:

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....
我有一个使用存储过程的FDStoredProc组件: 以下是从组件到代码

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;
我正在使用以下代码初始化:

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;
但我不断从firedac收到错误反馈,抱怨参数类型更改: 我尝试过使用数据类型映射。 我已尝试使用此代码: spGLForAP.ParamByName'indt_Rev'。值=0

及 spGLForAP.parabyname'indt_Rev'。AsDateTime:=日期

及 spGLForAP.parabyname'indt_Rev'.AsDateTime:=now

我还尝试将两个日期参数上的数据类型从ftTimeStamp更改为ftDateTime,在设置参数类型后重新准备查询,以及我能想到的任何其他内容。显然,我错过了一些东西

使用Delphi10.2.2,针对mssql服务器2008R2


注意:在这种特殊情况下,我试图将inDt_rev和inDt设置为0。但似乎无法成功地将它们设置为任何值。

尝试更改代码的这一部分:

  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.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;
并使用Value属性而不是.AsDateTime访问器,如:

spGLForAP.Params.ParamByName('@inDt').Value := Now;
或使用AsSQLTimeStamp访问器:

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

因为FireDAC映射诸如dtDateTimeStamp type之类的参数,而dtDateTimeStamp type是的AsSQLTimeStamp访问器。

您可以创建自定义数据类型映射规则:

并将dtTimeStamp映射到dtDateTime

  // --------------------------- MAP RULES ------------------------- \\
  with dm6.fdDB.FormatOptions do begin
    OwnMapRules := True;
    with MapRules.Add do begin
      SourceDataType := dtDateTimeStamp;
      TargetDataType := dtDateTime;
    end;
  end;

为什么在这里使用dtDateTimeStamp,而列的数据类型是DateTime而不是TimeStamp?您只是在参数名称中遗漏了@前缀,并混合了映射规则的方向。对于参数,它类似于TargetDataType映射到SourceDataType。但我会失去手动参数准备,不会干扰内部使用的FDDataType、无精度设置等,让FireDAC从元数据准备参数集合,只保留该映射。根据建议1,将其恢复为默认参数类型,并使用spGLForAP.ParamByName'indt_Rev'进行设置。值:=0;和spGLForAP.ParamByName'indt'。值:=0;按照建议1,将其还原为默认参数类型,并使用spGLForAP.ParamByName“indt_Rev”进行设置。值:=0;和spGLForAP.ParamByName'indt'。值:=0;我在执行时得到了一个“无效的变量类型转换”。第二种方法是使用dateTimeToSQLTimeStamp。非常感谢。