当前位置:七道奇文章资讯数据防范MySQL防范
日期:2011-01-25 22:43:00  来源:本站整理

<b>MySQL的10件事—它们大概和你预想的不一样</b>[MySQL防范]

赞助商链接



  本文“<b>MySQL的10件事—它们大概和你预想的不一样</b>[MySQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
#10. 搜索一个“NULL”值 
  1. SELECT  *  
  2. FROM    a  
  3. WHERE   a.column = NULL 

SQL中,NULL什么也不等于,并且NULL也不等于NULL.这个查询不会返回任何后果的,实际上,当构建那个plan的时刻,优化器会把这样的语句优化掉.

当搜索NULL值的时刻,应当利用这样的查询:

  1. SELECT  *  
  2. FROM    a  
  3. WHERE   a.column IS NULL 

#9. 利用附加条件的LEFT JOIN

  1. SELECT  *  
  2. FROM    a  
  3. LEFT JOIN 
  4.         b  
  5. ON      b.a = a.id  
  6. WHERE   b.column = 'something' 

除了从a返回每个记录(至少一次),当没有真正匹配的记录的时刻,用NULL值替换缺失的字段之外,LEFT JOIN和INNER JOIN都是一样的.

但是,在LEFT JOIN之后才会查抄WHERE条件,所以,上面这个查询在衔接之后才会查抄column.就像我们方才理解到的那样,非NULL值才可以满意相等条件,所以,在a的记录中,那些在b中没有对应的条目的记录不可避免地要被过滤掉.

从本质上来说,这个查询是一个INNER JOIN,只是效率要低一些.

为了真正地匹配满意b.column = 'something'条件的记录(这时要返回a中的全部记录,也就是说,不过滤掉那些在b中没有对应的条目的记录),这个条件应当放在ON子句中:

  1. SELECT  *  
  2. FROM    a  
  3. LEFT JOIN 
  4.         b  
  5. ON      b.a = a.id  
  6.         AND b.column = 'something' 

#8. 小于一个值,但是不为NULL

我常常看到这样的查询:

  1. SELECT  *  
  2. FROM    b  
  3. WHERE   b.column < 'something' 
  4.        AND b.column IS NOT NULL 

实际上,这并非一个错误:这个查询是有效的,是成心这样做的.但是,这里的IS NOT NULL是冗余的.

假如b.column是NULL,那么无法满意b.column < 'something'这个条件,因为任何一个和NULL举行的对比城市被断定为布尔NULL,是不会通过过滤器的.

风趣的是,这个附加的NULL查抄不能和“大于”查询(比方:b.column > 'something')一同利用.

这是因为,在MySQL中,在ORDER BY的时刻,NULL会排在前面,因此,一些人错误地认为NULL比任何其他的值都要小.

这个查询可以被简化:

  1. SELECT  *  
  2. FROM    b  
  3. WHERE   b.column < 'something' 

在b.column中,不大概返回NULL

#7. 按照NULL来举行衔接

  1. SELECT  *  
  2. FROM    a  
  3. JOIN    b  
  4. ON      a.column = b.column 

在两个表中,当column是nullable的时刻,这个查询不会返回两个字段都是NULL的记录,缘由如上所述:两个NULL并不相等.

这个查询应当这样来写:

  1. SELECT  *  
  2. FROM    a  
  3. JOIN    b  
  4. ON      a.column = b.column 
  5.         OR (a.column IS NULL AND b.column IS NULL

MySQL的优化器会把这个查询当作一个“等值衔接”,然后供应一个特别的衔接条件:ref_or_null

#6. NOT IN和NULL值

  1. SELECT  a.*  
  2. FROM    a  
  3. WHERE   a.column NOT IN 
  4.         (  
  5.         SELECT column 
  6.         FROM    b  
  7.         ) 

假如在b.column中有一个NULL值,那么这个查询是不会返回任何后果的.和其他谓词一样,IN  和 NOT IN 碰到NULL也会被断定为NULL.

你应当利用NOT EXISTS重写这个查询:

  1. SELECT  a.*  
  2. FROM    a  
  3. WHERE   NOT EXISTS  
  4.         (  
  5.         SELECT NULL 
  6.         FROM    b  
  7.        WHERE   b.column = a.column 
  8.        ) 

不像IN,EXISTS老是被断定为true或false的.

#5. 对随机的样本举行排序

  1. SELECT  *  
  2. FROM    a  
  3. ORDER BY 
  4.         RAND(), column 
  5. LIMIT 10 

这个查询试图选出10个随机的记录,按照column来排序.

ORDER BY会按照自然次序来对输出后果举行排序:这就是说,当第一个表达式的值相等的时刻,这些记录才会按照第二个表达式来排序.

但是,RAND()的后果是随机的.要让RAND()的值相等是行不通的,所以,按照RAND()排序今后,再按照column来排序也是没有意义的.

要对随机的样本记录举行排序,可以利用这个查询:

  1. SELECT  *  
  2. FROM    (  
  3.         SELECT  *  
  4.         FROM    mytable  
  5.         ORDER BY 
  6.                 RAND()  
  7.         LIMIT 10  
  8.        ) q  
  9. ORDER BY 
  10.        column 

#4. 通过一个组来选取肆意的记录

这个查询打算通过某个组(定义为grouper来)来选出一些记录

  1. SELECT  DISTINCT(grouper), a.*  
  2. FROM    a 

DISTINCT不是一个函数,它是SELECT子句的一部份.它会利用到SELECT列表中的全部列,实际上,这里的括号是可以省略的.所以,这个查询大概会选出grouper中的值都相同的记录(假如在其他列中,至少有一个列的值是差别的).

有时,这个查询可以正常地利用( 这主要依靠于MySQL对GROUP BY的扩大):

  1. SELECT  a.*  
  2. FROM    a  
  3. GROUP BY 
  4.         grouper 

在某个组中返回的非聚合的列可以被肆意地利用.

首先,这仿佛是一个很好的办理筹划,但是,它存在着一个很严重的缺陷.它依靠于这样一个假定:固然可以通过组来肆意地获得,但是返回的全部值都要属于一条记录.

固然当前的实现仿佛就是这样的,但是它并没有文档化,无论什么时刻,它都有大概被改变(特别是,当MySQL学会了在GROUP BY的背面利用index_union的时刻).所以依靠于这个行为并不安全.

假如MySQL支持解析函数的话,这个查询可以很简单地用另一种更清楚的方法来重写.但是,假如这张表拥有一个PRIMARY KEY的话,即便不利用解析函数,也可以做到这一点:

  1. SELECT  a.*  
  2. FROM    (  
  3.         SELECT  DISTINCT grouper  
  4.         FROM    a  
  5.         ) ao  
  6. JOIN    a  
  7. ON      a.id =  
  8.         (  
  9.         SELECT  id  
  10.        FROM    a ai  
  11.         WHERE   ai.grouper = ao.grouper  
  12.         LIMIT 1  
  13.         ) 

#3. 通过一个组来选取第一条记录

把前面那个查询略微改变一下:

  1. SELECT  a.*  
  2. FROM    a  
  3. GROUP BY 
  4.         grouper  
  5. ORDER BY 
  6.         MIN(id) DESC 

和前面那个查询差别,这个查询试图选出id值最小的记录.

一样:无法保证通过a.*返回的非聚合的值都属于id值最小的那条记录(大概肆意一条记录)

这样做会更清楚一些:

  1. SELECT  a.*  
  2. FROM    (  
  3.         SELECT  DISTINCT grouper  
  4.        FROM    a  
  5.         ) ao  
  6. JOIN    a  
  7. ON      a.id =  
  8.         (  
  9.         SELECT  id  
  10.         FROM    a ai  
  11.         WHERE   ai.grouper = ao.grouper  
  12.         ORDER BY 
  13.                 ai.grouper, ai.id  
  14.         LIMIT 1  
  15.         ) 

这个查询和前面那个查询近似,但是利用额外的ORDER BY可以确保按id来排序的第一条记录会被返回.

#2. IN和‘,’——值的脱离列表

这个查询试图让column的值匹配用‘,’脱离的字符串中的肆意一个值:

  1. SELECT  *  
  2. FROM    a  
  3. WHERE   column IN ('1, 2, 3'

这不会正常施展作用的,因为在IN列表中,那个字符串并不会被展开.

假如列column是一个VARCHAR,那么它(作为一个字符串)会和整个列表(也作为一个字符串)举行对比,当然,这不大概匹配.假如 column是某个数值范例,那么这个列表会被强迫转换为那种数值范例(在最好的情形下,只有第一项会匹配)

处理这个查询的精确办法应当是利用符合的IN列表来重写它:

  1. SELECT  *  
  2. FROM    a  
  3. WHERE   column IN (1, 2, 3) 

大概,也可以利用内联:

  1. SELECT  *  
  2. FROM    (  
  3.         SELECT  1 AS id  
  4.         UNION ALL 
  5.         SELECT  2 AS id  
  6.         UNION ALL 
  7.         SELECT  3 AS id  
  8.         ) q  
  9. JOIN    a  
  10. ON      a.column = q.id 

但是,有时这是不大概的.

假如不想改变那个查询的参数,可以利用FIND_IN_SET:

  1. SELECT  *  
  2. FROM    a  
  3. WHERE   FIND_IN_SET(column'1,2,3'

但是,这个函数不可以操纵索引从表中检索行,会在a上履行全表扫描.

#1. LEFT JOIN和COUNT(*)

  1. SELECT  a.id, COUNT(*)  
  2. FROM    a  
  3. LEFT JOIN 
  4.         b  
  5. ON      b.a = a.id  
  6. GROUP BY 
  7.         a.id 

这个查询试图统计出关于a中的每条记录来说,在b中匹配的记录的数目.

问题是,在这样一个查询中,COUNT(*)永久不会返回一个0.关于a中某条记录来说,假如没有匹配的记录,那么那条记录还是会被返回和计数.

只有需求统计b中的记录数目的时刻才应当利用COUNT.既然可以利用COUNT(*),那么我们也可以利用一个参数来调用它(忽视掉NULL),我们可以把b.a传送给它.在这个例子中,作为一个衔接主键,它不可认为空,但是假如不想匹配,它也可认为空.

原文标题:10 things in MySQL (that won’t work as expected)   以上是“<b>MySQL的10件事—它们大概和你预想的不一样</b>[MySQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • <b>hosts是什么 hosts文件在什么位置 若何改正hosts</b>
  • <b>在 Windows 8 中手动安装语言包</b>
  • <b>五个常见 PHP数据库问题</b>
  • Windows中Alt键的12个高效快速的利用本领介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • <b>详解MySQL存储历程参数有三种范例(in、out、inout)</b>
  • <b>Win8系统恢复出来经典的开始菜单的办法</b>
  • <b>Win8系统花屏怎么办 Win8系统花屏的办理办法</b>
  • <b>Windows 7系统下无线网卡安装</b>
  • <b>为什么 Linux不需求碎片整理</b>
  • <b>Windows 8中删除账户的几种办法(图)</b>
  • <b>教你如安在win7下配置路由器</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .