В случае столбца набора результатов каждое правило определяет преобразование типа данных источника, возвращаемого драйвером, в целевой тип, предпочтительный для приложения. В случае параметра команды правило определяет преобразование целевого типа данных, заданного приложением, в тип данных источника, поддерживаемый драйвером. Все правила, кроме именных, работают в обоих случаях в двух направлениях.

перехода на FireDAC у меня возникают проблемы с получением этого кода для работы на MSSQL / Oracle:

with DataFormsettings do
begin
  Close;
  if Params.Count=0 then FetchParams;
  Params.ParamByName('TT_EMP_ID').Asinteger := AEmpID;
  Params.ParamByName('TT_FORM').AString := UpperCase(AKey);  
  Open;
  if (RecordCount>0) then
     S := FieldByName('TT_VIEWDATA').Asstring;     
end;   

AKey и S обе строки.

Оператор Open дает ошибку

[FireDAC][Phys][MSSQL]-338 Param type changed from [ftString] to [ftWidestring]
[FireDAC][Phys][Ora]-338 Param type changed from [ftString] to [ftWidestring]

при подключении к базе данных MSSQL или Oracle; не при подключении к FireBird.
ПослеFetchParams, DataFormsettings.params[1].datatype всегдаftString.

Если я заменю

Params.ParamByName('TT_FORM').AString := UpperCase(AKey);  

с участием

Params.ParamByName('TT_FORM').Value := UpperCase(AKey);

... в операторе Open нет ошибок. Я думал, что это решило это, хотя я действительно не понимал ошибку. В конце концов, это должны быть все типы Delphi String по умолчанию ...
Но теперь S-определение не работает для Oracle (не FireBird или MSSQL) в том смысле, что я вижу возвращение двухбайтовых символов. S содержит:

\'#0'S'#0'o'#0'f'#0't'#0'w'#0'a'#0'r'#0'e'#0'\'#0'T'#0'i'#0'm'#0'e'#0'T'#0'e'#0'l'#0'l'#0'...

Я могу справиться с этим, например,

S := TEncoding.Unicode.GetString(FieldByName('TT_VIEWDATA').AsBytes);  

для Oracle, но (конечно) при использовании двух других типов баз данных, которые не работают:

No mapping for the Unicode character exists in the target multi-byte code page

Что мне здесь не хватает? В частности, я хотел бы просто заставить извлечения / назначения AsString работать.
Обратите вниманиеУстановка свойства AsString устанавливает для свойства DataType значение ftWideString или ftString. замечание вДокументация FireDAC TFDParam.AsString, Кажется, что назначение значения параметра просто переключает тип с ftString на ftWideString (как указано в исходной ошибке).

DataFormSettings этоTClientDataSet в клиентском приложении, подключенном к серверному приложению, гдеTDataSetProvider а такжеTFDQuery проживают. Запрос

select
  TT_FORMSETTINGS_ID,
  TT_EMP_ID,
  TT_FORM,
  TT_VERSION,
  TT_VIEWDATA
from TT_FORMSETTINGS
where TT_EMP_ID=:TT_EMP_ID
and TT_FORM=:TT_FORM

Таблицы были созданы следующим образом:

FireBird:

CREATE TABLE TT_FORMSETTINGS
(
  TT_FORMSETTINGS_ID    INTEGER DEFAULT 0 NOT NULL,
  TT_EMP_ID     INTEGER,
  TT_FORM       VARCHAR(50),
  TT_VERSION        INTEGER,
  TT_VIEWDATA       BLOB SUB_TYPE TEXT SEGMENT SIZE 80,
  TT_TAG    INTEGER,
  TT_TAGTYPE    INTEGER,
  TT_TAGDATE    TIMESTAMP
);

Oracle:

CREATE TABLE TT_FORMSETTINGS
(
  TT_FORMSETTINGS_ID    NUMBER(10,0) DEFAULT 0 NOT NULL,
  TT_EMP_ID     NUMBER(10,0),
  TT_FORM       VARCHAR(50),
  TT_VERSION        NUMBER(10,0),
  TT_VIEWDATA       CLOB,
  TT_TAG    NUMBER(10,0),
  TT_TAGTYPE    NUMBER(10,0),
  TT_TAGDATE    DATE
);

MSSQL:

CREATE TABLE TT_FORMSETTINGS
(
  TT_FORMSETTINGS_ID    INTEGER  NOT NULL CONSTRAINT TT_C0_FORMSETTINGS DEFAULT 0,
  TT_EMP_ID     INTEGER NULL,
  TT_FORM       VARCHAR(50) NULL,
  TT_VERSION        INTEGER NULL,
  TT_VIEWDATA       TEXT NULL,
  TT_TAG    INTEGER NULL,
  TT_TAGTYPE    INTEGER NULL,
  TT_TAGDATE    DATETIME NULL
);

Я проверил этоTT_VIEWDATA содержит правильные данные во всех базах данных; это длинная строка, содержащая CRLF:

\Software\TimeTell\Demo8\Forms\TFormTileMenu'#$D#$A'Version,1,80502'#$D#$A'\Software\TimeTell\Demo8\Forms\TFormTileMenu\TileControlMenu'#$D#$A'\Software\TimeTell\Demo8\Forms\TFormTileMenu\TileControlMenu\FormTileMenu.TileControlMenu'#$D#$A'Version,4,2'#$D#$A'\Software\TimeTell\Demo8\Forms\TFormTileMenu\TileControlMenu\FormTileMenu.TileControlMenu...

Примечания:

В настоящее время тестирую на SQL Server 2008 и Oracle 10, но я ожидаю, что это не будет отличаться для других версий.FWIW,select * from NLS_database_PARAMETERS where parameter like '%CHARACTERSET%' возвращаетсяNLS_CHARACTERSET=WE8MSWIN1252 а такжеNLS_NCHAR_CHARACTERSET=AL16UTF16
запросSELECT dump(dbms_lob.substr(tt_viewdata,100,1), 1016), tt_viewdata FROM tt_formsettings подтверждает, что CLOB содержит байты ASCII для кодовой страницы Win1252:
Typ=1 Len=100 CharacterSet=WE8MSWIN1252: 5c,53,6f,66,74,77,61,72,65,5c,54,69,6d,65,54,65,6c,6c,5c,44,65,...FieldByName().AsANSIString дает те же результаты, что иFieldByName().AsString

Дополнительная информация: Это устаревшее приложение с постоянными определениями полей наDataFormsettings TClientDataset. TT_VIEWDATA определяется какTMemoField:

DataFormsettingsTT_VIEWDATA: TMemoField;

В небольшом testapp (напрямую связанном с Oracle; не клиент-сервер) я позволил Delphi добавить определения полей и затем сказал:

DataFormsettingsTT_VIEWDATA: TWideMemoField;

Если я использую это в основном приложении, Oracle работает нормально, но тогда я получаю «мусор» для MSSQL.

Я также экспериментировал с настройкой правил отображения для соединения Oracle, таких как (много вариантов):

with AConnection.FormatOptions.MapRules.Add do
begin
  SourceDataType := dtWideMemo;
  TargetDataType := dtMemo;
end;
AConnection.FormatOptions.OwnMapRules := true;

но это не помогло.

Ответы на вопрос(2)

Ваш ответ на вопрос