Oracle/MSSQL下的Parameter.AsString失败 - Oracle下的Parameter.Value 2字节字符

8

在切换到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字符串类型...
但是现在对于Oracle(而不是FireBird或MSSQL),S分配失败,因为我看到返回了2字节字符。 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

"What am I missing here? Specifically, I would like to just get the AsString retrievals/assignments to work."请问我错过了什么?具体来说,我想让AsString的检索/赋值起作用。 请注意FireDAC TFDParam.AsString documentation中的“设置AsString属性会将DataType属性设置为ftWideString或ftString”的说明。似乎参数值赋值只是将类型从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在所有数据库中都包含正确的数据;它是一个长字符串,包含回车换行符(CRLFs)。
\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=WE8MSWIN1252NLS_NCHAR_CHARACTERSET=AL16UTF16
    查询SELECT dump(dbms_lob.substr(tt_viewdata,100,1), 1016), tt_viewdata FROM tt_formsettings确认CLOB包含Win1252代码页的ASCII字节:
    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().AsANSIStringFieldByName().AsString给出相同结果

额外信息:这是一个遗留应用程序,其在 DataFormsettings TClientDataset 上具有持久字段定义。 TT_VIEWDATA 被定义为一个 TMemoField

DataFormsettingsTT_VIEWDATA: TMemoField;

在一个小的测试应用程序中(直接连接到Oracle;不是客户端-服务器),我让Delphi添加字段定义,然后它说:
DataFormsettingsTT_VIEWDATA: TWideMemoField;

如果我在主应用程序中使用它,Oracle可以正常工作,但是对于MSSQL,我会得到“垃圾”结果。
我还尝试设置Oracle连接的映射规则,例如(有很多变化):
with AConnection.FormatOptions.MapRules.Add do
begin
  SourceDataType := dtWideMemo;
  TargetDataType := dtMemo;
end;
AConnection.FormatOptions.OwnMapRules := true;

但那并没有帮助。

为什么要使用 FetchParams 方法来描述参数?这里发生了和 这里 相同的情况(请查看帖子中间部分)。我打赌,如果你删除 FetchParams 调用,就不会有任何麻烦了。FireDAC 会自动转换准备好的语句的参数值。但它不允许您准备描述参数、更改参数数据类型并执行该语句。 - Victoria
@Victoria ?? 如果我不执行FetchParams,那么就没有参数,而Params.ParamByName的赋值会立即失败。这是一个客户端/服务器应用程序,客户端使用TClientDataSet,服务器使用TFDQuery/TDataSetProvider。否则客户端怎么知道参数呢? - Jan Doggen
FireDAC解析查询并为查询中的标记创建参数对象(默认情况下)。我不知道你的设置。从你的问题中,我只是假设DataFormsettings是一个TFDQuery,并且你运行了你展示的命令。 - Victoria
抱歉,我更新了问题文本,以表明DataFormsettings是稍后提到的TClientDataSet。 - Jan Doggen
@nil 是的,我需要使用 varchar 字段 - 这不是在遗留应用程序中 MSSQL 最常见的字段类型吗? - Jan Doggen
显示剩余2条评论
2个回答

5

以下是它不能正常工作的原因:

FireDAC.Stan.Option中:

procedure TFDFormatOptions.ColumnDef2FieldDef()
...
dtWideHMemo:
  // Here was ftOraClob, but then will be created TMemoField,
  // which does not know anything about Unicode. So, I have
  // changed to ftFmtMemo. But probably may be problems ...
  ADestFieldType := ftWideMemo;

确实,可能会出现问题。

解决方法是添加映射规则,将 dtWideHMemo 转换为 dtMemo
之后,对 CLOB 进行读写操作,.AsString 就能正常工作。

在 Embarcadero Quality Portal 中报告为RSP-19600


为了完整起见:因为我其他答案中提到的映射已不再生效,您需要使用 .Value 而不是 .AsString 访问参数。


1
这不是一个最终解决方案,请参考代码块前的最后一条评论。它仍然感觉像是一个hack。我不会将其添加到问题中(作为“尝试”),因为最终这将起作用。
有两件事情正在进行,可以通过以下更改来解决:
1. Params值分配上的Param类型更改错误 2. 字段定义和FieldByName().AsString检索/分配不工作
请注意,我受制于整个应用程序的设计时字段定义,必须处理所有三种数据库类型,特别是DataFormSettingsTT_VIEWDATA持久字段是TMemoField。
对于问题底部提到的表定义,如果您设置了TFDConnection -> TFDQuery -> TDataSetProvider -> TClientDataSet,并使用Add all fields添加字段定义,则DataFormSettingsTT_VIEWDATA将是以下类型:
  • 对于FireBird,使用BlobType=ftMemoFieldTMemoField

  • 对于MSSQL,使用BlobType=ftWideMemoFieldTMemoField

  • 对于Oracle,使用BlobType=ftWideMemoFieldTWideMemoField

