初学者Oracle数据库:sql语句的基本使用与示例

一.DBMS  和 DB
   1.DBMS 是什么
     数据库管理系统 是管理数据库的软件
   2.DB  是什么
     真正存储数据的文件
   3.RDBMS 和 RDB
     关系型数据库管理系统 和 关系型数据库
     基于二维表的数据库 就是关系型数据库        
   4.二维表中的基本概念
     表头
     行
     列
     字段名
     字段值  
   5.关系型数据库的代表
     oracle     甲骨文     oracle9i oracle10g 
                           oracle11g
     DB2        IBM
     sqlserver  微软       
     mysql      sun--->oracle   
二.操作数据库的语言SQL(结构化查询语言) 
   1.查询  
     select    
   2.数据定义的语句  DDL
     create  table
     drop    table
     alter   table 
   3.数据操作语句    DML
     insert 
     delete 
     update
   4.事务控制语句    TCL
     commit
     rollback
     savepoint 
三.如何使用服务器上的数据库
   1.远程登录服务器
   telnet    服务器IP  
   2.输入用户名  密码
   3.输入指令
   sqlplus 
   4.输入用户名  密码
   5.自动进入sql编程环境
   SQL> !clear
四.使用Sql的编程环境 查看数据库中的表结构
 SQL>desc  表名;
SQL> desc  s_emp;
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------------
 ID    员工编号                                    NOT NULL NUMBER(7)
 LAST_NAME  姓                                NOT NULL VARCHAR2(25)
 FIRST_NAME 名                                        VARCHAR2(25)
 USERID     用户编号                                         VARCHAR2(8)
 START_DATE 入职日期                                        DATE
 COMMENTS   备注                                         VARCHAR2(255)
 MANAGER_ID 领导的员工编号                                        NUMBER(7)
 TITLE      职位                                         VARCHAR2(25)
 DEPT_ID    部门编号                                          NUMBER(7)
 SALARY     月薪                                        NUMBER(11,2)
 COMMISSION_PCT 提成                                    NUMBER(4,2)                       
 
 1.查看表结构可以得到的信息  表头中每个字段的名
 2.字段是否必须有值   如果必须有值 则显示
   成 not  null
 3.可以得到字段名的类型
   number      数字类型
   varchar2    字符串类型
   date        日期类型

查询每个人的月薪 
select   salary   from   s_emp;    
SELECT   salary   FROM   s_emp;  
------------------------------------------------
             查询语句select语句
