ITPub博客

首页 > 数据库 > MySQL > 两个看似奇怪的MySQL语句问题

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

原创 MySQL 作者:jeanron100 时间:2018-03-28 16:37:04 1 删除 编辑

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

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

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

TEST1 10.0.0.1 7382 TEST2 10.0.0.2 7388 TEST21 10.0.0.21 7389

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

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

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多行,这看起来就麻烦了。

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个字段

mysql> create table test(col1 int,col2 varchar(30),col3 varchar(30)); Query OK, 0 rows affected (0.11 sec)

插入3条数据

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,看看执行的结果到底是什么样的。

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,但是真正的数据没有正常变更。

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的部分是生效了。

mysql> select concat(rtrim('101022152a  '),'tttt'); +--------------------------------------+ | concat(rtrim('101022152a  '),'tttt') | +--------------------------------------+ | 101022152atttt | +--------------------------------------+ 1 row in set (0.00 sec)

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

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)

查看文件的内容

mysql> system cat a.sql 
select concat(trim('10.10.22.152 '),'10.10.22.152');

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

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

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这样的符号,是不可见的。

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

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

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23718752/viewspace-2152374/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
技术文章每天更新,阵地已转移到微信公众号端。 公众号:jianrong-notes

注册时间:2012-05-14

  • 博文量
    1498
  • 访问量
    14429518