手动编辑.DFM和.PAS文件将Oracle中的TWideMemoField设置回TMemoField是可行的(好吧,我不必更改它,因为它是旧代码),如果我还:

  • 在运行时强制将设计时的TMemoFieldBlobType=ftWideMemoField设置(我可以在所有数据模块派生自的父级OnCreate中完成);

  • 仅针对Oracle处理字符串检索,使用TEncoding.Unicode.GetString(FieldByName(SFormSettingsViewData).AsBytes)

但这仍然不是最优的。我的客户端代码与TClientDataSet 现在必须知道它连接的数据库类型。我在客户端应用程序中有一种方法来查询服务器以获取该信息。
这里是一个带有这些更改的示例应用程序: < p > uFireDacOracleBlob.pas文件:

unit uFireDacOracleBlob;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
  FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.Oracle,
  FireDAC.Phys.OracleDef, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, Datasnap.DBClient, Datasnap.Provider,
  Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, Vcl.StdCtrls, Vcl.ExtCtrls,
  FireDAC.Phys.MSSQL, FireDAC.Phys.MSSQLDef, FireDAC.Phys.IB,
  FireDAC.Phys.IBDef, FireDAC.Phys.FBDef, FireDAC.Phys.IBBase, FireDAC.Phys.FB,
  FireDAC.Phys.ODBCBase;

type
  TFrmFireDacOracleBlob = class(TForm)
    FDConnection1: TFDConnection;
    FDPhysOracleDriverLink1: TFDPhysOracleDriverLink;
    FDQuery1: TFDQuery;
    DataSetProvider1: TDataSetProvider;
    ClientDataSet1: TClientDataSet;
    Edit0: TEdit;
    Label1: TLabel;
    LblPos0: TLabel;
    RGpDB: TRadioGroup;
    BtnOpen: TButton;
    FDConnection2: TFDConnection;
    FDQuery2: TFDQuery;
    DataSetProvider2: TDataSetProvider;
    ClientDataSet2: TClientDataSet;
    FDConnection0: TFDConnection;
    FDQuery0: TFDQuery;
    DataSetProvider0: TDataSetProvider;
    ClientDataSet0: TClientDataSet;
    FDPhysMSSQLDriverLink1: TFDPhysMSSQLDriverLink;
    FDPhysFBDriverLink1: TFDPhysFBDriverLink;
    ClientDataSet0TT_FORMSETTINGS_ID: TIntegerField;
    ClientDataSet0TT_EMP_ID: TIntegerField;
    ClientDataSet0TT_FORM: TStringField;
    ClientDataSet0TT_VERSION: TIntegerField;
    ClientDataSet0TT_VIEWDATA: TMemoField;

    ClientDataSet1TT_FORMSETTINGS_ID: TIntegerField;
    ClientDataSet1TT_EMP_ID: TIntegerField;
    ClientDataSet1TT_FORM: TStringField;
    ClientDataSet1TT_VERSION: TIntegerField;
    ClientDataSet1TT_VIEWDATA: TMemoField;

    ClientDataSet2TT_FORMSETTINGS_ID: TIntegerField;
    ClientDataSet2TT_EMP_ID: TIntegerField;
    ClientDataSet2TT_FORM: TStringField;
    ClientDataSet2TT_VERSION: TIntegerField;
    ClientDataSet2TT_VIEWDATA: TMemoField;
    BtnSet: TButton;
    Label2: TLabel;
    LblPos1: TLabel;
    Edit1: TEdit;
    Label4: TLabel;
    LblPos2: TLabel;
    Edit2: TEdit;
    BtnParam: TButton;
    procedure BtnOpenClick(Sender: TObject);
    procedure BtnSetClick(Sender: TObject);
    procedure BtnParamClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FStrFirebird,
    FStrOracle,
    FStrMSSQL   :String;
    procedure ShowString(AStr: String; ALbl: TLabel; AEdit: TEdit);
  public
  end;

var
  FrmFireDacOracleBlob: TFrmFireDacOracleBlob;

implementation

{$R *.dfm}

