【写在最前】SQLSTATE[HY000]这种形式的报错 不属于MySQL报错,是PDO报错(SQL状态错误)
【问题01】:SQLSTATE[HY000]: General error: 1023 program err:java.lang.NumberFormatException: For input string: \"2886861933\" (SQL: select * from `t_pandora_account_token` where `account_id` = '269708248855481922' and `status` = '1' and `app` = 'bim' and `via` = 'weApp')
原因分析:错误关键字 java.lang.NumberFormatException 这句话明确告诉了我们是数字格式异常,接着后面有 For input string: \"2886861933\" 提示,这就告诉我们当前想把 \"2886861933\"转换成数字类型时出错了,这样就很确切了。
明明数据库中就是int类型,但此时提示string\"2886861933\"转换成数字类型时出错,就是因为 使用PDO查询mysql数据库时,执行prepare,execute后,返回的字段数据全都变为字符型。对于PHP这种弱类型的语言,影响不大。在做API返回数据时,如果类型与数据库不一致,对于Java和Objective C这些强类型,影响就很大了(mycat就是Java开发的)。
【问题02】:SQLSTATE[HY000] [2054] Server sent charset unknown to the client. Please, report to the developers (SQL: select * from `t_pandora_coupon_budget` where `status` = '1' and `type` = '10')
解决方法:$pdo->query("SET NAMES utf8");
由于mycat是Java开发的(ERROR 1115 (HY000): Unknown charset 'utf8'),所以$pdo->query("SET NAMES utf-8");
或配置文件设置:set charset utf-8
BUG01、SQLSTATE[HY000]: General error: 1023 program err:java.lang.NumberFormatException: For input string: \"2886862063\" (SQL: select * from `t_pandora_account_token` where `account_id` = '262034539203022996' and `status` = '1' and `app` = 'bim' and `via` = 'weApp'
问题说明:开发通过代码执行会抛出此错误,通过命令行连接mycat不会报错。而且SQL语句依然存在隐士转换和select * 的查询。
问题分析:
1.查看表结构:
|
CREATE TABLE `t_pandora_account_token` ( `access_token` char(32) NOT NULL DEFAULT '' COMMENT '令牌', `account_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '账户id', `shop_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '店铺id', `client_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '客户端版本', `token_ip` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ip', `status` int(1) NOT NULL DEFAULT '1', `via` varchar(16) NOT NULL DEFAULT '' COMMENT '手机平台(iphone,android)', `cver` varchar(8) NOT NULL DEFAULT '' COMMENT 'APP?汾??', `token_expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '令牌过期时间', `last_refresh_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '最后互动刷新时间', `token_mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '令牌修改时间', `token_ctime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '令牌创建时间', `app` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`access_token`), UNIQUE KEY `idx_token` (`account_id`,`app`,`via`), KEY `shop_id` (`shop_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='账户令牌表';
细说表问题:1.主键为32位char类型的access_token值使得大大降低了性能 2.token_expire和token_ctime为timestamp数据类型,默认值和保存的形式却为‘0000-00-00 00:00:00’ 3.表中字段注释出现了乱码 |
2.查询相应的值信息
|
select * from t_pandora_account_token where account_id =262034539203022996 and status=1 and app='bim' and via='weApp \G; *************************** 1. row *************************** access_token: 0000011838b2218093245e74032727ba account_id: 262034539203022996 shop_id: 0 client_id: 7 token_ip: 2886862063 status: 1 via: wx cver: 3.0 token_expire: 2018-05-16 13:19:55 last_refresh_time: 0000-00-00 00:00:00 token_mtime: 2018-05-17 13:19:55 token_ctime: 2018-05-17 13:19:55 app: bim 1 row in set (0.01 sec) select inet_ntoa(2886862063); +-----------------------+ | inet_ntoa(2886862063) | +-----------------------+ | 172.18.4.239 | +-----------------------+ 亮点:把IP地址存成 UNSIGNED INT |
3.err:java.lang.NumberFormatException: For input string: "2886862063",数据类型转换异常
|
把String类型转换为Integer类型,会抛出同样的异常 或BigInteger b = new BigInteger(s); //String 转换为 BigInteger 原因&解决办法01:Integer存储长度为32位。即-2^31~2^31-1; 即-2,147,483,648~2,147,483,647(2886862063>2147483647),此时将Integer换成BigInteger类型或long长整型。(MySQL中带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295。) 因为暂时无法修改微信小程序或mycat源码,所以修改token_ip int(11) 为bigint(11),让其根据MySQL数据类型自动识别匹配BigInteger,问题解决。 ALTER TABLE t_pandora_account_token MODIFY COLUMN token_ip bigint(12) unsigned NOT NULL DEFAULT '0' COMMENT '来源ip'; 解决办法02:开发代码对"2886862063"不做类型转换,直接利用函数转换为字符串IP(172.18.4.239),如果不涉及到该字段值的读取,强烈建议不要用select*,查询自己所需即可。(拿这次为例,其实最后用到的就access_token,但是开发为了方便还是用了select *)
BUG02、HUE查询跑错:Server error occurred: year=1000 is before 1900; the datetime strftime() methods require year >= 1900报错原因: File "/home/hue/hue/apps/rdbms/src/rdbms/api.py", line 48, in default return obj.strftime('%Y-%m-%d %H:%M:%S %Z') ValueError: year=1000 is before 1900; the datetime strftime() methods require year >= 1900 问题分析:Python的strftime()是不支持转化1900前的日期,因为数据库中默认日期为1000-01-01 00:00:00 解决办法:通过str对象的format()方法根据需求格式化出想要的形式,而format()方法原生支持datetime对象的格式化。
特别注意:# su - hue 启动守护进程:$ /home/hue/hue/build/env/bin/supervisor &
|