gpt4 book ai didi

oracle - Parameter.As String 在 Oracle/SQL 下失败 - Parameter.Value 2 字节字符在 Oracle 下

转载 作者:行者123 更新时间:2023-12-03 14:48:16 25 4
gpt4 key购买 nike

更改为 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 检索/分配工作。
请注意 FireDAC TFDParam.AsString documentation 中的设置 AsString 属性将 DataType 属性设置为 ftWideString 或 ftString 注释。似乎参数值分配只是将类型从 ftString 切换到 ftWideString(如原始错误所示)。

DataFormSettings 是客户端应用程序中的 TClientDataSet,连接到 TDataSetProviderTFDQuery 所在的服务器应用程序。查询是

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

甲骨文:

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,从 NLS_database_PARAMETERS 中选择 *,其中“%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 字符集=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;

在一个小型测试应用程序(直接连接到 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 工作正常。

报告为RSP-19600在 Embarcadero 质量门户中。

<小时/>

为了完整起见:由于我的其他答案中提到的映射不再有效,因此您必须使用 .Value 而不是 .AsString 更改对参数的访问权限。

关于oracle - Parameter.As String 在 Oracle/SQL 下失败 - Parameter.Value 2 字节字符在 Oracle 下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47673049/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com