Dr. Codd's 对关系型数据库系统的十二条规则

       关系型数据库是最为流行的数据存储模式 它产生于一个名称为 A Relational Model of Data for Large Shared Data Banks 的论文中 SQL 进而发展为关系型的数据库 。对于关系型数据库 Dr. Codd's 定义了 12 条规则使之与其他类型的数据库相区别
0 、关系型数据库必须通过关系来实现对数据的完全管理
1 、所有在关系型数据库中的信息均可以在表中以数值的形式加以体现
2 、在关系型数据库中的每一项数据均可以通过库名 键名和列名来准确指定
3 、关系型数据库系统必须对空值(未知的和违规的数据)提供系统级的支持,有独特的缺省值,而且具有独立域 {这一段不太清楚}
4 、活动的、即时的数据联合 —— 它的意思就是在数据库中的数据应有逻辑表格的行的形式来表达,并且可以通过数据处理语言来访问
5 、完善的数据子语句 — — 它应该至少支持一种有严格语法规则和功能完善的语言,并且应该支持数据和定义、处理、完整性、权限以及事务等操作
6 、查看更新规则 — — 所有在理论上可以更新的视图可以通过系统操作来更新
7 、数据库中数据和插入、更新与删除操作 — — 该数据库系统不仅要支持数据行的访问,还要支持数据和的插入、更新和删除操作
8 、数据和物理独立性 — — 当数据在物理存储结构上发生变化时应用程序在逻辑上不应受到影响
9 、数据的逻辑独立性 — — 当改变表的结构时应用程序在最大程度上不受影响
10 、有效性独立 — — 数据库的语言必须有定义数据完整性规则的能力 数据应即时存储在线目录 而且在处理时必须通过这一五一节
11 、发布的独立性 — — 当数据第一次发布或当它重新发布时应用程序应不受影响

12 、任何程序不可能使用更低级的语言从而绕过数据库语言的有效性规则定义,大多数数据库具有父/子关系 这就是说在父结点中保存有子结点的文件指针

       这种方式有优点也有缺点。它的好处在于它使得数据在磁盘上的物理存储结构变得不再重要,编程人员只需存储下一个文件的指针就可以实现对下一个文件的访问,而且数据的添加和删除操作也变得非常容易,可是不同组的信息想要联合为一个新组就变得困难了。这是因为在这种方式下数据在磁盘上的存储格式不能在数据库建立以后再强制性地改变,如果需要这样做那就必须重新建立一个数据库结构。

        Codd's 的关系型数据库思想借用的逻辑代数的思想,使得数据的子集与父级之间具有平等的地位。由于信息可以很自然地组织在不同的表格中,Dr. Codd 也以这种方式来组织他所提出的数据库。

        在关系模式下,数据被存入类似于表格的结构中,这种表格由独立的数据元组,被称为列或字段,所组合而成 一组数据信息被存储为一行。举例来说,创建一个包括雇员内容的关系型数据库 我们可以很容易地从雇员表开始,而像这样的表在很容易得到的,该表中包含有如下信息、姓名、年龄、职业这三项数据用作雇员表的字段。

       如果数据库管理系统已经检索过了全部的数据,那么它将会把满足条件的的姓名、年龄、职业三项的记录返回给用户 SQL 会通知 DBMS 找什么样的数据

       随着关系型数据库模型的发展,有两种技术被引用到了在今天被称为服务器/客户机的数据库系统当中。第一项技术就是个人电脑;第二项技术则是局域网的发展,它导致的世界范围内的办公交叉。

       服务器/客户机的数据库系统处理过程被分解上了客户机和数据服务器上,新型的应用程序取代了基于主机的应用程序这一体系有着相当多的优点

    1、降低了维护费用

    2、减轻的网路负荷 处理过程在服务器上和客户机上均有
    3、多个操作系统可以基于相同了网络协议来共同工作
    4、本地化的数据操作提高了数据的完整性
对于什么是客户机/服务器型电脑系统 Bernard H. Boar 的定义如下

       客房机/服务器系统就是把单一的任务分解到多个处理器上进行协同处理,就像在单个处理器上运行时一样 一个完备的客户机/服务器系统可以将多个处理器捆绑在一起,以提供一个单一系统虚拟环境 共享的资源可以被位于远端的客户机通过特殊的服务来访问,这种结构可以逐级递归。所以一级服务器可以在最后转变为客户机进需要求其他的服务器提供服务,就这样一直下去。


       用过使用 SQL 和网络 应用程序就可以访问位于远端服务器上的数据库,个人电脑处理能力的提高可以对存放在一系统相关的服务器的数据库作出评定,而这此服务器是可以更换的,而应用程序则只需做出较少的改动甚至无需改动。


*****交互式语言
      该文章在许多场合下可以借用 BASIC 的概念。举例来说Microsoft Access 是基于windows的单用房应用程序,而SQL SEVER 则可以允许100 个用户同时工作。SQL 的最大优越性在于它是一种真正的跨平台的交互式语言,由于它可以被程序员在第四代的编程语言中调用,第四代编程语言可以做用少量的代码做大量的工作易于实现。ORACLE 公司是第一个发行基本于SQL的关系型数据库管理系统 RDBMS 的公司。虽然它是为 VAX/VMS 系统开发的 ORACLE,公司也是 DOS 下的关系型数据库的供应商之一,ORACLE 现在可以运行在近 70 种平台之上,在八十年代中期 Sybase 公司发行了。

SQL 是操作和检索关系型数据库的事实上的标准语言,它允许程序员和数据库管理员做如下的工作
      1、更改数据库的结构
      2、更改系统的安全设置
      3、增加用户对数据库或表的许可权限
      4、在数据库中检索需要的信息
      5、对数据库的信息进行更新
      注:对于 SQL 大家可能还不明白 S 即 Structured 结构, L 即 Language 语言, 这是显而易见的。但是 Q 的意思容易让人误解, Q 的意思当然是 Query 查询 — —如果你直译的话,可是这只限于你对数据库提问,但是 SQL 能干的不只是查询,通过它你可以建立一个库,添加和删除数据,对数据作联合,当数据库改变时触发动作,并把你的查询存储在程序或数据库中。


流行的 SQL 开发工具
        这一部分将介绍一些大众化的 SQL 开发工具 每一种工具都有它的优点和缺点.一些工具是基于 PC 用户的,强调易用性。而另一些则是为超大型数据库提供的,本部分将介绍选择这些工具的关键所在。

