6、认为 NOT (A IN (X, Y)) 和 IN (X, Y) 的布尔值相反
  对于NULLs,这是一个举足轻重的细节!让我们看看 A IN (X, Y) 真正意思吧:
  A IN (X, Y)
  is the same as    A = ANY (X, Y)
  is the same as    A = X OR A = Y
  When at the same time, NOT (A IN (X, Y)) really means:
  同样的,NOT (A IN (X, Y))的真正意思:
  NOT (A IN (X, Y))
  is the same as    A NOT IN (X, Y)
  is the same as    A != ANY (X, Y)
  is the same as    A != X AND A != Y
  看起来和之前说的布尔值相反一样?其实不是。如果X或Y中任何一个为NULL,NOT IN 条件产生的结果将是UNKNOWN,但是IN条件可能依然会返回一个布尔值。
  或者换种说话,当 A IN (X, Y) 结果为TRUE或FALSE时,NOT(A IN (X, Y)) 结果为依然UNKNOWN而不是FALSE或TRUE。注意了,如果IN条件的右边是一个子查询,结果依旧。
  不信?你自己看SQL Fiddle 去。它说了如下查询给不出结果:
  SELECT 1
  WHERE    1 IN (NULL)
  UNION ALL
  SELECT 2
  WHERE NOT(1 IN (NULL))
  更多细节可以参考我的上一篇博客,上面写了在同区域内不兼容的一些SQL方言。
  解决方案:
  当涉及到可为NULL的列时,注意NOT IN条件。
  7、认为NOT (A IS NULL)和A IS NOT NULL是一样的
  没错,我们记得处理NULL值的时候,SQL实现了三值逻辑。这是我们能用NULL条件来检测NULL值的原因。对么?没错。
  但在NULL条件容易遗漏的情况下。要意识到下面这两个条件仅仅在行值表达式(row value expressions)为1的时候才相等:
  NOT (A IS NULL)
  is not the same as A IS NOT NULL
  如果A是一个大于1的行值表达式(row value expressions),正确的表将按照如下方式转换:
  如果A的所有值为NUll,A IS NULL为TRUE
  如果A的所有值为NUll,NOT(A IS NULL) 为FALSE
  如果A的所有值都不是NUll,A IS NOT NULL 为TRUE
  如果A的所有值都不是NUll,NOT(A IS NOT NULL)  为FALSE
  在我的上一篇博客可以了解到更多细节。
  解决方案:
  当使用行值表达式(row value expressions)时,要注意NULL条件不一定能达到预期的效果。
  8、不用行值表达式
  行值表达式是SQL一个很棒的特性。SQL是一个以表格为中心的语言,表格又是以行为中心。通过创建能在同等级或行类型进行比较的点对点行模型,行值表达式让你能更容易的描述复杂的判定条件。一个简单的例子是,同时请求客户的姓名
  SELECT c.address
  FROM  customer c,
  WHERE (c.first_name, c.last_name) = (?, ?)
  可以看出,将每行的谓词左边和与之对应的右边比较这个语法而言,行值表达式的语法更加简洁。特别是在有许多独立条件通过AND连接的时候特别有效。行值表达式允许你将相互联系的条件放在一起。对于有外键的JOIN表达式来说,它更有用:
  SELECT c.first_name, c.last_name, a.street
  FROM  customer c
  JOIN  address a
  ON  (c.id, c.tenant_id) = (a.id, a.tenant_id)
  不幸的是,并不是所有数据库都支持行值表达式。但SQL标准已经在1992对行值表达式进行了定义,如果你使用他们,像Oracle或Postgres这些的复杂数据库可以使用它们计算出更好的执行计划。在Use The Index, Luke这个页面上有解析。
  解决方案:
  不管干什么都可以使用行值表达式。它们会让你的SQL语句更加简洁高效。
  9、不定义足够的限制条件(constraints)
  我又要再次引用Tom Kyte 和 Use The Index, Luke 了。对你的元数据使用限制条件不能更赞了。首先,限制条件可以帮你防止数据质变,光这一点很有用。但对我来说更重要的是,限制条件可以帮助数据库进行SQL语句转换,数据库可以决定。
  哪些值是等价的
  哪些子句是冗余的
  哪些子句是无效的(例如,会返回空值的语句)
  有些开发者可能认为限制条件会导致(数据库)变慢。但相反,除非你插入大量的数据,对于大型操作是你可以禁用限制条件,或用一个无限制条件的临时“载入表”,线下再把数据转移到真实的表中。
  解决方案:
  尽可能定义足够多的限制条件(constraints)。它们将帮你更好的执行数据库请求。
  10、认为50ms是一个快的查询速度
  NoSQL的炒作依然在继续,许多公司认为它们像Twitter或Facebook一样需要更快、扩展性更好的解决方案,想脱离ACID和关系模型横向扩展。有些可能会成功(比如Twitter或Facebook),而其他的也许会走入误区
  对于那些仍被迫(或坚持)使用关系型数据 库的公司,请不要自欺欺人的认为:“现在的关系型数据库很慢,其实它们是被天花乱坠的宣传弄快的”。实际上,它们真的很快,解析20Kb查询文档,计算 2000行执行计划,如此庞大的执行,所需时间小于1ms,如果你和数据管理员(DBA)继续优化调整数据库,能得到大限度的运行。
  它们会变慢的原因有两种:一是你的应用滥用流行的ORM;二是ORM无法针对你复杂的查询逻辑产生快的SQL语句。遇到这种情况,你要考虑选择像 JDBC、jOOQ 或MyBatis这样的更贴近SQL核心,能更好的控制你的SQL语句的API。
  因此,不要认为查询速度50ms是很快或者可以接受的。完全不是!如果你程序运行时间是这样的,请检查你的执行计划。这种潜在危险可能会在你执行更复杂的上下文或数据中爆发。
  总结
  SQL很有趣,同时在各种各样的方面也很微妙。正如我的关于10个错误的博客所展示的。跋山涉水也要掌握SQL是一件值得做的事。数据是你有价值的资产。带着尊敬的心态对待你的数据才能写出更好的SQL语句。