MySQL 过滤字段不加条件的执行结果
2012-10-10 16:32
253 查看
背景:
今天从库有延迟,进数据库看到他一直在执行这类更新语句:
对于这个sql语句,按照以往的经验,认为是:userid 非NULL的话就会被更新,要是NULL的话,就不更新。但是出现这个sql语句明显是有问题的,程序肯定出了问题。
但找程序员之前,我对这张表进行查看,从当中发现一个现象。结果证明以往的经验是错误的。
分析:
上面的可以看出:按照以往的经验,认为是:userid 非NULL的话就会被更新,要是NULL的话,就不更新。 这样的说法是错误的。
从上面得出的userid都有一个规律:数字开头。
验证:
外面套一层子查询并且过滤数字开头的,确实和单独执行的结果一样:2627。
那整张表数字开头的是否也是2627呢?
结果显示多了21条,怎么回事?那这21条是怎么样的规律。
结果显示确实都是0开头,把这些都转换成整数的话,刚好全部都是0。
那tb1,tb2的userid转换了之后是否都大于0呢?是否相等呢?
结果和猜想的一样,不等于0之后的都是相同的(True)。这样就清楚为什么有21条不一样的数据了(都是数字开头并且等于0的数据)。
结论:
类似 select * from tb where col 这类查询,只要col转换成不为0的[b]整型值的话 (!=),则都会被检索出来,包括负数。要是col里面没有数字,只有字母和汉字等字符串的话,则就检索不出结果来。和col是否为NULL 没有关系。[/b]
看到一个情况和我上面说的差不多:http://www.pnigos.com/?p=19
今天从库有延迟,进数据库看到他一直在执行这类更新语句:
UPDATE `A` SET `isD` = '1', `modTime` = '2012-10-10 10:45:56' WHERE (userid) /* userid是一个varchar的字符串 */
对于这个sql语句,按照以往的经验,认为是:userid 非NULL的话就会被更新,要是NULL的话,就不更新。但是出现这个sql语句明显是有问题的,程序肯定出了问题。
但找程序员之前,我对这张表进行查看,从当中发现一个现象。结果证明以往的经验是错误的。
分析:
zhoujinyi@localhost : test 02:35:34>select count(*) from A where userid; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.00 sec) zhoujinyi@localhost : test 03:36:01>select count(*) from A; +----------+ | count(*) | +----------+ | 86181 | +----------+ 1 row in set (0.00 sec) zhoujinyi@localhost : test 03:36:34>select count(*) from A where userid is null; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)
上面的可以看出:按照以往的经验,认为是:userid 非NULL的话就会被更新,要是NULL的话,就不更新。 这样的说法是错误的。
从上面得出的userid都有一个规律:数字开头。
zhoujinyi@localhost : test 03:36:41>select userid from A where userid limit 10; +-----------------+ | userid | +-----------------+ | 000726 | | 0008875 | | 0010040 | | 00110222 | | 00123456789 | | 001400 | | 0015238 | | 001577 | | 0019myfavourite | | 001catherine | +-----------------+ 10 rows in set (0.00 sec)
验证:
zhoujinyi@localhost : test 03:54:26>select count(*) from (select userid from A where userid) ab where ab.userid regexp '^[0-9]'; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.14 sec)
外面套一层子查询并且过滤数字开头的,确实和单独执行的结果一样:2627。
那整张表数字开头的是否也是2627呢?
zhoujinyi@localhost : test 03:54:42>select count(*) from A where userid regexp '^[0-9]'; +----------+ | count(*) | +----------+ | 2648 | +----------+ 1 row in set (0.19 sec)
结果显示多了21条,怎么回事?那这21条是怎么样的规律。
/* 把整张表所有的数字开头的userid去出来 */ zhoujinyi@localhost : test 03:57:49>create table tb2 select userid from A where userid regexp '^[0-9]'; /* 把原始sql得出的所有数字开头的userid取出来 */ zhoujinyi@localhost : test 03:59:36>create table tb1 select userid from (select userid from A where userid) ab where ab.userid regexp '^[0-9]';
zhoujinyi@localhost : test 04:03:04>select a.userid from tb2 a left join tb1 b on a.userid=b.userid where b.userid is null; +-------------------+ | userid | +-------------------+ | 000000he | | 0000liujie | | 000yanzi | | 00benson | | 00bxy | | 00lugenkuzhu | | 00wenjin | | 00的颠覆 | | 00逗 | | 0atta0 | | 0dishuizhiyuan | | 0min | | 0osissio0 | | 0v132 | | 0wanghuan0 | | 0云淡风轻0 | | 0吟风0 | | 0梧桐0 | | 0求知 | | 0白大褂在线0 | | 0超级野蛮0 | +-------------------+ 21 rows in set (1.17 sec)
结果显示确实都是0开头,把这些都转换成整数的话,刚好全部都是0。
zhoujinyi@localhost : test 04:04:48>select a.userid+0 from tb2 a left join tb1 b on a.userid=b.userid where b.userid is null; +------------+ | a.userid+0 | +------------+ | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | | 0 | +------------+ 21 rows in set (1.46 sec)
那tb1,tb2的userid转换了之后是否都大于0呢?是否相等呢?
zhoujinyi@localhost : test 04:08:02>select count(*) from tb1; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.00 sec) zhoujinyi@localhost : test 04:08:09>select count(*) from tb1 where userid+0 <>0; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.00 sec) zhoujinyi@localhost : test 04:08:11>select count(*) from tb2 where userid+0 <>0; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.00 sec)
结果和猜想的一样,不等于0之后的都是相同的(True)。这样就清楚为什么有21条不一样的数据了(都是数字开头并且等于0的数据)。
结论:
zhoujinyi@localhost : test 04:08:18>select count(*) from A where userid; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.00 sec) zhoujinyi@localhost : test 04:15:32>select count(*) from A where userid+0 != 0; +----------+ | count(*) | +----------+ | 2627 | +----------+ 1 row in set (0.01 sec)
类似 select * from tb where col 这类查询,只要col转换成不为0的[b]整型值的话 (!=),则都会被检索出来,包括负数。要是col里面没有数字,只有字母和汉字等字符串的话,则就检索不出结果来。和col是否为NULL 没有关系。[/b]
看到一个情况和我上面说的差不多:http://www.pnigos.com/?p=19
相关文章推荐
- MySql insert:当通过条件查询结果存在该条数据则不插入,否则执行insert
- mysql存储过程的参数名不能和表字段名一样,否则不执行条件
- MYSQL 查询不同条件,但是同一个字段的结果
- MySQL 查询优化(查询条件字段传值要和字段取值类型一致)
- 可遇不可求的Question之MySqlClient与ODBC访问字段返回不同结果篇
- MySQL循环遍历执行查询SQL语句结果的方法
- mysql中Where条件中字段顺序的重要性
- MYSQL条件查询--字段A不同值的state为0,1,9的数量统计
- MySQL中给自定义的字段查询结果添加排名的方法
- mysql 数据条件过滤查询练习
- mysql where过滤条件中and连接的两个条件的顺序不必和建立的联合索引的字段顺序一致
- django ORM model filter 条件过滤,及多表连接查询、反向查询,某字段的distinct
- Mysql 与聚合函数在一起时候where条件和having条件的过滤时机
- MySQL执行Select语句将结果导出到文件的方法
- MySQL INSERT插入多字段条件判断,如果不存在则插入
- MySQL执行Select语句将结果导出到文件的方法
- 将SQL查询分组后获得的结果中的某字段按照条件相加
- 解决mysql查询,in条件参数为带逗号的字符串,查询结果错误
- SQL一次性查询一个字段不同条件下的统计结果
- MySQL group by后的结果将每组某VARCHAR字段字符串连接起来