在 firedac 存储过程组件上使用 datetime 参数时出错
Error using datetime parameter on firedac stored procedure component
我有一个具有日期时间参数的 FDStored 过程:
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 返回的错误,抱怨参数类型发生变化:
error on execute
我试过使用数据类型映射。
我试过使用这段代码:
spGLForAP.ParamByName('indt_Rev').value = 0;
和
spGLForAP.ParamByName('indt_Rev').AsDateTime := 日期;
和
spGLForAP.ParamByName('indt_Rev').AsDateTime := 现在;
我还尝试将两个日期参数的数据类型从 ftTimeStamp 更改为 ftDateTime,在设置参数类型后重新准备查询,以及我能想到的任何其他方法。显然,我错过了一些东西...
使用 Delphi 10.2.2 Tokyo,针对 mssql server 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
类型(这是 AsSQLTimeStamp
访问器)。
您可以创建自定义数据类型映射规则:
http://docwiki.embarcadero.com/RADStudio/XE5/en/Data_Type_Mapping_(FireDAC)
并将 dtTimeStamp 映射到 dtDateTime。
// --------------------------- MAP RULES ------------------------- \
with dm6.fdDB.FormatOptions do begin
OwnMapRules := True;
with MapRules.Add do begin
SourceDataType := dtDateTimeStamp;
TargetDataType := dtDateTime;
end;
end;
我有一个具有日期时间参数的 FDStored 过程:
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 返回的错误,抱怨参数类型发生变化: error on execute 我试过使用数据类型映射。 我试过使用这段代码: spGLForAP.ParamByName('indt_Rev').value = 0;
和 spGLForAP.ParamByName('indt_Rev').AsDateTime := 日期;
和 spGLForAP.ParamByName('indt_Rev').AsDateTime := 现在;
我还尝试将两个日期参数的数据类型从 ftTimeStamp 更改为 ftDateTime,在设置参数类型后重新准备查询,以及我能想到的任何其他方法。显然,我错过了一些东西...
使用 Delphi 10.2.2 Tokyo,针对 mssql server 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
类型(这是 AsSQLTimeStamp
访问器)。
您可以创建自定义数据类型映射规则: http://docwiki.embarcadero.com/RADStudio/XE5/en/Data_Type_Mapping_(FireDAC)
并将 dtTimeStamp 映射到 dtDateTime。
// --------------------------- MAP RULES ------------------------- \
with dm6.fdDB.FormatOptions do begin
OwnMapRules := True;
with MapRules.Add do begin
SourceDataType := dtDateTimeStamp;
TargetDataType := dtDateTime;
end;
end;