前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >两个看似奇怪的MySQL语句问题

两个看似奇怪的MySQL语句问题

作者头像
jeanron100
发布2018-03-22 15:21:12
1.1K0
发布2018-03-22 15:21:12
举报
文章被收录于专栏:杨建荣的学习笔记

今天同事给了我一个文件需要更新下CMDB的数据,提供的内容是excel的形式,因为条目比较多,我需要做一些转换,批量修改成对应的SQL语句,因为只有我知道这个逻辑,所以这个转换工作由我来做。

本来看起来很简单的一个问题,结果因为不经意的操作出了两个问题,会牵扯出来两条有趣的SQL问题。

首先excel数据类似下面的形式:

代码语言:javascript
复制
TEST1 10.0.0.1  7382
TEST2 10.0.0.2  7388
TEST21 10.0.0.21  7389

所以我需要把内容做一个简单的转换,比如使用awk或者使用文本编辑器来做都可以。

我需要把数据转换成SQL语句,类似下面的形式:

代码语言:javascript
复制
update cmdb_server set server_app_code = trim('TEST1      ') where server_ip_addr=trim('10.0.0.1 ') and server_db_port=7382; 

这样就可以批量生成大量的update语句,更新即可。

我从开始就犯了一个低级错误。

我把语句给转换成了这样,很快就编辑好了,但是执行语句之后发现没有生效,真是奇怪,自己抽出一条语句来单独执行看看,发现结果竟然有这样的提示,影响到的行数有500多行,这看起来就麻烦了。

代码语言:javascript
复制
update cmdb_server set server_app_code = trim('TEST1      ') and server_ip_addr=trim('10.0.0.1 ') and server_db_port=7382;
Query OK, 0 rows affected (0.01 sec)
Rows matched: 537  Changed: 0  Warnings: 0

原来,是update语句竟然where字句部分让我写成了and,这种语句竟然能够成功执行,我想看看这类语句到底是个什么逻辑。

创建一个表test,有3个字段

代码语言:javascript
复制
mysql> create table test(col1 int,col2 varchar(30),col3 varchar(30));
Query OK, 0 rows affected (0.11 sec)

插入3条数据

代码语言:javascript
复制
mysql> mysql> insert into test values (1,'aa','aaa');
Query OK, 1 row affected (0.07 sec)
mysql> insert into test values (2,'bb','aaab');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values (3,'cc','aaac');
Query OK, 1 row affected (0.00 sec)

然后使用这种奇怪的update,看看执行的结果到底是什么样的。

代码语言:javascript
复制
mysql> update test set col1=4 and col2='cc' and col3='aaac';
Query OK, 3 rows affected (0.07 sec)
Rows matched: 3  Changed: 3  Warnings: 0

查看结果,发现会把原来的col1列给刷新,标记为0和1,如果映射到了就是1,否则就是0,但是真正的数据没有正常变更。

代码语言:javascript
复制
mysql> select *from test;
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
|    0 | aa   | aaa  |
|    0 | bb   | aaab |
|    1 | cc   | aaac |
+------+------+------+
3 rows in set (0.00 sec)

所以这个问题牵扯出来一个还蛮意思的问题。

修改语句之后,数据还是没有变更过来,这个时候碰到了一个诡异的问题,

上面的update语句手工拷贝过来能够正常执行,但是在文本里就不可以。反反复复试了多次,还可以复现,让我都有些怀疑人品了。

情况大概是这样,通过缩小范围,能够定位出来是在trim的部分。

手工执行,可以看到trim的部分是生效了。

代码语言:javascript
复制
mysql> select concat(rtrim('101022152a  '),'tttt');
+--------------------------------------+
| concat(rtrim('101022152a  '),'tttt') |
+--------------------------------------+
| 101022152atttt                       |
+--------------------------------------+
1 row in set (0.00 sec)

而如果编辑这个文件,执行的时候trim的部分却没有生效。

代码语言:javascript
复制
mysql> source a.sql

+----------------------------------------------+
| concat(trim('10.10.22.152 '),'10.10.22.152') |
+----------------------------------------------+
| 10.10.22.152 10.10.22.152                    |
+----------------------------------------------+
1 row in set (0.00 sec)

查看文件的内容

代码语言:javascript
复制
mysql> system cat a.sql 
select concat(trim('10.10.22.152 '),'10.10.22.152');

而这个问题我犹豫了一会,突然想明白了,我换个思路来解答。

我把文本中的那段内容简单修改了下,保持空格的部分不变,然后使用hex来解析。

代码语言:javascript
复制
mysql> system cat a.sql 
select hex(concat(trim('2 '),'1'));
+-----------------------------+
| hex(concat(trim('2 '),'1')) |
+-----------------------------+
| 320931                      |
+-----------------------------+
1 row in set (0.00 sec)

这个时候就明白了,32是2的ascii码值,同理,1对应的是31,而09对应的是制表符,也就是\t这样的符号,是不可见的。

明白了原因,来回溯过程,会发现我使用文本编辑器的时候还是可能生成这个制表符的,不能直接把锅扣给工具,还是自己触发的,当然这个过程中因为字符不可见,所以也就没有重视。

同事也给我提供了一个蛮有意思的类似问题,大家一睹为快,这类问题简直会让你怀疑人生。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档