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

前端之家收集整理的这篇文章主要介绍了在Oracle / MSSQL下的Parameter.AsString失败 – 在Oracle下的Parameter.Value 2字节字符前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
更改为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类型……
但是现在,对于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

我在这里想念的是什么?具体来说,我想让AsString检索/分配工作.
请注意,设置AsString属性会将数据类型属性设置为FireDAC TFDParam.AsString documentation中的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

表格创建如下:

火鸟:

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
);

甲骨文:

CREATE TABLE TT_FORMSETTINGS
(
  TT_FORMSETTINGS_ID    NUMBER(10,0) DEFAULT 0 NOT NULL,TT_EMP_ID     NUMBER(10,0),TT_VERSION        NUMBER(10,TT_VIEWDATA       CLOB,TT_TAG    NUMBER(10,TT_TAGTYPE    NUMBER(10,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,从NLS_database_PARAMETERS中选择*,其中’%CHARACTERSET%’等参数返回NLS_CHARACTERSET = WE8MSWIN1252和NLS_NCHAR_CHARACTERSET = AL16UTF16
查询SELECT转储(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,6c,6C,5C,44,…
> 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;

但这没有帮助.

这是它不起作用的原因:

在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更改对参数的访问.

猜你在找的Oracle相关文章