Jan*_*gen 8 delphi oracle firedac delphi-10.2-tokyo
更改为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;
Run Code Online (Sandbox Code Playgroud)
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]
Run Code Online (Sandbox Code Playgroud)
连接到MSSQL或Oracle数据库时; 连接到FireBird时没有.
之后FetchParams
,DataFormsettings.params[1].datatype
永远是一个ftString
.
如果我更换
Params.ParamByName('TT_FORM').AString := UpperCase(AKey);
Run Code Online (Sandbox Code Playgroud)
同
Params.ParamByName('TT_FORM').Value := UpperCase(AKey);
Run Code Online (Sandbox Code Playgroud)
... 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'...
Run Code Online (Sandbox Code Playgroud)
我可以用例如
S := TEncoding.Unicode.GetString(FieldByName('TT_VIEWDATA').AsBytes);
Run Code Online (Sandbox Code Playgroud)
对于Oracle,但(当然)在使用其他两种不起作用的数据库类型时:
No mapping for the Unicode character exists in the target multi-byte code page
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?具体来说,我想让AsString检索/分配工作.
请注意,设置AsString属性会在FireDAC TFDParam.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
Run Code Online (Sandbox Code Playgroud)
表格创建如下:
火鸟:
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
);
Run Code Online (Sandbox Code Playgroud)
甲骨文:
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
);
Run Code Online (Sandbox Code Playgroud)
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
);
Run Code Online (Sandbox Code Playgroud)
我检查过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...
Run Code Online (Sandbox Code Playgroud)
笔记:
select * from NLS_database_PARAMETERS where parameter like '%CHARACTERSET%'
returns NLS_CHARACTERSET=WE8MSWIN1252
和NLS_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().AsANSIString
给出了相同的结果 FieldByName().AsString
附加信息:这是一个具有持久字段定义的遗留应用程序DataFormsettings
TClientDataset
.TT_VIEWDATA
被定义为TMemoField
:
DataFormsettingsTT_VIEWDATA: TMemoField;
Run Code Online (Sandbox Code Playgroud)
在一个小的testapp(直接连接到Oracle;而不是客户端 - 服务器)我让Delphi添加字段定义然后它说:
DataFormsettingsTT_VIEWDATA: TWideMemoField;
Run Code Online (Sandbox Code Playgroud)
如果我在主应用程序中使用它,Oracle工作正常,但后来我得到MSSQL的"垃圾".
我还尝试为Oracle连接设置映射规则,如(许多变体):
with AConnection.FormatOptions.MapRules.Add do
begin
SourceDataType := dtWideMemo;
TargetDataType := dtMemo;
end;
AConnection.FormatOptions.OwnMapRules := true;
Run Code Online (Sandbox Code Playgroud)
但这没有帮助.
这是它不起作用的原因:
在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;
Run Code Online (Sandbox Code Playgroud)
的确,可能是问题.
解决方案是添加转换dtWideHMemo
为的映射规则dtMemo
.
之后,读取和写入CLOB .AsString
工作正常.
在Embarcadero Quality Portal中报告为RSP-19600.
为了完整性:因为我的其他答案中提到的映射不再处于活动状态,您必须更改对参数的访问.Value
而不是.AsString.
归档时间: |
|
查看次数: |
593 次 |
最近记录: |