const
   cSQLText = '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';

procedure TFrmFireDacOracleBlob.BtnParamClick(Sender: TObject);
begin
  case RGpDB.ItemIndex of
     0: begin
           FDQuery0.SQL.Text := cSQLText;
           with ClientDataSet0 do
           begin
              if Params.Count=0 then FetchParams;
              Params.ParamByName('TT_EMP_ID').Asinteger := 1;
              Params.ParamByName('TT_FORM').AsString := 'TFORMTILEMENU';
              Open;
              if (RecordCount>0) then
                 FStrFirebird := FieldByName('TT_VIEWDATA').Asstring;
              ShowString(FStrFireBird,LblPos0,Edit0);
           end;
        end;
     1: begin
           FDQuery1.SQL.Text := cSQLText;
           with ClientDataSet1 do
           begin
              if Params.Count=0 then FetchParams;
              Params.ParamByName('TT_EMP_ID').Asinteger := 1;
              Params.ParamByName('TT_FORM').AsString := 'TFORMTILEMENU';
              Open;
              if (RecordCount>0) then
                 // FStrOracle := FieldByName('TT_VIEWDATA').Value;
                 FStrOracle := TEncoding.Unicode.GetString(FieldByName('tt_viewdata').AsBytes);
              ShowString(FStrOracle,LblPos1,Edit1);
           end;
        end;
     2: begin
           FDQuery2.SQL.Text := cSQLText;
           with ClientDataSet2 do
           begin
              if Params.Count=0 then FetchParams;
              Params.ParamByName('TT_EMP_ID').Asinteger := 1;
              Params.ParamByName('TT_FORM').AsString := 'TFORMTILEMENU';
              Open;
              if (RecordCount>0) then
                 FStrMSSQL := FieldByName('TT_VIEWDATA').Asstring;
              ShowString(FStrMSSQL,LblPos2,Edit2);
           end;
        end;
  end;
end;

procedure TFrmFireDacOracleBlob.BtnSetClick(Sender: TObject);
begin
  case RGpDB.ItemIndex of
     0: begin
           FStrFirebird := FStrFirebird + #13#10'Added another line';
           ClientDataSet0.Edit;
           ClientDataSet0.FieldByName('tt_viewdata').Value := FStrFireBird;
           ClientDataSet0.ApplyUpdates(0);
        end;
     1: begin
           FStrOracle := FStrOracle + #13#10'Added another line';
           ClientDataSet1.Edit;
           // ClientDataSet1.FieldByName('tt_viewdata').AsString := FStrOracle; // does not work
           // ClientDataSet1.FieldByName('tt_viewdata').Value := FStrOracle;    // does not work
           ClientDataSet1.FieldByName('tt_viewdata').Value := TEncoding.Unicode.GetBytes(FStrOracle);
           // ClientDataSet1.FieldByName('tt_viewdata').AsBytes := TEncoding.Unicode.GetBytes(FStrOracle);  Also works
           ClientDataSet1.ApplyUpdates(0);
        end;
     2: begin
           FStrMSSQL := FStrMSSQL + #13#10'Added another line';
           ClientDataSet2.Edit;
           ClientDataSet2.FieldByName('tt_viewdata').AsString := FStrFireBird;
           ClientDataSet2.ApplyUpdates(0);
        end;
  end;
end;

procedure TFrmFireDacOracleBlob.FormCreate(Sender: TObject);
var i: integer;
begin
   for i := 0 to self.ComponentCount-1 do
      if (self.Components[i] is TMemoField) then
         (self.Components[i] as TMemoField).BlobType := ftWideMemo;
end;

