DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: webb123
今日帖子: 3
在线用户: 4
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 13:21:22
标题:
请教一个FireDAC中文处理的问题 浏览:1691
加入我的收藏
楼主: 用FireDAC连MariaDB, FDConnection已经设置了CharacterSet=UTF8
用FDQuery查询一个自建的ACCOUNT表
SELECT NAME FROM ACCOUNT
能够返回有中文的记录,比如"中国"
但是用
SELECT NAME FROM ACCOUNT WHERE NAME='中国'
就返回空记录

我猜应该是编码方式的问题,但是又找不到问题点
请大神指教
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 13:24:38
1楼: 另外在表Account中插入含有中文记录的时候
用HeidiSQL连接数据库看到的实际结果,实在中文记录后面追加了莫名其妙的字符
比如插入"大神", HeidiSQL看到的是"大神 M"
但是用NAME="大神 M"查询返回的也是空记录了

用不含中文的字符插入\查询\删除都没有问题

凌乱了....
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 13:30:38
2楼: 这是用FDConnect自带的SQL Script Editor查询的结果

Running script [Main] ...
SELECT NAME FROM ACCOUNT
NAME          
----------
admin          
鲨鱼

2 rows selected.
[00:00:00.016].
Script [Main] finished without errors [00:00:00.016].

Running script [Main] ...
SELECT NAME FROM ACCOUNT WHERE NAME='ADMIN'
NAME          
----------
admin          

1 row selected.
[00:00:00.000].
Script [Main] finished without errors [00:00:00.000].

Running script [Main] ...
SELECT NAME FROM ACCOUNT WHERE NAME='鲨鱼'
no rows selected.
[00:00:00.000].
Script [Main] finished without errors [00:00:00.016].
----------------------------------------------
-
作者:
男 luckyso999 (luckyso) ★☆☆☆☆ -
盒子活跃会员
2022/1/5 16:09:13
3楼: 建立数据库的时候要选择是UTF8
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/5 16:09:13
3楼: 没用过这个数据库。

试试 SELECT NAME FROM ACCOUNT WHERE NAME=UTF8Encode('中国')
----------------------------------------------
-
作者:
男 dlfsystem (dlfsystem) ★☆☆☆☆ -
盒子活跃会员
2022/1/5 16:15:09
4楼: 数据库的字符集要用:utf8mb4
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 17:08:38
5楼: 跟踪了一下代码,应该是FDQuery.Open或者ExecSQL的时候,对Params的类型判断出了问题,比如
var vName:string:='中国';
FDQuery.Open('SELECT * FROM ACCOUNT WHERE NAME=:1',[vName])
因为没有显性的指定数据类型,系统给了一个缺省值空数组[]传递给了Params.DataType
改成
FDQuery.Open('SELECT * FROM ACCOUNT WHERE NAME=:1',[vName],[ftWideString])就可以了
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 17:10:02
6楼: @dlfsystem utf8mb4能解决这个问题的话就太好了, 我看了数据表的生成sql,用UTF8字符集生成数据表缺省用的是utf8mb3_general_ci

我试试看,多谢
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/5 17:38:20
7楼: 感觉像是Delphi把ftWideString给当成ftString传给Params.DataType了, 一旦有中文字符,存到数据里的字符串尾巴上总会多几个字节
----------------------------------------------
-
作者:
男 zhoutler (苦行僧) ★☆☆☆☆ -
普通会员
2022/1/5 21:24:04
8楼: 就是这样的。数据库UTF8编码的时候,凡是TParam的字符型,都要用AsWideString赋值。FireBird数据库也是如此。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/6 9:21:32
9楼: 你有没有设计期生成它的 Params ?如果有,可以看到数据类型的。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2022/1/6 17:46:49
10楼: 用firedac连接sqlserver、sybase没有楼主计的不能处理中文的问题
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/7 8:20:01
11楼: @pcplayer 代码里面几个form共享了一个datamodule的FDQuery,所有的SQL都是动态生成的, 调用
function TFDCustomQuery.ExecSQL(const ASQL: String; const AParams: array of Variant;const ATypes: array of TFieldType): LongInt;

