Рассмотрим эту таблицу в базе данных MSSQL:
CREATE TABLE dbo.TESTPAR
(
ID INTEGER NOT NULL,
YR VARCHAR(50) NULL
)
У меня есть TFDQuery
с текстом команды:
insert into TESTPAR
(ID,YR)
values(:ID,cast(:YR as varchar(4)))
Это имеет два ftInteger ptInput
параметра
Выполнение с помощью
procedure TFrmCastAsVarchar.BtnTestInsertClick(Sender: TObject);
begin
Inc(FLastID);
FDQuery2.Params[0].AsInteger := FLastID;
FDQuery2.Params[1].AsInteger := 2018;
try
FDQuery2.ExecSQL;
except
on E:Exception do ShowMessage(E.Message);
end;
end;
выдает ошибку EMSSQLNativeException Arithmetic overflow converting numeric to data type varchar
, когда Mapping для полей dtBCD и dtFmtBCD активен:
procedure TDM.SetBCDMapRules;
// For (Fmt)BCD data types. Called from SetOracleMapRules/SetMSSQLMapRules
begin
with FDConnection.FormatOptions.MapRules.Add do
begin // Convert numeric data types with scale=0 and precision<=10 to a 32-bit integer
PrecMax := 10;
PrecMin := 0;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtBCD;
TargetDataType := dtInt32;
end;
with FDConnection.FormatOptions.MapRules.Add do
begin // Do the same for those that might return as dtFmtBCD instead of dtBCD
PrecMax := 10;
PrecMin := 0;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtFmtBCD;
TargetDataType := dtInt32;
end;
with FDConnection.FormatOptions.MapRules.Add do
begin // Convert numeric data types with scale=0 and precision>10 to a 64-bit integer
PrecMin := 11;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtBCD;
TargetDataType := dtInt64;
end;
with FDConnection.FormatOptions.MapRules.Add do
begin // Idem dtFmtBCD
PrecMin := 11;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtFmtBCD;
TargetDataType := dtInt64;
end;
with FDConnection.FormatOptions.MapRules.Add do
begin // All other dtBCD types (notably scale <> 0) should return as float
SourceDataType := dtBCD;
TargetDataType := dtDouble;
end;
with FDConnection.FormatOptions.MapRules.Add do
begin // Idem dtFmtBCD
SourceDataType := dtFmtBCD;
TargetDataType := dtDouble;
end;
end;
(Как) я могу изменить SQL, чтобы это исправить?
Кроме того, есть ли в моих правилах отображения что-то странное, что можно исправить? Я удивлен, что это вообще влияет.
- Это, конечно, только основной пример. Реальный сценарий объединяет другие строки в cast (), чтобы получить значение varchar для помещения в поле varchar.
- Не с использованием отображений BCD создаст другие проблемы (например, с типами полей DECIMAL).
- Изменение структуры таблицы для клиента "не оптимально"; -)
- Я проверил это, используя множество различных ODBC / родных драйверов.
- Это Delphi Tokyo 10.2.3, приложение Win32 для Win7.