注:为了 SQL 在实际中的使用,举出了一些 SQL 在实际开发环境中的应用例子。SQL 只有出现在你的代码中,为你真正地解决了问题才说明它是有用的。

       Microsoft Access在一些应用实例中,Microsoft Access 是一个非常容易使用的基于 PC 机的数据库管理系统,在它的下边你既可以手工输入 SQL 语句也可以使用图形用户界面工具来生成 SQL 语句。
       Personal Oracle7我们使用 Personal Oracle7 来向大家演示,SQL 对大型数据库上的命令行使用方法。当用户对一个数据库或一个操作系统有充分的了解以后,需要在一个孤立的电脑上进行设计时这种方法是非常重要的。在命令行下,用户可以在 SQL PLUS 工具中输入不同的单的 SQL语句。该工具可以把数据返回给用户,或是对数据库进行适当的操作。大多数例子是针对初用 SQL 进行程序设计的程序员的,我们从最简单的 SQL 语句开始并进阶到事务处理阶段,为程序设计做好准备 Oracle 的发行版提供一整套的开发工具。它包括 C++和 Visual Basic 函数库(Oracle Objects for OLE) 通过它可以将应用程序与ORACLE 个人数据库链接在一起,它也可以为数据库、用户或管理员提供图形工具,同SQL*Loader 一样,它也经常用于从 Oracle 数据库中导出或引入数据SQL 。