procedure TFDRdbmsDataSet.Open(const ASQL: String; const AParams: array of Variant; const ATypes: array of TFieldType);
来操作数据库
问题在于当不显性设定ATypes的时候, FD对AParams里面的中文字符串推断出的类型似乎有问题,把ftWideString当成了ftString, 显性指定所有参数的类型就好了

在HeidiSQL里手工输入SQL验证了一下,对中文的处理正常,说明数据库的字符编码设置应该没问题
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/7 8:58:24
12楼: 楼上,你这种动态的玩法,试试不要 AsString 或者 AsWideString,而是直接 .Value := 'aaf';  或则 .Value := 24324; 让它内部自己转换看看。

因为是动态,你如果还要写 AsString 这样的语句,那如果那个玩意是个整数你怎么办?
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/1/7 9:30:45
13楼: 代码里没有用ParamByName('xxx').asXXXX的写法,
图省事用的类似于
FDQuery.Open('SELECT * FROM WORK_ORDER WHERE NAME=:1 LIMIT 1', [PWorkOrder.IDName], [ftWideString]);
如果IDName中没有中文字符, 不指定[ftWideString],
FDQuery.Open('SELECT * FROM WORK_ORDER WHERE NAME=:1 LIMIT 1', [PWorkOrder.IDName])
这样写也没问题, 说明FD在实现Open函数的时候已经对参数IDName的类型进行了内部判断,只是判断逻辑似乎忘记了ftWideString这档子事

另外FD支持这样的写法,会自动判单开放数组的数据类型
FDQuery.open('select * from xx where A=:1 AND B=:2 AND C=:3',['abb',123,-234.5678]);
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/1/7 10:20:23
14楼: 最好不要在 SQL 语句里面直接写值,采用参数的方式比较好。
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/1/8 10:44:11
15楼: hello mates,

dont forget that "Firedac" do your life more easy when using all its potencial!


for example:
--> create a rule for "change" your Fields Data-Type when some "Data-Type" dont exists or you needs change for another type.

var
  MyMapRule: TFDMapRule;
begin
  // Hierarchy:
  // 1) FDManager1.FormatOptions   --> always exists "one hide FDManager" when using any FD_component or class in your project
  // 2) FDConnection1.FormatOptions;
  // 3) Datasets FireDAC
  //
  FDManager.FormatOptions.OwnMapRules := True; // valid for all descendents of FDManager -> FDConnection --> FD__Querys_or_Tables --> Updates, StoreProc, etc...
  //
  MyMapRule := FDConnection1.FormatOptions.MapRules.Add;
  // here, how to name the "rule mask": this works like "LIKE" keyword on SQL expression:
  // --> %abcdef  ==>   all fields ended with "abcdef"
  // --> %abcdef%  ==>  all fields that contains "abcdef"
  // --> abcdef%  ==> all fields that start with "abcdef"
  // --> _a__b    ==> all fields that have: 5 chars on length and 2nd char = "a", and 5th char = "b"
  //
  MyMapRule.NameMask := 'FieldName_On_Table'; // same "fieldname" in your table.
  // MyMapRule.NameMask          := '%name%';
  // MyMapRule.NameMask          := '%na_e';
  //
  // The TypeMask property is useful for the databases that support domain based types, such as ODBC, InterBase, Firebird, PostgreSQL,SQLite.
  // MyMapRule.TypeMask       := 'domain type DOMAIN_NAME_IN_YOUR_TABLE'; // you can use as "NameMask" definitions above!!!
  //
  // now, the "SourceDataType" and "TargetDataType" will using the definition above for exchanging data-type of fields with rules above
  //
  MyMapRule.SourceDataType := dtAnsiString; // read all AnsiSTRINGs...
  MyMapRule.TargetDataType := dtWideString; // works like WideSTRINGs!
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/1/8 10:51:58
16楼: screenshot
此帖子包含附件:
PNG 图像
大小:18.8K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行66.40625毫秒 RSS