技术开发 频道

抛开程序员思维定式,简单几步掌握SQL

  【IT168 评论】大多数程序员,面对SQL的第一直觉,往往是按思考命令行或面向对象语言的方式,想着机器是如何一步步执行的,先这样、再那样,咦?参数传进来了吗?满足条件A、B吗?跳进了自己设定的圈中,无法自拔,把简单的问题复杂化了。SQL是少数几个声明性语言之一。它的很多使用方式可能会让很多人不习惯,它与命令行语言、面向对象语言的使用方式有很大不同,本文主要关注select语句的使用。

抛开程序员思维定式,简单几步掌握SQL

  在使用之前,首先要知道一点:SQL是声明性的。你只需要直接声明你想要的结果,例如:

抛开程序员思维定式,简单几步掌握SQL

  我想知道工资大于10万的员工名字,至于这些员工记录是如何获取的,从哪里获取的,你完全不需要关心,这种方式岂不是很美好?

  SQL语法是无序的

  混乱的执行顺序是SQL语法的常态,常常让人摸不着头脑。SQL语句的语法顺序是(正常的书写顺序):

抛开程序员思维定式,简单几步掌握SQL

  简单起见,没有列出所有的SQL子句。这种语法顺序与执行顺序(根据优化器选择)有本质的区别,其执行顺序如下:

抛开程序员思维定式,简单几步掌握SQL

  这里有三件事要注意:

  1、FROM是第一子句,而不是SELECT。执行时的第一件事是将数据从磁盘加载到内存中(某些数据库,数据是从硬盘抽取到数据缓冲区中的),以便对这些数据进行操作。

  2、SELECT在大多数语句之后执行,严格地说,在FROM和GROUP BY之后执行。当你认为你可以在WHERE子句中使用SELECT子句中声明的东西时,是完全错误的。

抛开程序员思维定式,简单几步掌握SQL

  如果,你想重用别名z,你有两个选择。一是重写所有涉及到的表达式。

抛开程序员思维定式,简单几步掌握SQL

  二是求助衍生表,通用数据表达式或视图,以避免别名重用。

  3、UNION的位置一定是在ORDER BY之前,无论是在语法还是执行排序上。许多人认为每个UNION子查询都可以用ORDER BY实现,但根据SQL标准和大多数SQL语言的执行来看,这并不是真的。虽然有些地方允许SQL语言对子查询或派生表排序,但不能保证在UNION操作后仍可以保留这种排序。

  注意,并非所有数据库都以相同的方式实现事务。例如,上述方式的规则2就不能完全适用于MySQL,PostgreSQL和SQLite数据库。

  始终记住SQL子句的语法顺序和执行顺序,以避免犯一些常见的低级错误。如果你可以理解其中的区别,什么事情能做,什么事情不能做就会非常明显。当然,如果语法的设计方式直接可以反映出执行顺序,这种方式对程序员是十分友好的。例如,微软的LINQ。

  SQL中的头等公民是表引用

  由于语法排序和执行顺序之间的差异,大多数初学者可能认为列值是SQL中的头等公民。 其实不然,最重要的是表引用。

  SQL标准定义了FROM子句:

抛开程序员思维定式,简单几步掌握SQL

  FROM子句的“输出”是所有表引用在某一维度上的联合,接下来,我们慢慢消化一下。

抛开程序员思维定式,简单几步掌握SQL

  以上是对a表和b表的联合,如果a有3列,b有5列,那么“输出表”将会有8(3+5)列。其中包含的记录是a x b的结果(笛卡尔积),如果a有3条记录,b有5条记录,则上述组合表引用将产生15条记录。

  这个“输出”被“输送”/“管道化”到GROUP BY子句中(在WHERE子句中过滤之后),在那里它被转换成一个新的“输出”,为以后的操作做准备。如果我们从关系代数/集合理论的角度来看这些东西,一个SQL表是一个或一组元组,每个SQL子句将转换成一个或多个关系,以产生新的关系。

  也就是说,面对SQL语句,应该首先从表的角度思考问题,就可以理解整个SQL语句在执行过程中的变化了。

  SQL的派生表引用功能相当强大

  表引用相当强大。举一个简单的例子是JOIN关键字,它实际上不是SELECT语句的一部分,而是“特殊”表引用的一部分。 如SQL标准(简化)中连接表的定义:

抛开程序员思维定式,简单几步掌握SQL

  我们可以再举个例子:

抛开程序员思维定式,简单几步掌握SQL

  a可能是这样的:

抛开程序员思维定式,简单几步掌握SQL

  将此扩展到上一个表达式中,我们可以得到:

抛开程序员思维定式,简单几步掌握SQL

  虽然不鼓励用逗号分隔两个表的语法出现,但你可以这样做,所得到的组合表将有a1 + a2 + b个维度。

  派生表比连接表更强大,接下来要讲到表连接。

  在以表引用的角度思考SQL的基础上,要了解JOIN是用于构造连接表的关键字,虽然不是SELECT语句的一部分,但一些数据库允许在INSERT,UPDATE,DELETE中使用JOIN。

  应使用JOIN进行表连接,而不是逗号

  之前,我们已经看到这个子句:

抛开程序员思维定式,简单几步掌握SQL

  高级的SQL开发人员可能会告诉你,不鼓励使用逗号分隔的表,应该使用JOIN,因为这有助于提高SQL语句的可读性,从而防止错误。

  一个很常见的错误是在某处忘记JOIN谓词,想一下这个语句:

抛开程序员思维定式,简单几步掌握SQL

  语句太长,可能会在某处忘记JOIN谓词,但其连接表语法的好处是:

  1、可以把连接谓词放在连接表附近,从而防止错误。

  2、更具表达性,可以区分外连接和内连接。

  JOIN操作基本上有五种方式:

抛开程序员思维定式,简单几步掌握SQL

  这些术语通常用在关系代数中。SQL对上述概念使用不同的术语,如果它们存在的话。

  EQUI JOIN

  这是最常见的JOIN操作。 它有两种连接方式:

  · INNER JOIN (或者是 JOIN)

  · OUTER JOIN (包括LEFT, RIGHT, FULL OUTER JOIN)

  他们的区别通过示例解释是:

抛开程序员思维定式,简单几步掌握SQL

  SEMI JOIN

  此关系概念可以在SQL中以两种方式表示:使用IN谓词或使用EXISTS谓词。 “Semi”在拉丁语中是“半”的意思。 此类型的连接仅用于连接表引用的“一半”。 这意味着什么? 再次考虑上面作者和书的示例。 我们不想要作者/书的组合,而只要那些实际上有书的作者信息。我们可以这样写:

抛开程序员思维定式,简单几步掌握SQL

0
相关文章