注:Personal Oracle7 是 Oracle7 server 的不完整版,它只允许单用户操作,就如同它的名字一样,但它在 SQL 的语法使用与大型、更昂贵的 Oracle 版本是相同的。此外在Personal Oracle7中所使用的工具也适用于Oracle 的其他版本。我们选择 Personal7 基于以下原因
1、它几乎用到了本书中将要讨论的所有工具
2、它是可以在几乎全部的平台运行的 风靡世界的关系型数据库管理系统
3、可以从 Oracle 公司的服务器上下载一个它的 90 天限时版(http://www.oracle).
       注意在所给出的所有 SQL 代码都适用于其它的数据库管理系统,防止在其它的系统中语法出现大的差别,在例子中指出了它在其它系统中的不同之处Microsoft Query。Microsoft Query 是 Microsoft 公司的 Visual C++和 Visual Basic 开发工具包中所附带的一个非常有用的查询工具,它可应用在基于ODBC 标准下的数据库。该查询工具在将查询语句提交给数据库之前会将基保留在驱
开放型数据库联接 ODBC,ODBC 是为应用程序接口 API 提供的访问下层数据库所用的函数库,它通过数据库引擎与数据库交流 就像在 Windows通过打印驱动程序与打印机通信那样。为了访问数据库,可能还会需要网络驱动程序与异地数据库通信 ODBC 的结构。ODBC 的特色在于它不是针对任何一种数据库的。举例来说,你可以用相同的代码来在 Microsoft Access 表中或 Informix
database 上运行查询,而无需修改代码或只需做很小的改动,再提醒您一次,第三方数据库供应商可能会在 SQL 的标准之上对其
进行扩充 比如 Microsof 和 Sybase 的 Transact-SQL 以及 Oracle的 PL/SQL。当您用一种新型的数据库工作时您应该认真阅读一下它的文档 ODBC 是许多数据库所支持的一种标准。包括 Visual Basic Visual C++ FoxPro Borland Delphi和 PowerBuilder。
       基于 ODBC 所开发的应用程序有着明显的优势,因为它允许你在编写代码的时候不必考虑是为哪一个数据库所写的。当然它的运行速度要弱于特定的数据库代码,也就是说在使用 ODBC 的时候其灵活性更强但比起使用 Oracle7 或 Sybase 的函数库时要慢。


SQL 在编程中的应用
SQL 的最初标准是 ANSI-1986 而在 ANSI-1989 中定义的 SQL 在应用程序中的三种接口类型
1、模块语句 — — 在程序中使用过程 该过程可以通过主调参数向主调函数返回值
2、内嵌 SQL — — 可以在编写程序的过程中内嵌 SQL 语句,该方式在经常需要对 SQL语句进行预编译处理时所需要.在 Pascal                             FORTRAN COBOL PL/1 中均定义了这样的子句
3、直接调用 — — 由程序直接实现
        在动态 SQL 发展以前,内嵌 SQL 在编程中应用最为流行,这种方法在今天也仍然在使用。由于静态的 SQL — — 它的意思就是 SQL 语句已经被编译在了应用程序之中,不能在运行的过程中改变,这与编译程序同解释程序的区别类似。也就是说这种类型的 SQL 速度很快,但是灵活性很差,这在今天的商业应用领域是不适宜的。动态 SQL 这里就不多说了ANSI-92 标准将 SQL 语言标准扩展为一种国际化的标准,它定义了 SQL 的三种编译级别:登录调用、内嵌子句和完全编译。

主要的新特性如下

1、联接到数据库

2、移动游标

3、动态 SQL

4、外连接
      除了这些扩展以外还包括了第三方数据库供应商所提供的扩展。动态 SQL 允许你在运行时修改 SQL 语句,但是它的速度要比内嵌型 SQL 慢,它在调用级接口上为应用程序开发人员提供了相当大的灵活性。ODBC 或 Sybase 的 DB-Library 就是动态 SQL 的例子。调用级接口对于编程人员来说不是一个新概念,当您在使用 ODBC 时 举例来说,你需要在 SQL 语句提交给数据库时修改子句中的变量参数而使用该功能,在设计阶段可以通过使用其它的函数调用接收错误信息或结果,结果是以数据包的形式返回的。


问  为什么我要了解 SQL
答  到现在为止,如果你不知道如何利用大型数据库来进行工作,如果你要使用客户机/服务器型应用程序开发平台,如 Visual Basic Visual C++ ODBC Delphi 和PowerBuilder 以及一些已经移植到 PC 平台上的大型数据库系统,如 Oracle 和Sybase 来进行开发工作 ,那么你只有学习 SQL 的知识 在今天大多数的商用程序开发都需要你了解 SQL。
问  在学习 SQL 时我为什么要了解关系型数据库系统
答  SQL 在为关系型数据库系统开发的,不知道点关系型数据库系统的知识你就无法有效地使用 SQL
问  在 GUI 图形用户界面工具下我只需按按钮就可以写出 SQL 语句 为什么我还需要学习手工写 SQL
答  GUI 有 GUI 的方法 手工有手工的方法 一般说来手工写出来的 SQL 比 GUI 写出来的更有效率 GUI 的 SQL 语句没有手工写出的易读,而且如果你知道如何用手工来写,SQL 的话那么你在使用 GUI 时就会有更高的效率
问  既然 SQL 是一种标准化语言 那是不是说我可以用它在任何数据库下进行编程
答  不是。你只能将它用于支持 SQL 的关系型数据库系统,如 MS-Access Oracle Sybase和 Informix 尽管不同的系统在执行时有所差别,但是你只需要对你的 SQL 语句进行很小的调整。

把数据清楚地分成一个个唯一集的过程叫什么名字?标准化。它可以减少数据的冗余度和数据库结构的复杂性。
如何知道一种数据库系统是不是关系型数据库系统?

关系型数据库:把实际问题的数据分别归成若干个简单的二元关系,一个二元关系都可以建一个关系表。就像班级管理系统中的学生情况表、学生成绩表一样。

关系型数据库的关系有三种情况,我用婚姻来打个比方:
第一种是一夫一妻制,一个男人只能娶一个老婆,一个女人也只能嫁一个老公,这种关系叫做一对一关系
第二种是一夫多妻制(或者一妻多夫?:P),一个男人可以同时娶多个老婆,但是其中的任何一个老婆却都只能嫁给他一个,不能再嫁给另一个男人(一妻多夫制自己去解释,反正都一样,哈哈),这种关系叫做一对多的关系
第三种就乱套了,是多夫多妻制,一个男人可以同时娶多个老婆,其中的任何一个老婆也都还可以同时嫁给其它的任何多个男人(这跟动物有什么区别),这种关系叫做多对多的关系


在 SQL 中查询也能进行一般的查询工作,除了向数据库提出问题之外还可以实现下面的功能
1、建立或删除一个表
2、插入、修改或删除一个行或列
3、用一个特定的命令从几个表中查找所需要的信息并返回
4、改变信息的安全性

注意: 

1、在 SQL 语句中大小写是不敏感的(关键字可以大写也可以小写),并且用空格进行划分的

2、分号:当在 SQL 语句中出现分号就意味着本条语句已经结束

SQL 语句对大小写并不敏感,但在数据库中的数据却是大小写敏感的。举例来说,许多公司在储存数据时用大写字母,在这种情况下,所有的字段名也将是大写字母

Select name,startterm,endterm from presidents where name='LINCOLN'

现在我们来看另一个例子,在这个例子中的空格有问题吗?

不是。这个语句完全可以正常执行,但是如果你注意在你的语句中使用空格和大写字母会增强语句的可读性,当它变成你的工程,编程的一部分时会更便于维护

为什么在格式中大小写是不重要的?
原因何在?

答案是 — — 关键字 关键字是 SQL 语法中的保留字,在 SQL 语句中关键字是可选择的,但其内容有强制性在。SQL*PLUS在没有遇到分号时将不会执行语句,但是在其它的 SQL 解释器中可能不会用到分号。例如Microsoft Query 和 Borland's ISQL 不需要查询终止符,因为你是在编辑框中输入查询语句并且当你在按下按钮以后才开始执行查询

数据报的形成 — — SELECT 和 FROM

当两条语句结合使用时就有了后台访问数据库的能力。SQL 的关键字是 SQL 中的特定元素。如SELECT 和FROM 子句则是SQL语句的一部分 如, SELECT column1, column2, ...就是一个子句 而 SQL 语句则是几个子句的结合。例如你可以将 SELECT 子句和 FROM
子句组合成为一个 SQL 语句。


每一个种 SQL 都有其特定的出错信息

       例如SQL中出现 SELECT* ERROR at line 1 ORA-00936 missing expression

       当在访问ORACLE 时会有*出现以表示有事件产生,错误信息的意思是告诉你有一个东西丢了,这个丢失的东西就是 FROM 子句,Microsoft Query 会显示说它不能运行查询,并引导你发现错误所在 Borland's Interbase 将会弹出一个错误对话框 Personal Oracle7 的引擎将会出现如前所述的信息,并给出一个错误号码 所以当你手工输入 SQL语句时会看到详细的错误信息 以及对错误的简要诠释。

例如下表checks:

CHECK#   PAYEE             AMOUNT    REMARKS

1            MaBell                150             Havesonsnexttime

2            ReadingR.R.        245.34         TraintoChicago

3             MaBell               200.32         CellularPhone

4             LocalUtilities      98               Gas

5             JoesStale$Dent   150            Groceries

6              Cash                   25              WildNightOut

7              JoansGas             25.1           G

1、SQL>select * from checks    //结果中:对于数字类型采用右对齐而对于字符类型则是采用左对齐的 

2、SQL> SELECT payee,remarks,amount,check# from checks;
注意在 SELECT 子句中给出了每个列的名字 排序是根据列的先后顺序来进行的 注
意将最后列的列名与其后的子句 这里是 FROM 用空格分开。SQL> SELECT payee,check# from checks;//返回指定的列

3、SQL> select DISTINCT amount from checks;  //只想查看amount中不重复的数据

4、SQL> select ALL amount from checks;  //ALL 是在 SELECT 中默认的关键字 你几乎从来也不会用到 ALL 因为 SELECT与 SELECT ALL 是等价的

关键字 SELECT 可以检索数据库并从中返回数据,也可以用一个很长的语句并使用SELECT *来检索数据库中的所有表,而且你可以对指定表格的结果进行重新排序,而关键字 DISTINCT 则会强制性地要求返回的结果中不能有重复数据。

问  这些数据是从哪里来的?我们是如何得到它的?
答  数据是自己创建的,与数据库的联接是依靠你所使用的 SQL 它以传统的命令行方式与数据库进行会话该数据库原来属于服务器        或客户机范畴,但最近它已经被移植到了 PC 机上
问  可是我用不到这些数据库 那我还可以用 SQL 干什么?
答  你可以在编程语言中使用SQL一般的编程语言都支持内嵌的 SQL。例如COBOL你可在它的环境中写SQL并编译,而 Microsoft        公司则提供了应用程序接口函数,以允许编程人员在 Visual Basic C 或 C++中使用 SQL Sybase and Oracle 提供的库,也允许      你在编程时使用 SQL Borland 公司则将 SQL 置于 Delphi中。


表达式 条件语句与运算

表达式:

表达式可以返回一个值,表达式的类型非常广泛,它以包括各种类型的数据如数字、字符、以逻辑型等 

在下边的例子中 amount 就是一个表达式 它可以返回 amount 列中的数据SELECT amount FROM checks

条件语句:

WHERE 子句
where 子句的语法如下
           WHERE <SEARCH CONDITION>

运算:

  运算是你需要对从数据库中返回的数据进行数学处理时所用到的元素。运算可以归为六组:数值型 比较型 字符型 逻辑型和备注型以及混合型

  有加 减 乘 除和取模(有小数的数据不能应用取模运算);

1、SQL>SELECT ITEM,WHOLESALE,WHOLESALE+0.15 FROM PRICE;   

     给WHOLESALE列的所有数据+0.15,虚拟列,实际数据库中WHOLESALE列的数据没有变

2、写法一:

      SQL> SELECT ITEMPRODUCE,WHOLESALE,WHOLESALE+0.15 RETAIL  FROM PRICE;  //使用空格

      写法二:

     SQL> SELECT ITEM=PRODUCE,WHOLESALE,WHOLESALE+0.25=RETAIL FROM PRICE;  //使用=

     给ITEM重命名为PRODUCE,WHOLESALE列的所有数据+0.15的新列进行重命名为RETALL

     你大概想知道当不在命令行状态时应如何使用别名吧。很清楚,你知道报表生成器是如何工作的吗?总有一天,当有人让你写一个报表的生成器时,你就会记住它而且不用却重复Dr Codd 和 IBM 已经做过的工作。
两种加号的用法;

第一种用法是在 SELECT 子句中使用+号以执行对数据的运算并将结果显示出来 

第二种用法是在 WHERE 子句中使用加号,在WHERE中使用操作符可以在当你对数据有特定条件时具有更大的灵活性,在一些解释器中,加号还同时肩负着进行字符运算的责任。

减号的两种用途:

第一种用途是作为负号使用 

      SQL> SELECT STATE HIGHTEMP LOWS LOWTEMP HIGHS FROM HILOW;

第二种用法:很明显是作为减号从某一列中减去另一列 

      SQL> SELECT STATE,HIGHTEMP LOWS,LOWTEMP HIGHS,(LOWTEMP - HIGHTEMP) DIFFERENCE,FROM HILOW;

      注意这里使用了别名来对输入的错误进行更正,这只不过是一种暂时的补救方法。虽然这不是永久的解决办法,你是在常见的SQL 错误及其解决方案中会看到如何对数据以及输入进行更正,在那里你将学会如何对错误的数据进行更正。该查询不只是修正,至少看起来是这样错误的数据,而且还创建了一个新列以获得每个记录的最高与最低的差价。
如何你在一个字符型字段中意外地使用了减号,你将会看到如下信息
SQL> SELECT STATE FROM HILOW
ERROR ORA-01722 invalid number
No rows selected
在不同的解释器中错误的号码可能会不同 但是结果是相同的

除法、乘法、取模只有一种显而易见的应用 在 PRICE 表中它的应用如下

1、SQL> SELECT ITEM,WHOLESALE,(WHOLESALE/2) SALEPRICE,FROM PRICE; //WHOLESALE除2

2、SQL> SELECT ITEM,WHOLESALE,WHOLESALE*0.9 NEWPRICE,FROM PRICE;//WHOLESALE乘以0.9

3、SQL> SELECT NUMERATOR,DENOMINATOR,NUMERATOR%DENOMINATOR REMAINDER,FROM REMAINS;

    在一些 SQL 解释器中取模运算符为MOD函数— —返回数据的再加工。下边的语句所得到的结果与上边的语句相同:

    SQL> SELECT NUMERATOR,DENOMINATOR,MOD(NUMERATOR,DENOMINATOR) REMAINDER,FROM REMAINS;


优先级别  在这一部分的例子中主要讲述在 SELECT 语句中的优先级别

比较运算
       顾名思义,比较运算就是将两个表达式进行比较并返回三个数值中的一个True,False,Unknow。Unknow True 和 False 的意义无需说明,但是什么是 Unknow呢?
       为了便于理解什么是 Unknow 你需要理解一下什么是 NULL, 在数据库领域内 NULL的意义就是在一个字段之中没有数据。这与在该字段中数据为零或为空的不是同一个概念,为零或为空是一种特殊的数值,而 NULL 则表示在这个字段之中什么也没有。如果你想进行 Field=9 的比较,而 Field 字段是空的,那么比较的结果就会返回 Unknow。由于 Unknow是一种不正常的状态,所以大多数 SQL 都会置其为无效并提供一种叫 IS NULL 的操作来测试 Null 的存在。

找空值:

1、SQL> SELECT * FROM PRICE WHERE WHOLESALE IS NULL;//返回Unknow

2、SQL> SELECT * FROM PRICE WHERE WHOLESALE = NULL;//返回false,没有得到任何记录
      No rows selected

3、SQL> SELECT * FROM FRIENDS WHERE FIRSTNAME = 'JD';

     字符型字段:特殊的空字段表明在字符型字段中空字段与空白字段是不同的

大于与大于等于、小于与小于等于、不等号(<>或!=)

1、SQL> SELECT * FROM FRIENDS WHERE AREACODE>=300;

     //注:在这个语句中 300 没有使用引号,对于数字型字段是不需要加引号的;对于字符字段是需要加引号的

2、SQL> SELECT * FROM FRIENDS WHERE STATE< 'LA';

3、SQL>SELECT * FROM FRIENDS WHERE STATE < 'la';//2和3结果不一样

      因为大写的字母代码比小写的小(ASCII码),所以大写的字符总是排在小写字符的前面。为了保证安全,请在执行前检查大小写情况。技巧:想知道你所进行操作的结果,那你先要检查一下你的电脑所采用的字符编码集,PC机解释器使用的是 ASCLL 编码 而其它平台则使用 EBCDIC 编码。

4、SQL> SELECT * FROM FRIENDS WHERE FIRSTNAME <> 'AL';


字符操作
无论数据的输出是否为有条件输出,都可以对其中的字符串进行操作。下面将会讲述两个操作符LIKE 和 || 以及字符串连接的概念

       LIKE:如果你想从数据库中选出一部分数据并把它们添到一个模板中,并且不需要非常精确的匹配,你可以用 = 来对每一种可能的情况进行操作,但是这一过程烦琐而又耗时,这时你可以使用 LIKE。  

%  _ (下划线)   ||(连接) 几种通配符  

1、SQL>SELECT * FROM PARTS WHERE LOCATION LIKE '%BACK%';//找出其中有BACK的记录

2、SQL> SELECT * FROM PARTS WHERE NAME LIKE 'A%';//找出以A开头的记录,%表示0个或多个

3、SQL> SELECT * FROM FRIENDS WHERE STATE LIKE 'C_';//找出以C开头,后面有一个字符的记录

4、SQL> SELECT * FROM FRIENDS WHERE PHONE LIKE '555-6_6_';//找出以556-6x6y的记录 (x,y表示任意字符、数字等)

5、SQL> SELECT * FROM FRIENDS WHERE FIRSTNAME LIKE '_L%';//找出以xL开头的记录

  下划线_:用于代替一个任意字符(相当于正则表达式中的 ? )

  百分号%:用于代替任意数目的任意字符(相当于正则表达式中的 * )

  方括号[]:用于转义(事实上只有左方括号用于转义,右方括号使用最近优先原则匹配最近的左方括号)

  尖号<>:用于排除一些字符进行匹配(这个与正则表达式中的一样)

  需要说明的是,只有like操作才有这些特殊字符,=操作是没有的。

  eg:  [马先生]'的意义是搜索字段中含有马or先or生的所有记录,而不是搜索‘[马先生]’ 要想搜索'[马先生]' 写成 '[[]马先生]'  将左边中括号转义

6、SQL> SELECT FIRSTNAME || LASTNAME ENTIRENAME FROM FRIENDS;//||可以将两个字符串连接

7、SQL> SELECT FIRSTNAME+LASTNAME ENTIRENAME FROM FRIENDS;

它试图将两个数字做加法运算,但是它没有在表达式中找到任何数字。

注:有一些解释器也采用加号来连接字符串,请检查一下你的解释器

8、SQL> SELECT LASTNAME ||   ','   || FIRSTNAME NAME FROM FRIENDS;//这条语句在姓与名之间插入了一个逗号

注:请注意在姓与名之间的多余的空格 这些空格是数据的一部分,对于确定的数据类型空格将右填充至达到字段的设定宽度


逻辑运算

SQL> SELECT LASTNAME YEARS*12-LEAVETAKEN REMAINING 

FROM VACATION 

WHERE LASTNAME LIKE 'B%' AND YEARS*12-LEAVETAKEN>50

AND:AND 只有当两个表达式的值都为真的时候才会返回真。如果任意一个表达式的值不是真那么结果就会是假的

OR:你也可以使用 OR 来对几个条件进行合并,当其中的任一个条件为真时,其结果就会为真值

NOT:顾名思义,它对条件取反,条件为假时结果为真,条件为真时结果为假

1、SQL> SELECT LASTNAME 

WORKAHOLICS 

FROM VACATION 

WHERE YEARS >= 5 AND ((YEARS *12)-LEAVETAKEN)/(YEARS * 12) < 0.50;

//例子1和2都是找到公司中工作时间5年以上员工和休假时间不足已有假期的50%的员工,(YEARS *12)-LEAVETAKEN为剩余假期

2、SQL> SELECT LASTNAME 

WORKAHOLICS 

FROM VACATION 

WHERE YEARS >= 5 AND ((YEARS *12)-LEAVETAKEN)/(YEARS * 12) >= 0.50;

3、SQL>SELECT * FROM PRICE WHERE WHOLESALE IS NOTNULL;//找出所有的非空项


集合运算 SET

UNION 与 UNION ALL:UNION 将返回两个查询的结果并去除其中的重复部分

1、SQL> SELECT NAME FROM SOFTBALL
     UNION  SELECT NAME FROM FOOTBALL;  //合并两个表,去除两个表中的重复的NAME

2、SQL> SELECT NAME FROM SOFTBALL
     UNION ALL SELECT NAME FROM FOOTBALL;  //UNION ALL 与 UNION 一样对表进行了合并,但是它不去掉重复的记录

如果我们想知道都有谁同时在两个表中呢?UNION 无法做到这一点,我们需要使用intersect
INTERSECT 相交:INTERSECT 返回两个表中共有的行。

MINUS 相减:MINUS 返回的记录是存在于第一个表中但不存在于第二个表中的记录

3、SQL> SELECT * FROM FOOTBALL
     INTERSECT SELECT * FROM SOFTBALL;   //将返回两个表中有存在的员工

4、SQL> SELECT * FROM SOFTBALL MINUS SELECT * FROM FOOTBALL; //在表SOFTBALL中不在FOOTBALL中

5、SQL> SELECT * FROM FRIENDS WHERE STATE= 'CA' OR STATE ='CO' OR STATE ='LA';

     SQL> SELECT * FROM FRIENDS WHERE STATE IN('CA','CO','LA'); 

     //两者查询结果相同

6、SQL> SELECT * FROM FRIENDS WHERE AREACODEIN(100,381,204);

7、SQL> SELECT * FROM PRICE WHERE WHOLESALE>0.25 AND WHOLESALE<0.75; //不包括边界值

     SQL>SELECT * FROM PRICE WHERE WHOLESALE BETWEEN 0.25 AND 0.75;  

     //between...and...,BETWEEN 操作将包括边界值

不论你使用内嵌 SQL 的 COBOL 还是微软的 ODBC 它们所使用的 SQL 结构都是一样的

      既然 SQL 是一种标准,那为什么又种是让我检查一下自己的解释器呢?
我们所使用的是 ANSI1992 标准,但大多数供应商对它进行了修改以使它更适用于自己的数据库,我们是以 ANSI1992 标准为基础的,但在具体使用时要注意它们的不同。


函数:对数据的进一步处理

      在 SQL 中的函数可以执行一些储如对某一些进行汇总或将一个字符串中的字符转换为大写的操作


1、汇总函数

      开始的五个汇总函数 COUNT SUM AVG MAX MIN 是由 ANSI 标准所制定的

      COUNT:该函数将返回满足 WHERE 条件子句中记录的个数

      SUM:它返回某一列的所有数值的和,SUM 只能处理数字。
       SUM 只能处理数字如果它的处理目标不是数字 你将会收到如下信息
       ERROR
       ORA-01722 invalid number
       no rows selected
       该错误信息当然的合理的 因为 NAME 字段是无法进行汇总的

      AVG:AVG 可以返回某一列的平均值,AVG 函数只能对数字进行计算

      MAX:某一列中的最大值,可为字符串

      MIN:某一列中的最小值,可为字符串

      VARIANCE:VARIANCE 方差(不是标准中所定义),VARIANCE 也是一个只应用于数值对象的函数

      STDDEV:STDDEV 返回某一列数值的标准差,STDDEV也是一个只应用于数值对象的函数

例子:

   SELECT COUNT(*) FROM TEAMSTATS WHERE HITS/AB>0.35; //列名为COUNT(*)

   SELECT COUNT(*) NUM_BELOW_350 FROM TEAMSTATS; //列名为NUM_BELOW_350
   SELECT SUM(SINGLES) TOTAL_SINGLES FROM TEAMSTATS;

   a、SELECT SUM(HITS)/SUM(AB) TEAM_AVERAGE FROM TEAMSTATS; //估计一下一个球队的平均中球率

   b、SELECT AVG(HITS/AB) TEAM_AVERAGE FROM TEAMSTATS; //AVG 计算的是打中的次数与总打击次数商的平均值

   在a中是对打中次数和打击次数分别求和后在进行相除的。举例来说 A 队员打了 100 杆 中了 50 次 那么他的平均值是 0.5 B 队员打了 1 杆 没打中 他的平均值是 0.0 而 0.0 与 0.5 的平均值是 0.25 如果你按打 101 杆中 50 杆计算,那么结果就会是正确的,下边的例子将会返回正确的击中率输入/输出

    SELECT AVG(HITS)/AVG(AB) TEAM_AVERAGE FROM TEAMSTATS;

       SELECT MIN(NAME) FROM TEAMSTATS; //返回最低的字符串

       SELECT MAX(HITS) FROM TEAMSTATS;  //返回最大值

       SELECT MIN(AB) MAX(AB) FROM TEAMSTATS;

       SELECT VARIANCE(HITS) FROM TEAMSTATS;

       SELECT STDDEV(HITS) FROM TEAMSTATS;

    SELECT COUNT(AB),AVG(AB),MIN(AB),MAX(AB),STDDEV(AB),VARIANCE(AB) .SUM(AB) FROM TEAMSTATS;


2、日期与时间函数

       我们的生活是由日期和时间来掌握的,大多数的 SQL 解释器都提供了对它进行支持的函数,在这一部分我们使用 PROJECT 表来演求日期和时间函数的用法.

       SQL> SELECT * FROM PROJECT;

       注:这里的数据类型使用日期型,大多数 SQL 解释器都有日期型,但是在语法的细则上有不同之处

       ADD_MONTHS:将给定的日期增加N个月

       LAST_DAY:可以返回指定月份的最后一天

       MONTHS_BETWEEN:知道在给定的两个日期中有多少个月,MONTHS_BETWEEN 对于你所给出的月份的次序是敏感的

              如果两个日期月份内天数相同,或者都是某个月的最后一天,返回一个整数,否则,返回数值带小数(小数是以每天1/31月来计算月中剩余          天数)。如果日期1比日期2小 ,返回值为负数。

       NEW_TIME:想把时间调整到你所在的时区

       NEXT_DAY:将返回与指定日期在同一个星期或之后一个星期内的,你所要求的星期天数的确切日期

       SYSDATE:将返回系统的日期和时间

例子:

       SELECT TASK FROM PROJECT WHERE ADD_MONTHS(STARTDATE,1)>ENDDATE;

       SELECT DISTINCT LAST_DAY( 1-FEB-95 ) NON_LEAP LAST_DAY( 1-FEB-96 ) LEAP;  //DISTINCT去重(唯一性)闰年的二月最后一天

       SELECT TASK STARTDATE ENDDATE MONTHS_BETWEEN ENDDATE,STARTDATE DURATION FROM PROJECT;

       SELECT * FROM PROJECT WHERE MONTHS_BETWEEN('19-MAY-95',STARTDATE)>0;//显示在 1995 年 5 月 19 日以前开始的比赛

       SELECT ENDDATE EDT NEW_TIME(ENDDATE,'EDT','PDT') FROM PROJECT;

      SELECT STARTDATE NEXT_DAY(STARTDATE,'FRIDAY') FROM PROJECT; //想知道你所指定的日期的星期五是几号

      SELECT DISTINCT SYSDATE FROM PROJECT; 

      SELECT * FROM PROJECT WHERE STARTDATE>SYSDATE;//你已经看到了项目在今天所启动的部分

例题:已知birthday求年龄,平均年龄        SELECT floor(months_between(SYSDATE, to_date('20170403','yyyy-mm-dd'))/ 12) a,  /*手工输入日期*/
       months_between(SYSDATE, dt.modifydate) / 12 b, /*从数据库取值计算月份*/
       floor(months_between(SYSDATE, dt.modifydate) / 12) c /*对月份向下取整,表示年龄*/
       FROM org_userinfo dt;
       算年龄可以精确到日。

floor(x),有时候也写做Floor(x),其功能是“向下取整”,或者说“向下舍入”,即取不大于x的最大整数(与“四舍五入”不同,下取整是直接取按照数轴上最接近要求的值左边的值,也就是不大于要求的值的最大的那个)。

3、数学函数

       大多数情况下你所检索到的数据在使用时需要用到数学函数 大多数 SQL 的解释器都提供了与这里相类似的一些数学函数

       ABS:返回给定数字的绝对值

       CEIL 返回与给定参数相等或比给定参数在的最小整数 

       FLOOR:返回与给定参数相等或比给定参数小的最大整数

       COS、COSH、SIN、SINH、TAN、TANH:COS SIN TAN 函数可以返回给定参数的三角函数值,默认的参数认定为弧度制。如果你没有认识到                     这一点那你会觉得下例所返回的值是错误

       EXP:EXP 将会返回以给定的参数为指数 以 e 为底数的幂值

       LN and LOG:这是两个对数函数 其中 LN 返回给定参数的自然对数。注意:不能忽视了参数的取值范围,负数是没有对数的

       MOD:在 ANSI 标准中规定取模运算的符号为%在一些解释器中被函数 MOD 所取代

       POWER:返回某一个数对另一个数的幂。在使用幂函数时,第一个参数为底数,第二个指数

       SIGN:  如果参数的值为负数,那么 SIGN 返回-1;如果参数的值为正数,那么 SIGN 返回 1;如果参数为零,那么 SIGN 也返回零。

       SQRT:  该函数返回参数的平方根 由于负数是不能开平方的 所以我们不能将该函数应用于负数

例子:

       SQL>SELECT ABS(A) ABSOLUTE_VALUE FROM NUMBERS;

       SQL>SELECT B,CEIL(BCEILING FROM NUMBERS;

       SQL>SELECT A,COS(A) FROM NUMBERS;//A为角度时,默认为弧度制

       SQL>SELECT A,COS(A*0.01745329251994) FROM NUMBERS;//得到角度转换成弧度后的数值

       SQL>SELECT A EXP(AFROM NUMBERS;

       SQL>SELECT A LN(ABS(A)) FROM NUMBERS;//ABS进行取绝对值后,在进行LN

       SQL>SELECT A,B,MOD(A,B) FROM NUMBERS;

       SQL>SELECT A,CEIL(B),POWER(A,CEIL(B)) FROM NUMBERS;

          //如果第一个参数为负数的话 那么第二个参数就必须是整数,负数是不能开方的,对于这个问题可以使用 CEIL 或 FLOOR 函数

       SQL>SELECT A FROM NUMBERS WHERE SIGN(A)=1;

       SQL>SELECT ABS(A),SQRT(ABS(A)) FROM NUMBERS;//ABS进行取绝对值后,在进行sqrt


4、字符函数

       CHR:  该函数返回与所给数值参数等当的字符,返回的字符取决于数据库所依赖的字符集

       CONCAT:  表示将两个字符串连接起来,同 || 

       INITCAP:  数将参数的第一个字母变为大写,此外其它的字母则转换成小写

       LOWER 和 UPPER:  LOWER 将参数转换为全部小写字母而 UPPER 则把参数全部转换成大写字母

       LPAD 与 RPAD:  这两个函数最少需要两个参数,最多需要三个参数。每一个参数是需要处理的字符串,第二个参数是需要将字符串扩充的宽度 第三个参数表                  示加宽部分用什么字符来做填补,第三个参数的默认值为空格,但也可以是单个的字符或字符串。LPAD为左边追加,RPAD为右边追加

       LTRIM 与 RTRIM:LTRIM 和 RTRIM至少需要一个参数,最多允许两个参数。第一个参数与 LPAD 和 RPAD类似 是一个字符串,第二个参数也是一个字符或                  字符串,默认则是空格,如果第二个参数不是空格的话,那么该函数将会像剪除空格那样剪除所指定的字符。 LTRIM 与 RTRIM剪除空格或指定的字符

       REPLACE:  需要三个参数,第一个参数是需要搜索的字符串,第二个参数是搜索的内容,第三个参数则是需要替换成的字符串,如果第三个参数省略或者是                           NULL,那么将执行搜索操作而不会替换任何内容。

         SUBSTR:这个函数有三个参数。允许你将目标字符串的一部份输出,第一个参数为目标字符串,第二个字符串是将要输出的子串的起点,第三个参数是将                      要输出的子串的长度。

         TRANSLATE:这一函数有三个参数:目标字符串、源字符串和目的字符串,在目标字符串与源字符串中均出现的字符将会被替换成对应的目的字符串的字                      符。这个函数对大小写是敏感的。

         INSTR: 知道在一个字符串中满足特定的内容的位置可以使用 INSTR。它的第一个参数是目标字符串,第二个参数是匹配的内容,第三和第四个参数是数字                      用以指定开始搜索的起点以及指出第几个满足条件的将会被返回。

          LENGTH: LENGTH将返回指定字符串的长度

例子:

       SQL>SELECT CODE CHR(CODE) FROM CHARACTERS;

       SQL>SELECT CONCAT(FIRSTNAME,LASTNAME) "FIRST AND LAST NAMES" FROM CHARACTERS;  

       //当用多个词来做为别名时需对它们使用引号 请检查你的解释器 看看它是否支持别名

       SQL>SELECT FIRSTNAME,BEFORE,INITCAP(FIRSTNAME,AFTER) FROM CHARACTERS;

       SQL>UPDATE CHARACTERS SET FIRSTNAME='kelly' WHERE FIRSTNAME='KELLY';

       SQL>SELECT FIRSTNAME,UPPER(FIRSTNAME),LOWER(FIRSTNAME) FROM CHARACTERS;

       SQL>SELECT LASTNAME,LPAD(LASTNAME,20,'*') FROM CHARACTERS;//向字段中加入了五个字符(该字段的定义宽度为 15)

       SQL> SELECT LASTNAME,RPAD(RTRIM(LASTNAME),20,'*') FROM CHARACTERS;//清空空格·,扩展到20个字段,用*填充

       SQL> SELECT LASTNAME RTRIM(LASTNAME) FROM CHARACTERS;//剪除空格

       SQL>SELECT LASTNAME LTRIM(LASTNAME,'C') FROM CHARACTERS;//左边剪除C

       SQL> SELECT LASTNAME REPLACE(LASTNAME,'ST','**') REPLACEMENT FROM CHARACTERS;//将‘ST’替换为‘**’

       SQL>SELECT FIRSTNAME SUBSTR(FIRSTNAME,2,3) FROM CHARACTERS;//从第二个字符开始,往后进行,显示三位

          //如果SUBSTR第二个参数为负数 那么将会从源串的尾部开始向前定位至负数的绝对值的位置。如果没有第三个参数,将会输出字符串余下的部分

       SQL> SELECT SUBSTR(SSN,1,3) ||'-'||SUBSTR(SSN,4,2) ||'-'||SUBSTR(SSN,6,4);

          //注:当数字特别大。例如 1,343,178,128,需要用逗号分隔时,以及区位号码或电话号码需要下划线分隔时特别有效

       SQL> SELECT SUBSTR(NAME,1,15) NAME, SUBSTR(JOB,1,15) JOB FROM JOB_TBL;

          //SUBSTR 的另一个非常有用的功能,倘若你需要打印一个报表而其中一些列的宽度超。过了 50 个字符时,你可以使用 SUBSTR 来减小列宽以使它更接               近数据的真实宽度。

       SQL>SELECT FIRSTNAME,TRANSLATE(FIRSTNAME,'ABCDEFG','AAAAAAA') TRANSLATE_FIRSTNAME FROM CHARACTERS; 

          //出现A到G的大写字符都转换为A

       SQL>SELECT LASTNAME,INSTR(LASTNAME,'O',2,1) FROM CHARACTERS;//从字符串的第二个字符开始搜索并返回第一个以 O 开头的字符的位置

       SQL>SELECT FIRSTNAME,LENGTH(RTRIM(FIRSTNAME)) FROM CHARACTERS;


5、转换函数

         转换函数有三个, 可以使你方便地将数据从一种类型变换为另一种类型。

         TO_DATE:将一个数字或字符型转换为日期型。若为数字型字符型转换后可进行加减等运算,若为非数字型字符型转换后不可以进行加减等运算

         TO_CHAR:将一个数字或日期型转换为字符型,不同的解释器可能会使用它来转换其它的数据类型,例如日期型转换为字符型或者是拥有更多的参数。

                          要以24小时的形式显示出来要用HH24

                            select * from XS where to_char(birthday,'MM')=5;/*找出5月份出生的人的信息*/

                            select to_char(trunc(sysdate,'YYYY'),'YYYY') from XS; /*sysdate为当前时间(2017),不能为YYYY-MM等*/

                            select to_char(trunc(sysdate,'YEAR'),'YEAR') from XS;/*返回sysdate为当前时间年份(2017)的英文表达*/

                            select trunc(sysdate ,'YEAR') from XS; /*sysdate为当年的第一天(2017-01-01)*/

                            select trunc(sysdate) from XS; /*返回具体年月日具体时间(2017-04-21)*/

                    注意:----year英文表达年份,trunc函数进行截取。TRUNC(number,num_digits) ,Number 需要截尾取整的数字,Num_digits 用于指定取                                 整精度的数字。Num_digits 的默认值为 0。TRUNC()函数截取时不进行四舍五入。

         TO_NUMBER: 将一个字符串型数字转换为数值型,不能为日期型或非字符串型数字

         注:日期型的形式为 to_date('2017-04-21','yyyy-mm-dd') 。可使用yyyy-mm-dd HH:mm:ss或者其中一部分MM等

日期格式参数含义说明  
D 一周中的星期几  
DAY 天的名字,使用空格填充到9个字符  
DD 月中的第几天  
DDD 年中的第几天  
DY 天的简写名  
IW ISO标准的年中的第几周  
IYYY ISO标准的四位年份  
YYYY 四位年份  
YYY,YY,Y 年份的最后三位,两位,一位  
HH 小时,按12小时计  
HH24 小时,按24小时计  
MI 分  
SS 秒  
MM 月  
Mon 月份的简写  
Month 月份的全名  
W 该月的第几个星期  
WW 年中的第几个星期

例子:

         SQL>SELECT TESTNUM,LENGTH(TO_CHARR(TESTNUM)) TESTNUM FROM CONVERT;//LENGTH(TO_CHAR(TESTNUM))求转换后的长度

          //如果对数字使用 LENGTH函数将会返回错误。注意 : TO_CHAR 与在先前进过的 CHR 不同, CHR 返回字符集中给定数字位置的一个字符或符号

          SQL> SELECT NAME,TESTNUM,TESTNUM*TO_NUMBER(NAME) FROM CONVERT;//如果该函数没有将 NAME 转换为数值的话将会返回一个错误信息

6、其它函数

     GREATEST 与 LEAST:这两个函数将返回几个表达式中最大的和最小的

       USER:该函数返回当前使用数据库的用户的名字

例子:

       SQL> SELECT GREATEST('ALPHA',;BRAVO','FOXTROT') DELTA FROM CONVERT;

         //将会返回在字母表中最靠后的字符开头的字符串 虽然看起来似乎没有必要使用 FROM 子句,可是如果 FROM 子句没有的话,你将会收到一个错误信息。             每一个 SELECT 语句都需要 FROM 子句。由于给定的表有三行,所以结果返回了三个。

       SQL> SELECT LEAST(34,567,3,45,1090) FROM CONVERT;

       SQL> SELECT USER FROM CONVERT;

          //SELECT 又一次对表中的每一行都返回了结果。该函数与在今天早些时候提及的日期函数类似,甚至尽管 USER 不是表中确实存在的列,但 SELECT 仍然              检索了表中的每一行


SQL中select子句

1、 WHERE

     SELECT 列名称 FROM 表名称 WHERE 列 运算符 值
仅使用 SELECT 和 FROM 子句,你会受到表中的每一行数据均返回的限制。

AS的用法(as 可理解为:用作、当成,作为):一般是重命名列名或者表名

SQL>SELECT LOCATION AS "WHERE'S WALDO?" 

FROM PUZZLE 

WHERE NAME = 'WALDO';

//找到NAME为WALDO的,LOCATION重命名为"WHERE'S WALDO?"。可以不用AS,用空格即可

2、 STARTING WITH

   STARTING WITH 子句附加于WHERE 子句上,它的作用与 LIKE(exp%)相似 。

      SELECT PAYEE,AMOUNT,REMARKS 

      FROM CHECKS 

      WHERE PAYEE STARTING WITH('Ca');//找到STARTING中Ca开头的

3、 ORDER BY

       SELECT FROM 语句只会给你一个列表,除非你已经定义了关键字(创建视图和索引),否则你查询的结果是依据它们在输入时的次序排列的。数据输出的情况的确是按照它们被输入的先后次序排序的。

        ORDER BY 子句为你提供了对输出的结果进行排序的方法,默认升序排序,ASC为升序排序,DESC为降序排序。

   1)SQL>SELECT * 

        FROM CHECKS 

        ORDER BY PAYEE DESC;//PAYEE列按降序排序

   2)SQL>SELECT PAYEE,AMOUNT 

        FROM CHECKS 

        ORDER BY CHECK# ASC;

   3)SQL>SELECT PAYEE,AMOUNT 

        FROM CHECKS 

        ORDER BY REMARKS,PAYEE;//REMARKS和PAYEE两列都升序排列,先前者REMARKS后后者PAYEE

       //假如你已经知道了你想要进行排序的列是表中的第一列的话,那么你可以用 ORDER BY 1 来代替输入列的名字

4、 GROUP BY

           GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。
           SQL GROUP BY 语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
/*注意select找出的字段必须存在在group by中的字段,group by中的字段可以不全在select中*/

5、 HAVING

          在 SQL 中增加 HAVING 子句原因是WHERE 关键字无法与合计函数一起使用(例如统计每门课程的选课人数,找到每门课程的前三名等)。在group by后将进行使用,条件语句。
          SQL HAVING 语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value


SELECT TEAM,AVG(SALARY)

FROM ORGCHART 

GROUP BY TEAM

HAVING SALARY<38000 ;
分析:
为什么这一次的结果与子句 HAVING AVG(SALARY) < 38000 是对每一组的 SALARY 求平均数并将数值大于 38000 的组返回,正像你所想到的那样 HAVING
SALARY < 38000 则是用另外一种处理方式 所以就会有不同的结果。根据 SQL 的解释规则 如果用户要求对分组数据执行 HAVING SALARY < 38000 它么它会对数据库中的每个记录均进行检查 并且剔除 SALARY 大于 38000 的 这样的话就只有 PR 符合条件了在其它组中都至少有一条 SALARY 大于 38000 的记录 并不是所有的解释器都执行这条语句 ACCESS 就不能。

警告:在一些解释器中,如果在 HAVING 子句中使用了非汇总函数将会导致错误 ACCESS就是这样, 在没有对你所使用的解释器做认真的检查之前不要认为这样做一定会得到结果



更多推荐

SQL学习1