一.from子句
   1.如何从表中查询一个字段的值
     1.1 语法
     select   字段名   from  表名;
     1.2 查询s_emp 表中的所有的 id
     select    id      from  s_emp;
   2.如何从表中 查询多个字段的值
     2.1 语法
        select   字段名1,字段名2   from  表名;
     2.2 把s_emp 表中的 id  first_name salary
        显示出来。
        select   id,first_name,salary  from s_emp;  
   3.如何查询所有的字段的值 
     select  id,first_name      
     *号可以代表所有的字段名
     select  * from  s_emp;
   4.sql中的数学运算
     +  -  *  /
     4.1 把每个员工的工资 和 工资加100之后显示出来
     select  salary,salary+100 from s_emp;  
     4.2 把每个员工的月薪 和 年薪显示出来
     select  salary,salary*13  from  s_emp; 
   5.字段或者表达式的别名
     5.1 语法就是在字段 或者表达式后另起一个名字
     5.2 显示月薪 和 年薪的别名  
     select  salary monsal,salary*13 yearsal  from  s_emp; 
     5.3 别名默认处理成大写  别名只能有一个
	 别名中有空格字符或者想原样显示 
     select  salary monsal,salary*13 year sal  from  s_emp;     
     5.4 使用双引号 可以把多个对象看成一个整体
         可以使别名原样显示
     select  salary "monsal",salary*13 "Year sal"   from  s_emp; 
    6.sql中如何表达字符串
      6.1 语法
      使用单引号 引起一串字符
      6.2 举例
      ''   ' '   'a'   '&'  'hello world'
      6.3 oracle 中如何拼接字符串
         6.3.1 使用字符串拼接符号     ||
         6.3.2 举例
         select  first_name||last_name from  s_emp;
         6.3.3 在first_name 和 last_name 之间拼接一个下划线字符
         select  first_name||'_'||last_name from s_emp;
         6.3.4 思考如何在first_name 和last_name 之间拼接一个单引号
         %d  %lf    %%表达一个%
         select  first_name||''''||last_name from  s_emp;
         6.3.5 在first_name 和 last_name 之间拼接两个单引号
         select  first_name||''''''||last_name  from  s_emp; 
         select  first_name||''''||''''|| last_name from     s_emp;
      7.NULL 值的处理 
        7.1 查询 s_emp 表中所有 id,salary 以及对应 commission_pct 
        select  id,salary,commission_pct  from  s_emp; 
        7.2 按照这种方式计算年薪  月薪乘以12 再加上月薪乘以12乘以提成除以100
        select  salary*12,salary*12+salary*12*(commission_pct/100) from  s_emp;          
        任何值和NULL 做运算结果都是NULL
        7.3 oracle中如何 处理NULL值
        nvl(par1,par2) NULL值处理函数
        par1如果为NULL 则返回par2的值
        par1如果不为NULL 就返回par1的值
        NULL 要尽早处理   
        select  salary*12, salary*12+salary*12*(nvl(commission_pct,0)/100) from  s_emp;    
        7.4  要求显示 s_emp 表中的 id  first_name manager_id  如果manager_id 为NULL 则显示成 -1 
        select  id,first_name,nvl(manager_id,-1) from  s_emp;     
     8.数据的排重显示
       8.1 distinct  关键字完成 
       select  salary from  s_emp;
       select  distinct salary from s_emp;  
       select  distinct id from s_emp;  
       8.2 联合排重
       id     salary
       1      800
       2      800 
       2      800   
       显示   id  salary  如果id 和salary 的值都相同 就只显示一次 
       select  distinct id,salary from s_emp;  
       select  title,salary from s_emp;
       select  distinct title,salary from s_emp;     
 二.where 子句(条件子句)
    1.作用
    限制表中的行数据的返回
    符合where条件的数据 就返回 不符合where 条件的数据就被过滤掉。
    2.两个极端条件
    select  salary  from s_emp;
    select  salary  from s_emp where 1=1;
    select  salary  from s_emp where 1!=1;
    no rows selected  
    3.number 类型数据的条件判断
      3.1 把s_emp 表中 id  salary  显示出来
      要求显示 salary 大于1200的 
      select  id,salary from  s_emp where salary>1200;
      3.2 把s_emp 表中 id  salary  显示出来
      要求显示 salary 等于1200的 
      select  id,salary from  s_emp where salary=1200; 
    4.字符串类型的条件判断
      4.1 找出first_name 是mark 的  id  first_name salary 显示出来
      select  id,first_name,salary  from s_emp where first_name='mark';  
      sql语句不区分大小写
      字符串的值是区分大小写的
      字符串的值要加单引号    
    5.找出工资 在[1200,1400] 范围内的员工 的id  first_name salary
      where 字段  between  a  and b
      表达闭区间  
      select  id,first_name,salary from s_emp where salary between 1200 and 1400;
    6.sql提供的其它运算符
      6.1 where 字段 between  a  and b 表达一个闭区间
      6.2 where 字段  in (列表)
          列表   值1,值2,值3              
          where  id   in  (1,3,7)
          查询s_emp 表中部门编号  在 31 或者 32 或者 50 部门 的员工的 id first_name 以及部门编号 
          select  id,first_name,dept_id from  s_emp  where dept_id in(31,32,50);
          数据出现概率高的放前面
       6.3  模糊查询
          6.3.1 需求 
          找出所有姓王的人  王王王
                           王宝强
                           王安石                            
          找出所有数据中带龙 
                           李小龙
                           龙孩儿
                           小龙女
          ls  *.txt
          6.3.2  统配符          
          %     代表0-n个任意字符
          _     代表一个任意字符          
          '王%' '%龙%' 统配串            
          6.3.3  模糊查询关键字
          where 字段  like '统配串'
          找出s_emp 表中 first_name 所有带a的
          select  first_name from  s_emp where first_name like  '%a%';
          找出s_emp 表中 first_name 所有倒数第二个 字符是a的  
          select  first_name from  s_emp where first_name like  '%a_';
          6.3.4  特殊的模糊查询
          字符串中 带 %或者_ 的模糊查询
          s_emp  
          s_dept  
          6.3.4.1 找出所有的S 开头的表名
          desc  user_tables;
          其中一个字段 是table_name 
          select  table_name from user_tables where table_name like 'S%';
          找出所有的S_开头的表名  
          select  table_name from user_tables where table_name like 'S\_%'  escape '\';  
          6.3.4.2 找出所有的S__开头的表名       
          select  table_name from user_tables where table_name like 'S\_\_%'  escape '\';   
       6.4  NULL 值的判断
             6.4.1 使用where 字段  is null
             找出提成等于10 的人的 id  first_name和commission_pct 
             select  id,first_name,commission_pct from  s_emp where commission_pct=10;
             找出提成不等于10 的人的 id  first_name和commission_pct
             select  id,first_name,commission_pct from  s_emp where commission_pct!=10;
             6.4.2 判断NULL 使用is  null 
             select  id,first_name,commission_pct from  s_emp  where commission_pct is null;
             6.4.3 找出manager_id 是NULL 的 员工 
             列出id  salary  manager_id
             select  id,salary,manager_id  from s_emp  where manager_id is null;
      7.逻辑条件链接符
        and   连接的条件都为真 则条件为真
        or    只要有一个条件为真 则条件为真
        not   
        7.1 求工资在[800,1200] 的员工  列出 
        id  first_name  salary
        select  id,first_name,salary  from s_emp  where salary>=800 and salary<=1200;
        7.2 求部门号 在 31 或者 32 或者 50
        中的员工的id first_name dept_id
        select id,first_name,dept_id  from s_emp where dept_id=31 or dept_id=32 or  dept_id=50; 
        7.3 not 
        =      !=  <>  ^=  
        <      >= 
        >      <=
        between a and b   not  between a and b  
        in      not in (注意NULL值) 
        like    not like 
        is null is not null        
        找出提成不是NULL 员工 的
        id,first_name,commission_pct   
        select id,first_name,commission_pct from s_emp  where  commission_pct  is not null;  
三.数据排序 
   1.概念
   把数据 按照升序 或者降序 排列显示
   2.order by 排序标准   排序方式 
     2.1 排序方式
     升序 默认的顺序 asc  自然顺序  字典顺序
     降序            desc   
     2.2 出现的位置
     永远出现在sql语句最后
   3.举例
     3.1 查询s_emp 表中  id,first_name,salary
        按照工资排序显示
     select  id,first_name,salary from s_emp
         order by  salary;   
     3.2 查询s_emp 表中  id,first_name,salary
        按照工资降序显示       
     select  id,first_name,salary from s_emp
         order by  salary desc;  
   4.NULL值在排序中的处理
     按照manager_id 排序显示 id,first_name,
     manager_id
     select  id,first_name,manager_id 
         from  s_emp  order by manager_id;
     结论:NULL 在排序中做最大值处理
   5.多字段排序
     5.1 概念
     当第一排序的值相同时  可以启用第二排序字段
     来对数据进行排列
     5.2 举例 
     按照工资排序 如果工资相同 则按照id降序排列
     select  id,first_name,salary from s_emp
         order by salary,id desc;     
   6.总结:
     order by  排序标准  排序方式,第二排序标准  
         排序方式。
四.单行函数
   1.单行函数 和 组函数的概念
   单行函数:对sql语句的每一行数据都返回一个处理
       结果,sql语句影响多少行就返回多少个结果。
   组函数:对sql语句影响的所有数据 统一处理返回
       一个结果,无论sql语句影响多少行 都返回一
       个结果。
   2.举例
    2.1 单行函数   upper
    select   first_name,upper(first_name) 
        from s_emp;  
    2.2 组函数     count
    select   count(first_name) from s_emp;  
    select first_name,count(first_name) 
        from s_emp; 
   3.单行函数的测试
    dual 表  是一张单行 单列的表
    select  upper('hello world') from dual;  
   4.oracle中常见的处理字符串的函数
    4.1 upper(par1) 变大写
    4.2 lower(par1) 变小写
    select  lower('HELLO  World')  from dual;
    4.3 initcap(par1) 把每个单词的首字母变大写
    select  initcap('one world one dream')
        from  dual;
    4.4 length(par1) 求字符串的长度
    select   length('hello') from dual;  
    4.5 concat(par1,par2) 连接字符串   
    用的很少  因为有||
    4.6 substr(par1,par2,par3)
      4.6.1 参数含义
      par1 要处理的字符串
      par2 从什么位置开始截取  默认从1开始编号
         也可以是负数-1 代表最后一个字符的位置
      par3 截取多少个字符
      4.6.2 举例
      把s_emp 表中 first_name 和 first_name
      前三个字符截取下来
      select  first_name,substr(first_name,
      0,3) from s_emp;
      select  first_name,substr(first_name,
      1,3) from s_emp;
      把s_emp 表中 first_name 和 first_name
      后三个字符截取下来
      select  first_name,substr(first_name,
      -3,3) from s_emp;
    4.7 nvl(par1,par2) NULL值处理函数
        par1 和 par2 的类型要一致            
    5.数字处理函数
      5.1 round(par1,par2) 四舍五入
         5.1.1  参数
         par1 要处理的数据 
         par2 指定小数保留的位数 par2可以省略
         5.1.2  举例
         select  round(12.88) from dual;
         select  round(12.88,1) from dual;
         select  round(12.874,2) from dual;
         /* 对小数点前 第几位进行四舍五入 */
         select  round(12.874,-1) from dual;
         select  round(12.874,-2) from dual;         
      5.2 trunc(par1,par2) 截取 
         5.2.1  参数
         par1 要处理的数据 
         par2 指定小数保留的位数 par2可以省略
         5.2.2  举例
         select  trunc(12.88) from dual;  12
         select  trunc(12.88,1) from dual; 12.8
         select  trunc(12.874,2) from dual;12.87
         /* 对小数点前 第几位进行四舍五入 */
         select  trunc(12.874,-1) from dual; 10
         select  trunc(12.874,-2) from dual; 0
    6.数字格式显示函数
      6.1 to_char(par1,par2)
      par1是要处理的数据
      par2 是格式 可以省略 代表把一个数据类型 
           变成字符串类型
      格式以 fm开头
      9      小数点前代表0-9的任意数字 
             小数点后代表1-9的任意数字
             999.99     999.00
             123  123.  123.00
      0      小数点前代表 强制显示前导零 
             12345.67   012,345.67
             小数点后 代表 0-9的任意数字
      $      美元符号
      L      本地货币符号   ¥   RMB
      ,      分隔符号
      .      小数点                      
      6.2    举例  
         6.2.1 以fm$099,999.99 显示s_emp 中的数据
         select salary, to_char(salary,'fm$099,999.99')  from  s_emp;   
         6.2.2 以fmL099,999.99 显示s_emp 中的数据
         select salary, to_char(salary,'fmL099,999.99')  from  s_emp;  
      6.3  如何修改本地语言
         1.进入服务的shell 切换shell
           bash
         2.修改配置文件
           vi  .bash_profile
         3.写入环境变量
         export NLS_LANG
         ='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'
         4.保存退出  让配置生效
           source   .bash_profile    
         5.重新进入sqlplus              
     7.函数嵌套
       7.1 概念
       把一个函数的返回值  作为另一个函数的参数
       7.2 列子
         7.2.1得到s_emp 表中first_name,first_name 的后三个字符(length  substr)
         select first_name, substr(first_name,length(first_name)-2,3) from s_emp;
         7.2.2 把下面的连接改成 concat 的形式
         select  first_name||'_'||last_name from s_emp;
         select  concat(concat(first_name,'_'),last_name) from s_emp;             
         7.2.3 显示s_emp 表中 first_name,
         manager_id  如果manager_id 为NULL 则显示成BOSS
         select  first_name,nvl(to_char(manager_id), 'BOSS') from s_emp;        
 五.多表查询
    1.概念
    查询的数据 分布在多张表中,所以需要根据条件把表连接起来 形成一张表。
    2.列子
    把每个员工的first_name和对应的 部门编号查询出来
    select  first_name,dept_id from s_emp;
    s_dept  部门表
    SQL> desc  s_dept;
    Name                                      Null?    Type
    ----------------------------------------- -------- ----
    ID    部门编号                                    NOT NULL NUMB
    NAME  部门名                                     NOT NULL VARC         
    3.在第二个例子的基础上 显示部门名
       3.1笛卡尔积
       select first_name,dept_id,name from  s_emp,s_dept;     
       笛卡尔积   两张表匹配的所有可能
       3.2 表连接时注意连接
       select first_name,dept_id,name from  s_emp,s_dept where dept_id=s_dept.id; 
       结论:表中有同名字段时 可以使用表名区分  
    4.表连接的练习
      s_dept  
      id         部门编号   
      name       部门名  
      region_id  地区编号      
      s_region
      id         地区编号
      name       地区名 
      列出部门名 和 部门对应的地区名
      select  s_dept.name,s_region.name  from  s_dept,s_region where region_id=s_region.id;    
     5.使用表的别名 对上面程序进行简化
      select  d.name,r.name from  s_dept d,s_region r where region_id=r.id; 
     6.把员工的first_name 和 对应的部门名以及部门对应的地区名 显示出来
        select  e.first_name,d.name,r.name  from  s_emp e,s_dept d,s_region r
        where e.dept_id=d.id  and  d.region_id=r.id; 
        设置name的这一列一行最多显示15个字符        
        col  name  for a15;
     7.上面的连接条件都是用等号作为连接符号则称之为等值连接。
       如果连接两张表的连接符号 不是等号则称之为非等值连接。
       7.1 工资级别表 salgrade
          得到初始化脚本  上传到服务器
          进入sqlplus  执行脚本
          SQL>@路径名/脚本名
          SQL> desc salgrade;
          Name
          --------------------
          GRADE    工资等级
          LOSAL    这个等级低工资
          HISAL    这个等级的高工资 
       7.2 列出每个员工的id,工资 和 工资对应的工资级别。    
        select id,salary,grade  from  s_emp ,salgrade where salary between losal and hisal;
     8.特殊的表连接(自连接)
       把两层业务含义的数据放到了一张表中。
       s_emp  表有普通员工 和  领导
       把s_emp 表中所有的领导查询出来
       id    manager_id 
       9527  9527
       9528  9527
       9529  9527
       有员工的领导id 是你的id 则你是领导
       select id,first_name from s_emp  where manager_id=id;            
 六 表连接的总结
    1.内连接
    等值连接    员工名和对应的部门名
    非等值连接  工资和工资对应的级别
    自连接      谁是领导    
    符合连接条件 数据就被选中 不符合连接条件数据就被过滤掉。这种总称为内连接。
    2.列出每个部门名 和 部门对应的地区名
       select  d.name,r.name from s_dept  d,s_region r where d.region_id=r.id; 
      公司业务发展  增加了新的部门
      insert  into s_dept values(101,'Test1',NULL);
      commit;   
    3.外连接:目的就是为了找回在内连接连接时 丢掉的不符合条件的数据。
      外连接的结果集 等于内连接的结果集加上匹配不上记录。(一个也不能少) 
      (+)  (+)字段对面的表的数据全部被匹配出来
      select  d.name,r.name  from s_dept  d,s_region r where d.region_id=r.id(+);
    4.列出所有的员工id first_name和员工对应部门名
    select  e.id,e.first_name,d.name   from  s_emp e,s_dept d where e.dept_id=d.id; 
    把老板开除即 把老板的dept_id 变成NULL
    update  s_emp set dept_id=NULL where id=1;
    commit; 
    列出所有员工 包括没有部门的员工
    select  e.id,e.first_name,d.name   from  s_emp e,s_dept d where d.id(+)=e.dept_id;
    5.思考如何使用外连接找出所有的普通员工
      列出id 和first_name 
    /* 找回过滤掉的员工 */  
    select distinct  m.id,m.first_name   from  s_emp  e,s_emp m  where e.manager_id(+)=m.id;
   /* 过滤掉的哪部分员工就是假领导 */   
    select distinct  m.id,m.first_name    from  s_emp  e,s_emp m where e.manager_id(+)=m.id and   e.manager_id is null;
    6.列出员工的id  salary   和 工资对应的工资级别
        select  id,salary,grade from  s_emp,salgrade where salary between losal and hisal;         
        /*给老板涨工资*/
     update  s_emp  set salary=12500 where id=25;
     commit;     
      select  id,salary,grade from  s_emp,salgrade where salary between  losal(+) and hisal(+);    
 七.(+) 是oracle的外连接
    SQL99 sql标准委员会 规定了内外连接的标准
    7.1 SQL99内连接:
    from a表  join  b 表  on 连接条件;
    from a表  inner join  b 表  on 连接条件;  
    from  a表 ,b 表
        where  连接条件;
    列出每个员工的first_name 和对应的部门名
     select first_name,d.name from  s_emp e,s_dept d where e.dept_id=d.id;
     select first_name,d.name from  s_emp e join s_dept d on e.dept_id=d.id;    
    7.2 SQL99的外连接 
    from  a表 left outer join b表  on 连接条件;
    from  a表 right outer join b表 on 连接条件;
    from  a表 full outer join b表  on 连接条件; 
    多表查询
表连接:
    内连接:在表连接时  符合连接条件的数据 就被选中,不符合连接条件的就被过滤掉。
        等值连接:员工  部门   地区
        非等值连接:员工工资 和 工资级别
        自连接:谁是领导           
    外连接:外连接的结果集 等于内连接的结果集 加上匹配不上的记录。
        (+) (+)字段对面表的数据全部被匹配出来 
        等值连接:员工  部门   地区
        非等值连接:员工工资 和 工资级别
        自连接:谁是领导 
一.SQL99 中的内外连接
   1.sql99中内连接
   from  a 表  join  b表  on  连接条件; 
   from  a 表  inner join  b表  on  连接条件;
   2.把每个部门名 和对应的地区名显示出来
     s_dept
     s_region 
      select d.name,r.name from  s_dept d,s_region r where d.region_id=r.id;        
      select d.name,r.name from  s_dept d join s_region r on d.region_id=r.id; 
   3.sql99 中的外连接
     3.1把每个部门名 和对应的地区名显示出来 
     即使没有对应的地区名 也要显示出这个部门
     select d.name,r.name from  s_dept d,s_region r
      where d.region_id=r.id(+);
     3.2 语法
     from  a表 left outer join b 表 on 连接条件;
     from  a表 right outer join b 表 on 连接条件;           
     要把a表的数据全部匹配出来 就让a表发起连接。 
     select d.name,r.name from s_dept d left outer join s_region r
     on d.region_id=r.id; 
     select d.name,r.name from s_region r right outer join s_dept d 
     on d.region_id=r.id;                
     3.3 谁是普通员工?
     (+) 实现之后  再使用left outer join 实现
     select  distinct m.id,m.first_name  from  s_emp  e,s_emp m
     where  e.manager_id(+)=m.id and  e.manager_id is null; 
     select  distinct m.id,m.first_name from  s_emp  m left outer join s_emp e
     on  e.manager_id=m.id where  e.manager_id is null; 
     3.4 全外连接:全外连接的结果集 等于左外连接的
         结果集 加上右外连接结果集 减去重复的记录。
         a 表 full outer join b表 on 连接条件;
         oracle 中不是通过两端都加(+) 
         union       合并两个结果集 排重
         union  all  合并两个结果集
         select id from s_emp  union select id from s_emp;
         select id from s_emp  union   all select id from s_emp;
二.  组函数
   1. 特点就是对一组数据处理之后 得到一个结果。                                             
   2. 常见的组函数
      count  统计数据个数
      max    统计最大值    
      min    统计最小值
      avg    统计平均值
      sum    统计和
   3. 统计 s_emp 表中的人数  统计工资的最大值和 工资的最小值
      select  count(id),max(salary),min(salary)  from s_emp;   
   4. 统计s_emp  中工资的平均值 和工资的和 
      select   avg(salary),sum(salary), sum(distinct salary) from  s_emp;  
      组函数中可以使用 distinct
   5. 组函数对NULL值的处理 是忽略的
      统计s_emp  表中提成的个数  和 提成的和
      commission_pct select  count(commission_pct), sum(commission_pct) from  s_emp;
三. 分组
   1.概念
   按照一定的标准  把数据分成若干组
   2.group  by  分组标准 (用在where后)
   select  dept_id,count(id) from  s_emp 
   where 1=1  group by  dept_id;      
   3.按照部门号分组,统计每个部门的人数
     能不能把部门名显示出来?
   select  dept_id,count(s_emp.id),max(name) from  s_emp,s_dept 
   where  dept_id=s_dept.id group by  dept_id;    
   在分组语句中  select 后的字段要么是分组标准
   要么是经过合适的组函数处理过的。 
   select  dept_id,count(s_emp.id),name from  s_emp,s_dept 
   where  dept_id=s_dept.id group by  dept_id,name;
   4.对组数据的过滤  having 
     按照部门号分组,统计每个部门的平均工资
     要求显示工资大于 1500
     select  dept_id,avg(salary) asal from  s_emp 
     where  asal>1500 group by  dept_id; /* error */    
         from 
             where 
                 group by
     select  dept_id,avg(salary) asal from  s_emp 
     group by  dept_id having  asal>1500;  /* error */
          from 
             where 
                 group by
                     having 
                         select
                             order by        
    select  dept_id,avg(salary) asal from  s_emp group by  dept_id
    having  avg(salary)>1500 order by asal; 
   5.按照部门号 分组  求每个部门的人数
     要求显示人数大于1的部门 
     要求按照部门号排序
     要求显示部门名
   select  dept_id,count(e.id),max(d.name)  from  s_emp e,s_dept d 
   where  e.dept_id=d.id group  by  dept_id having  count(e.id)>1 order by dept_id;
 四.子查询
    4.1 概念
    把一个查询的结果 作为另一个查询的基础
    4.2 举例
    /* 找出所有的领导id */
    select distinct manager_id from s_emp;
    /* 让员工的id出现在领导id中 */
    select id,first_name from  s_emp where id in( select distinct 
    manager_id from s_emp );
    /* 使用子查询找出所有的普通员工? 
       注意NULL */  
    select id,first_name from  s_emp where id not in(
    select distinct  manager_id from s_emp where manager_id  is not NULL);   
    commission_pct=10   2
    commission_pct!=10 or  commission is null  
    
    4.3 子查询 还可以用在 having 之后
       求平均工资大于 41部门平均工资的
       select  avg(salary) from  s_emp where dept_id=41;//1510           
       select  dept_id,avg(salary) from  s_emp group by dept_id
       having  avg(salary)>(select   avg(salary) from  s_emp where  dept_id=41);    
    4.4 子查询 用在 from 后面
       任何一条sql语句 都对应内存中的一张表
       select id,first_name name,salary from s_emp;   
       select id,name from ( select id, first_name name,salary from s_emp ) where id>10;         
       求平均工资大于 41部门平均工资的
       select*from(select dept_id,avg(salary) asal from s_emp group by dept_id) where 
         asal>(select   avg(salary)from s_emp where dept_id=41);
 五.表的操作
    5.1 如何建立表
    create table  表名(
        字段名    类型,
        字段名    类型,
        字段名    类型 
    ); 
    5.2 建立一张员工表 myemp
        id        number
        name      varchar2(30)
        salary    number
    drop table  myemp;
    create  table myemp(
        id        number,
        name      varchar2(30),
        salary    number
    );    
    5.3 删除表
        drop table  表名;
        drop table  myemp;             
    5.4 建立一张订单表 myorder123
        id     number
        name   varchar2(50)
        money  number
        odate  date
        drop   table  myorder9526;
        create table  myorder9526(
            id     number,
            name   varchar2(50),
            money  number,
            odate  date
        );  
        desc  myorder9526;          
 六.对表中数据的操作
       create table  myorder19527(
            id     number,
            name   varchar2(50),
            money  number,
            odate  date
        ); 
    6.1.增加数据  insert 
      6.1.1 insert into 表名 values(字段值1,字段值2,字段值3);
          insert into myorder19527 values(1,'test1',1888.88,NULL);
      6.1.2 insert into 表名(字段名1,字段名3) values(字段值1,字段值3);
          选择部分字段插入数据 必须包含所有的非空字段。
          没有选择的字段当做NULL值插入数据库
          insert into myorder19527(id) values(1001); 
      6.1.3 向s_dept 表中放入数据
          insert into  s_dept values(100,'test', NULL);     
     6.2 删除数据 delete
         delete   from  表名 where 条件;        
         delete   from  myorder19527  where id=1001;           
     6.3 修改数据 update
         update   表名  set  字段名=值, 字段名2=值2 where  条件;
         update   myorderbdl  set id=9527 ,name='zhouxingxing' where id=1;          
         commit; 
               
      create table  myorderbdl(
            id     number,
            name   varchar2(50),
            money  number,
            odate  date
        ); 
      insert into myorderbdl values( 1,'test1',1888.88,NULL);
      commit;               
 
 七.数据库中的事务操作
    原子性:一个事务中sql语句,是不可分隔的整体。
        转账
        update  account set money=money-20000
            where   ano='A';
        a 
        update  account set money=money+20000
            where   ano='B';
        b
        if(a&&b){
           /* 确认这次操作 */
           commit; 
        }else{
           /* 撤销这次操作 */
           rollback;
        }              
    隔离性:一个事务中的操作 在没有提交以前
        数据的变化 不能被另一个事务发现数据
        的变化。
        update s_emp set salary=salary+2000  where id=1;
        insert  delete  update 是有事务操作的
        select 没有事务可言
        create  drop  事务自动提交    
    持久性
    一致性
    事务的补充:
        事务中的语句一起成功 一起失败太严格
        部分成功 部分失败
        update  account  set  money=money-0.1 where ano='1581100****';
        savepoint  a;
        insert  into   logtable values();
        发送短信
        savepoint  b;
        update   logtable
        savepoint  c;
        if(a&& b&& c){
           commit;
        }else{
           rollback to b; 
           commit;           
        }        
        update  account ...;
        savepoint  a;
        insert  into  ....;
        savepoint  b;
        update  account ... ;
        rollback  to a;
        commit;               
 八.日期类型的操作
    8.1 日期的默认格式
        'dd-MON-yy'  
        '23-DEC-13'
        '23-12月-13'
        select start_date from s_emp;         
    8.2 四位年
        按照入职日期排序 显示 id first_name
        start_date        
        select  id,first_name,start_date from s_emp order by start_date;
        to_char(日期数据,'日期格式')
        yyyy    四位年
        mm      两位月 
        dd      两位天
        hh      12小时制
        hh24    24小时制
        mi      分钟
        ss      秒 
        
        MON     月的英文缩写
        month   月的英文全写
        pm      am    pm
        day     星期几   
        select  id,first_name, to_char(start_date,
        'yyyy-mm-dd hh24:mi:ss') from s_emp order by start_date;
        select  id,first_name,  to_char(start_date,
        'yyyy-mm-dd hh24:mi:ss mon day pm') from s_emp order by start_date;      
    8.3 如何插入日期
       建立一张订单表  myorder1112
       id       varchar2(50)
       name     varchar2(50)
       money    number
       odate    date
       create  table  myorder1112(
           id   varchar2(50),
           name varchar2(50),
           money number,
           odate date
       ); 
       insert  into myorder1112 values('bj001','bjolp00001',280000,'08-AUG-08');
       select to_char(odate,'yyyy-mm-dd hh24:mi:ss') from  myorder1112; 
       默认无法放入时分秒信息 默认是00:00:00       
    8.4  to_date(par1,par2)
       par1 要处理的日期字符串
       par2 日期字符串的格式
       '2008-08-08 20:08:08' 
       'yyyy-mm-dd hh24:mi:ss'  
       insert  into myorder1112 values( 'bj002','bjolp00002',290000,
       to_date('2008-08-08 20:08:08', 'yyyy-mm-dd hh24:mi:ss'));
       '2012-12-20  23:59:59'
   
八.日期类型的操作
    8.1 日期的默认格式
        'dd-MON-yy'  
        '23-DEC-13'
        '23-12月-13'
        select start_date from s_emp;         
    8.2 四位年
        按照入职日期排序 显示 id first_name
        start_date
        
        select  id,first_name,start_date from s_emp order by start_date;
        to_char(日期数据,'日期格式')
        yyyy    四位年
        mm      两位月 
        dd      两位天
        hh      12小时制
        hh24    24小时制
        mi      分钟
        ss      秒 
        
        MON     月的英文缩写
        month   月的英文全写
        pm      am    pm
        day     星期几   
        select  id,first_name, to_char(start_date, 'yyyy-mm-dd hh24:mi:ss') from s_emp order by start_date;
        select  id,first_name, to_char(start_date, 'yyyy-mm-dd hh24:mi:ss mon day pm') from s_emp order by start_date;    
    
    8.3 如何插入日期
       建立一张订单表  myorder1112
       id       varchar2(50)
       name     varchar2(50)
       money    number
       odate    date
       create  table  myorder1112(
           id   varchar2(50),
           name varchar2(50),
           money number,
           odate date
       ); 
       insert  into myorder1112 values( 'bj001','bjolp00001',280000,'08-AUG-08');
       select to_char(odate,'yyyy-mm-dd hh24:mi:ss') from  myorder1112; 
       默认无法放入时分秒信息 默认是00:00:00
       
    8.4  to_date(par1,par2)
       par1 要处理的日期字符串
       par2 日期字符串的格式
       '2008-08-08 20:08:08' 
       'yyyy-mm-dd hh24:mi:ss'  
       insert  into myorder1112 values( 'bj002','bjolp00002',290000, to_date('2008-08-08 20:08:08', 'yyyy-mm-dd hh24:mi:ss'));      
       '2012-12-20  23:59:59'
       to_date('2012-12-20  23:59:59', 'yyyy-mm-dd  hh24:mi:ss')  
    8.5 代表系统时间的函数
        sysdate
        select  to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual;
        insert into  myorder1112 values( 'bj0001','bjtest',18888,sysdate); 
        select  to_char(odate,'yyyy-mm-dd hh24:mi:ss')  from   myorder1112; 
    8.6 日期的调整
        8.6.1 按照天进行调整
        select  to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
        to_char(sysdate+8, 'yyyy-mm-dd hh24:mi:ss') from dual;
        8.6.2 按照小时为单位进行调整   
        select  to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
        to_char(sysdate+1/24, 'yyyy-mm-dd hh24:mi:ss') from dual;
        8.6.3 按照分钟 秒为单位调整
        select  to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
        to_char(sysdate+31/(24*60), 'yyyy-mm-dd hh24:mi:ss') from dual; 
        
        select  to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
        to_char(sysdate-1/(24*60*60), 'yyyy-mm-dd hh24:mi:ss') from dual;
        
        8.6.4  按照月为单位进行调整
        add_months(par1,par2)
        par1要调整的日期
        par2 要调整几个月 正数向后调整 负数向前调
        select to_char(add_months(sysdate,-2),
        'yyyy-mm-dd hh24:mi:ss')
        from dual; 
        8.6.5  得到一个日期对应月的最后一天
        last_day(par1) 
        select  to_char(last_day(sysdate),
        'yyyy-mm-dd hh24:mi:ss') from dual; 
        
        8.6.6 下一个星期几 
        next_day(par1,par2)
        par1 要处理的日期
        par2 星期几
        
        select next_day(sysdate,'monday') from dual;
        select next_day(sysdate,'friday') from dual;  
        select next_day(next_day(sysdate, 'friday'),'friday') from dual;
        
        8.6.7 日期的其它处理
        8.6.7.1 round(par1,par2)
        par1 要进行四舍五入的日期
        par2 按照什么单位进行四舍五入 默认是dd
        select  to_char(round(sysdate), 'yyyy-mm-dd hh24:mi:ss') from dual;
        select  to_char(round(sysdate,'mm'), 'yyyy-mm-dd hh24:mi:ss') from dual;
        
        8.6.7.2 trunc(par1,par2) 
        par1 要进行截取的日期
        par2 按照什么单位进行截取 默认是dd
        select  to_char(trunc(sysdate), 'yyyy-mm-dd hh24:mi:ss') from dual;
        select  to_char(trunc(sysdate,'mm'), 'yyyy-mm-dd hh24:mi:ss') from dual;     
 ---------------------------------------------       
   日期综合练习
   给定一个日期  得到这个日期对应月的最后一天
   最后一秒  使用 to_char做验证
   sysdate     2013-12-31 23:59:59
   2008-08-08  2008-08-31 23:59:59
   select to_char(trunc(last_day(sysdate)) +1-1/(24*60*60),'yyyy-mm-dd hh24:mi:ss') from  dual;       
   trunc(add_months(sysdate,1),'mm')-1/(24*60*60)      
   select to_char(trunc(add_months(sysdate,1),'mm') -1/(24*60*60),'yyyy-mm-dd hh24:mi:ss') from  dual;   
   last_day(trunc(sysdate,'mm'))+1-1/(24*60*60) 
 -------------------------------------------------
 
 九.数据库中的约束
    9.1 概念
    对表中的字段 加的一些限制
    9.2 约束的具体种类
      9.2.1主键约束   primary key
      字段的值必须非空 并且不能重复  
      一个表只能有一个主键
      9.2.2 唯一性约束   unique
      代表值不能重复
      9.2.3 非空约束     not null
      字段的值不能是NULL值
      9.2.4 检查约束     check
      字段的值必须符合检查条件  否则报错
      9.2.5 外键约束     references 
                         foreign key
     9.3 约束的实现方式
        9.3.1 列级约束
          在定义表的某一列时 直接在这一列的后面
          加约束限制。
          9.3.1.1 主键的列级约束
          create table  test_columncons(
              id   number primary key,
              name  varchar2(30)
          ); 
          insert into test_columncons values(1,'test');
          ERROR at line 1:
          ORA-00001: unique constraint 
          (OPENLAB.SYS_C00393099) violated 
          如果不给约束起名字 则系统会自动提供
          一个约束名。
          9.3.1.2 给约束起名字
           drop   table   test_columncons;
           create table  test_columncons(
              id   number constraint
              test_columncons_id_pk primary key,
              name  varchar2(30)
           ); 
          insert into test_columncons values(1,'test'); 
          ERROR at line 1:
          ORA-00001: unique constraint 
          (OPENLAB.TEST_COLUMNCONS_ID_PK) violated
         9.3.1.3 使用列级约束 完成一张表
           要求表有三个字段  id   number
           要求设置成主键    name  varchar2(30)
           要求设置成唯一    sname varchar2(30)
           要求设置成非空 
           create table  test_columncons(
              id   number        constraint
              test_columncons_id_pk primary key,
              name  varchar2(30)  constraint
              test_columncons_name_uk unique,
              sname  varchar2(30) constraint 
              test_columncons_sname_nn not null 
           );
         9.3.1.4 使用列级约束 建立一张表 有两个字段
         id    number  设置成主键salary  number 要求符合检查条件工资大于3500
         create table testemp1007(
             id   number  constraint 
             testemp1007_id_pk  primary  key,
             salary  number  constraint 
             testemp1007_salary_ck 
             check(salary>3500)
         );  
         insert  into  testemp1007 values(
         1,3501);  
                     
        9.3.2 表级约束
        在定义完表的所有列之后  再选择某些列加约束限制。
        表级约束可以完成联合约束    
        create table testemp1008(
           id   number,
           name varchar2(30),
           salary number,
           constraint  testemp1008_id_pk
           primary key(id),
           constraint  testemp1008_name_uk
           unique(name),
           constraint  testemp1008_salary_ck
           check(salary>3500)
        );   
        在数据库层面上 没有联合非空的需求导致非空没有表级别的形式
        id   name
        1     a
        1     c                      
                           
     9.4 外键约束
         9.4.1 概念
         一个表的一个字段的值 要参考或者引用另一张表的字段的值。子表中的外键字段值要么取NULL 要么是父表字段对应的值。                 
         9.4.2 实现
         create table   parent191(
             id    number constraint 
             parent191_id_pk  primary key,
             name  varchar2(30) 
         );                                  
         create  table  child191(
             id   number constraint 
             child191_id_pk   primary key,
             name  varchar2(30),
             fid   number  constraint 
             child191_fid_fk  references
             parent191(id)
         );                                   
         9.4.3 外键中的一些规则
            a.建立表 一般先建立父表 后建立子表。先不考虑主外键就可以先建立子表。
            b.插入数据 一般先插入父表数据后插入子表数据,除非子表的外键值是NULL
              insert into  child191 values(1,'test',1);                   
              ORA-02291: integrity constraint
              insert into  parent191 values(1,'test1'); 
              insert into  parent191 values(2,'test2'); 
               insert into  child191 values(2,'test2',NULL);        
            c.删除数据 
              先删除子表中关联的数据 再删除父表
              中的数据。除非使用了级联。
            d.删除表?
              先删子表 后删子表
              drop  table parent191 cascade
              constraints; 
              
          9.4.4 用外键实现一个关系
             一个部门中可以有多个员工
             一个员工只能属于一个部门
             1:m
             mydept
             id     number
             name   varchar2(30)
               
             myemp
             id    number
             name  varchar2(30)
             dept_id number
                
             drop table  mydept1 cascade constraints;
             drop table  myemp1  cascade constraints;
             create table mydept1(
                 id   number constraint 
                 mydept1_id_pk  primary key,
                 name  varchar2(30)
             );
             insert into mydept1 values(1,'test');
             insert into mydept1 values(2,'app'); 
             commit;
             create table myemp1(
                 id   number constraint 
                 myemp1_id_pk  primary key,
                 name  varchar2(30),
                 dept_id   number constraint 
                 myemp1_dept_id_fk references
                 mydept1(id) 
             );
             insert into myemp1 values(1,'x',1);
             insert into myemp1 values(2,'y',1);
             insert into myemp1 values(3,'z',1);
             insert into myemp1 values(4,'m',2);
             insert into myemp1 values(5,'n',2); 
             commit; 
             
         9.5 级联 
             on delete  cascade   级联删除
             on delete  set null  级联置空
             
             drop table  mydept1 cascade constraints;
             drop table  myemp1  cascade constraints;
             create table mydept1(
                 id   number constraint 
                 mydept1_id_pk  primary key,
                 name  varchar2(30)
             );
             insert into mydept1 values(1,'test');
             insert into mydept1 values(2,'app'); 
             commit;
             create table myemp1(
                 id   number constraint 
                 myemp1_id_pk  primary key,
                 name  varchar2(30),
                 dept_id   number constraint 
                 myemp1_dept_id_fk references
                 mydept1(id) on delete set null
             );
             insert into myemp1 values(1,'x',1);
             insert into myemp1 values(2,'y',1);
             insert into myemp1 values(3,'z',1);
             insert into myemp1 values(4,'m',2);
             insert into myemp1 values(5,'n',2); 
             commit; 
       9.6  把上面的例子改成 表级约束的外键约束
             drop table  mydept1 cascade constraints;
             drop table  myemp1  cascade constraints;
             create table mydept1(
                 id   number constraint 
                 mydept1_id_pk  primary key,
                 name  varchar2(30)
             );
             insert into mydept1 values(1,'test');
             insert into mydept1 values(2,'app'); 
             commit;
             create table myemp1(
                 id   number constraint 
                 myemp1_id_pk  primary key,
                 name  varchar2(30),
                 dept_id   number,
                 constraint 
                 myemp1_dept_id_fk 
                 foreign key(dept_id)
                 references mydept1(id)  
                 on delete set null
             );
             insert into myemp1 values(1,'x',1);
             insert into myemp1 values(2,'y',1);
             insert into myemp1 values(3,'z',1);
             insert into myemp1 values(4,'m',2);
             insert into myemp1 values(5,'n',2); 
             commit; 
             
 --------------------------------
    约束:
    具体的约束种类
    主键    primary key
    唯一    unique
    非空    not null
    检查    check
    外键    references    foreign key
            on delete cascade
            on delete set null
    列级约束:在定义表的某一列时 直接在这一列
        后面加约束限制。            
    表级约束:在定义完表的所有列之后 再选择某些
        列加约束限制。
        
    外键约束:
        1.建立表  先建立父表后建立子表
        除非使用修改表结构 alter table add 
        constraint
        2.插入数据先插入 父表数据
          除非子表的外键值是NULL
        3.删除数据 
          先删除子表中关联的数据 
          再删除父表数据
          除非使用了级联  
          on delete cascade
          on delete set null
        4.删除表
          一般先删除子表 后删除父表
          除非使用 drop table 表 
          cascade constrints                  
 ------------------------------
 十.数据库中的其它对象
    10.1  序列
       10.1.1  作用
       用来产生主键的值
       10.1.2   如何创建序列
       create  sequence  序列名;
       create  sequence  myemp1001_id;
       CREATE SEQUENCE myemp1001_id
       MINVALUE 1   
       MAXVALUE 9999999   
       INCREMENT BY 1
       START WITH 51
       NOCACHE
       NOORDER
       NOCYCLE; 
       10.1.3   使用序列
       drop    table  myemp1001;
       create  table  myemp1001(
           id    number  primary  key,
           name  varchar2(30)
       );
       insert into  myemp1001  values(
           myemp1001_id.nextval,
           'test'||myemp1001_id.currval
       );
       10.1.4  删除序列
       drop  sequence  序列名; 
       drop  sequence  myemp1001_id; 
    
    10.2  索引
       10.2.1  作用
       加速查询
       10.2.2  如何实现底层通过树状结构组织数据 配合消耗空间和消耗时间 来达到加速查询的目的。       
       3亿条     8分钟
       使用索引  0.01秒 0.00
       10.2.3  如何创建索引
          数据库管理系统 会自动为 唯一性字段建立
          索引。
          create  index  索引名  on 表(字段);          
          set timing on;
          drop    table  copyemp;  
          create  table  copyemp as select *from s_emp;
          create  index  copyemp_salary_ind on  copyemp(salary);
       10.2.4  删除索引
          drop   index   copyemp_start_date_ind12;
          create  index  copyemp_start_date_ind12 on  copyemp(start_date);
    10.3  视图
       10.3.1  视图的本质
       就是一条sql语句 
       10.3.2  如何创建一个视图
       create or replace view  视图名  as select 语句;       
       create  or replace  view  myview as select id,first_name from s_emp;       
       select * from  myview;
       作用可以简化查询可以对同一份物理数据做不同的表现
       10.3.3  删除视图
       drop view  myview;
 
 十一. 分页技术
     oracle 中的分页技术  rownum
     mysql                limit  m,n
     sqlserver            top    n      
     select  id,first_name,salary from s_emp;
     select  rownum,first_name,salary from s_emp;
     一页显示10条  要第一页数据
      select  rownum,first_name, salary from s_emp where rownum<11; 
     一页显示10条  要第二页数据  
     select  rownum,first_name, salary from s_emp where rownum<21 and rownum>10;            
     select * from(select  rownum r,first_name, salary from s_emp where rownum<21) where r>10;         
     按照工资排序 每页显示10条  显示第二页数据  先排序 还是先编号? 先排序 后编号
     select*from(select rownum r,first_name,salary  from(select  first_name,salary
     from s_emp order by salary) where rownum<2*10+1) where r>(2-1)*10;     
     最内层select  完成数据的排序
     第二层select  完成数据的编号
     第三层select  完成rownum 特性的去除
     按照工资排序 每页显示10条  显示第三页数据 
     select*from(select rownum r,first_name,salary  from(select  first_name,salary
     from s_emp order by salary) where rownum<3*10+1) where r>(3-1)*10;
   

你可能感兴趣的:(数据库和存储过程)