procedure TFrmFireDacOracleBlob.ShowString(AStr: String; ALbl: TLabel; AEdit: TEdit);
begin
  ALbl.Caption := IntToStr(Pos(#13#10,AStr));
  AEdit.Text := AStr;
end;

procedure TFrmFireDacOracleBlob.BtnOpenClick(Sender: TObject);
begin
  case RGpDB.ItemIndex of
     0: begin
           // SetFireBirdMapRules(FDConnection1);   Design time
           ClientDataSet0.Open;
           FStrFirebird := ClientDataSet0.FieldByName('tt_viewdata').AsString;
           ShowString(FStrFireBird,LblPos0,Edit0);
        end;
     1: begin
           // SetOracleMapRules(FDConnection1);   Design time
           ClientDataSet1.Open;
           // FStrOracle := ClientDataSet1.FieldByName('tt_viewdata').AsString;
           FStrOracle := TEncoding.Unicode.GetString(ClientDataSet1.FieldByName('tt_viewdata').AsBytes);
           ShowString(FStrOracle,LblPos1,Edit1);
        end;
     2: begin
           // SetMSSQLMapRules(FDConnection1);   Design time
           ClientDataSet2.Open;
           FStrMSSQL := ClientDataSet2.FieldByName('tt_viewdata').AsString;
           ShowString(FStrMSSQL,LblPos2,Edit2);
        end;
  end;
end;

end.

uFireDacOracleBlob.dfm 文件:

object FrmFireDacOracleBlob: TFrmFireDacOracleBlob
  Left = 0
  Top = 0
  Caption = 'FireDac and Oracle Clobs'
  ClientHeight = 278
  ClientWidth = 577
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 32
    Top = 161
    Width = 91
    Height = 13
    Caption = 'Position first CRLF:'
  end
  object LblPos0: TLabel
    Left = 128
    Top = 161
    Width = 6
    Height = 13
    Caption = '0'
  end
  object Label2: TLabel
    Left = 32
    Top = 203
    Width = 91
    Height = 13
    Caption = 'Position first CRLF:'
  end
  object LblPos1: TLabel
    Left = 128
    Top = 203
    Width = 6
    Height = 13
    Caption = '0'
  end
  object Label4: TLabel
    Left = 32
    Top = 245
    Width = 91
    Height = 13
    Caption = 'Position first CRLF:'
  end
  object LblPos2: TLabel
    Left = 128
    Top = 245
    Width = 6
    Height = 13
    Caption = '0'
  end
  object Edit0: TEdit
    Left = 32
    Top = 138
    Width = 505
    Height = 21
    TabOrder = 0
  end
  object RGpDB: TRadioGroup
    Left = 32
    Top = 8
    Width = 249
    Height = 33
    Columns = 3
    ItemIndex = 0
    Items.Strings = (
      'FireBird'
      'Oracle'
      'MSSQL')
    TabOrder = 1
  end
  object BtnOpen: TButton
    Left = 32
    Top = 56
    Width = 75
    Height = 25
    Caption = 'Open Table'
    TabOrder = 2
    OnClick = BtnOpenClick
  end
  object BtnSet: TButton
    Left = 120
    Top = 56
    Width = 75
    Height = 25
    Caption = 'Update field'
    TabOrder = 3
    OnClick = BtnSetClick
  end
  object Edit1: TEdit
    Left = 32
    Top = 180
    Width = 505
    Height = 21
    TabOrder = 4
  end
  object Edit2: TEdit
    Left = 32
    Top = 222
    Width = 505
    Height = 21
    TabOrder = 5
  end
  object BtnParam: TButton
    Left = 32
    Top = 96
    Width = 104
    Height = 25
    Caption = 'Open with params'
    TabOrder = 6
    OnClick = BtnParamClick
  end
  object FDConnection1: TFDConnection
    Params.Strings = (
      'User_Name=testv4'
      'Password=testv4'
      'Database=VS2003-2005-10'
      'DriverID=Ora')
    FormatOptions.AssignedValues = [fvMapRules]
    FormatOptions.OwnMapRules = True
    FormatOptions.MapRules = <
      item
        SourceDataType = dtBCD
        TargetDataType = dtInt32
      end
      item
        SourceDataType = dtFmtBCD
        TargetDataType = dtDouble
      end>
    Connected = True
    LoginPrompt = False
    Left = 312
    Top = 72
  end
  object FDPhysOracleDriverLink1: TFDPhysOracleDriverLink
    Left = 368
    Top = 72
  end
  object FDQuery1: TFDQuery
    Connection = FDConnection1
    SQL.Strings = (
      'select * from tt_formsettings')
    Left = 416
    Top = 72
  end
  object DataSetProvider1: TDataSetProvider
    DataSet = FDQuery1
    Left = 464
    Top = 72
  end
  object ClientDataSet1: TClientDataSet
    Aggregates = <>
    Params = <>
    ProviderName = 'DataSetProvider1'
    Left = 512
    Top = 72
    object ClientDataSet1TT_FORMSETTINGS_ID: TIntegerField
      FieldName = 'TT_FORMSETTINGS_ID'
      Required = True
    end
    object ClientDataSet1TT_EMP_ID: TIntegerField
      FieldName = 'TT_EMP_ID'
    end
    object ClientDataSet1TT_FORM: TStringField
      FieldName = 'TT_FORM'
      Size = 50
    end
    object ClientDataSet1TT_VERSION: TIntegerField
      FieldName = 'TT_VERSION'
    end
    object ClientDataSet1TT_VIEWDATA: TMemoField
      FieldName = 'TT_VIEWDATA'
      BlobType = ftWideMemo
    end
  end
  object FDConnection2: TFDConnection
    Params.Strings = (
      'Database=test'
      'Password=test'
      'User_Name=test'
      'Server=VS2003-2008'
      'DriverID=MSSQL')
    FormatOptions.AssignedValues = [fvMapRules]
    FormatOptions.OwnMapRules = True
    FormatOptions.MapRules = <
      item
        SourceDataType = dtDateTimeStamp
        TargetDataType = dtDateTime
      end>
    Connected = True
    LoginPrompt = False
    Left = 312
    Top = 144
  end
  object FDQuery2: TFDQuery
    Connection = FDConnection2
    SQL.Strings = (
      'select * from tt_formsettings')
    Left = 416
    Top = 144
  end
  object DataSetProvider2: TDataSetProvider
    DataSet = FDQuery2
    Left = 464
    Top = 144
  end
  object ClientDataSet2: TClientDataSet
    Aggregates = <>
    Params = <>
    ProviderName = 'DataSetProvider2'
    Left = 512
    Top = 144
    object ClientDataSet2TT_FORMSETTINGS_ID: TIntegerField
      FieldName = 'TT_FORMSETTINGS_ID'
      Required = True
    end
    object ClientDataSet2TT_EMP_ID: TIntegerField
      FieldName = 'TT_EMP_ID'
    end
    object ClientDataSet2TT_FORM: TStringField
      FieldName = 'TT_FORM'
      Size = 50
    end
    object ClientDataSet2TT_VERSION: TIntegerField
      FieldName = 'TT_VERSION'
    end
    object ClientDataSet2TT_VIEWDATA: TMemoField
      FieldName = 'TT_VIEWDATA'
      BlobType = ftMemo
    end
  end
  object FDConnection0: TFDConnection
    Params.Strings = (
      'Database=D:\Testing\Diverse\FireDacOracleBlob\TIMETELL_DEMO.GDB'
      'User_Name=SYSDBA'
      'Password=masterkey'
      'DriverID=IB')
    FormatOptions.AssignedValues = [fvMapRules]
    FormatOptions.OwnMapRules = True
    FormatOptions.MapRules = <
      item
        SourceDataType = dtDateTimeStamp
        TargetDataType = dtDateTime
      end
      item
        SourceDataType = dtSingle
        TargetDataType = dtDouble
      end>
    Connected = True
    LoginPrompt = False
    Left = 312
    Top = 8
  end
  object FDQuery0: TFDQuery
    Connection = FDConnection0
    SQL.Strings = (
      'select * from tt_formsettings')
    Left = 416
    Top = 8
  end
  object DataSetProvider0: TDataSetProvider
    DataSet = FDQuery0
    Left = 464
    Top = 8
  end
  object ClientDataSet0: TClientDataSet
    Aggregates = <>
    Params = <>
    ProviderName = 'DataSetProvider0'
    Left = 512
    Top = 8
    object ClientDataSet0TT_FORMSETTINGS_ID: TIntegerField
      FieldName = 'TT_FORMSETTINGS_ID'
      Required = True
    end
    object ClientDataSet0TT_EMP_ID: TIntegerField
      FieldName = 'TT_EMP_ID'
    end
    object ClientDataSet0TT_FORM: TStringField
      FieldName = 'TT_FORM'
      Size = 50
    end
    object ClientDataSet0TT_VERSION: TIntegerField
      FieldName = 'TT_VERSION'
    end
    object ClientDataSet0TT_VIEWDATA: TMemoField
      FieldName = 'TT_VIEWDATA'
      BlobType = ftMemo
    end
  end
  object FDPhysMSSQLDriverLink1: TFDPhysMSSQLDriverLink
    Left = 368
    Top = 144
  end
  object FDPhysFBDriverLink1: TFDPhysFBDriverLink
    Left = 368
    Top = 8
  end
end

注意:现在(也)支持参数赋值的事实在Data Type Mapping (FireDAC)文档中有说明:

对于结果集列,每个规则定义了将驱动程序返回的源数据类型转换为应用程序首选的目标数据类型。对于命令参数,规则定义了将应用程序指定的目标数据类型转换为驱动程序支持的源数据类型。除了基于名称的规则外,所有规则都可以双向工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接