美文网首页我爱编程
DB学习之Oracle(一)

DB学习之Oracle(一)

作者: lvvl | 来源:发表于2016-04-18 00:13 被阅读192次

    一:数据库的基本环境

    1)Oracle数据库
        Oracle甲骨文公司 Orcale DBMS
        在DB中创建表table来保存数据
        管理思路:通过系统表  来管理 用户表
            (系统表)           (用户表)
            user_tables         s_emp  s_dept  stu  emp…
            user_constraints        管理约束
            user_sequences      管理序列
            …
            也称为:数据字典  DD
            DBA关注           程序员关注
        Oracle DBMS是一种多用户的管理系统:涉及多线程并发安全问题,采用了锁机制
    
        1.1系统表:user_tables管理所有用户表(表名全部大写存储)
            思路:    我们创建一张新的表,DBMS就会在系统表 添加一条记录,记载新表的信息(好比注册表)
                desc user_tables;   第一个字段:table_name    表名
                select table_name from user_tables;
                    - - -查询出当前数据库中有哪些用户表?
                S_SALGRADE  表名使用大写字母保存
                S_REGION
                S_EMP
                S_DEPT
            注意:oracle中值的比较是 区分大小的
        1.2虚表dual
            特点:单行单列的表
        1.3数据库习惯使用下划线分隔:s_emp  s_dept  dept_id  first_name
                用下划线的原因:全部大写保存时无法区分每个单词(oracle中是以大写保存的)
            java标识符:类名      HelloWorld  NullPointException
                    变量名     firstName
                    常量名     MAX_VALUE
                java有时不用_命名的原因:区分大小写  驼峰式  能区分每个单词
    2)如果访问Oracle数据库?    sqlplus工具   自带小软件
        使用sqlplus工具,发送并执行sql语句
        方式:cmd控制台(2种方法,第一种更安全)
            1)D:\> sqlplus
                输入用户名   system  
                密码  1234(以实际密码为准,不回显)
            2)D:\> sqlplus  system/1234
        只要看到提示符变为SQL> 说明登录成功
            
        如果sqlplus命令找不到(不是内部外部命令)
            需要修改系统环境变量Path  命令的搜索路径
            需要将sqlplus命令所在路径名,追回到Path中
                C:\oracle\product\10.1.0\db_1\bin
    
            右击我的电脑-》系统属性-》高级
            -》环境变量-》系统变量-》双击Path
            -》在变量值框中  enter跳到最后(加到最后,防止冲突),加个;号,在粘贴刚才拷贝的bin路径,
            -》关闭cmd窗口-》一定要重新启动cmd才可生效
        远程登录服务器
            cdm-》任何盘符下,telnet  主机名(比如像192.168.0.23)
            -》回车-》login:openlab
            -》回车-》Passoword:1234
            -》……..
            -》sun280%  sqlplus
            -》回车-》Enter user-name:openab
            -》回车-》Enter password:
            -》SQL>
            …….
            -》sun280%  exit
        下载: submit_me.sql       脚本  中文版(目前使用,本地安装了Oracle数据库)
                 submit_1.sql       英文版   备用(运程连接,同一台服务器中的Orcale数据库)
            s_emp_er.emf    E_R图       看熟
                .emf    矢量图     缩放不会失真  专业文档中
                .bmp    位图      缩放会失真
    创建4张表:
    s_emp           员工表
    s_dept      部门表
    s_region        区域表
    s_salgrade      薪水级别表
    

    二: Oracle 中常见的数据类型

    1、数值类型
        整数  number(n)       n表示整数最大位数
            number(8)       最多8位整数  99999999
        小数  number(m, n)    表示m位有效数位,n位小数
            number(8, 2)        8位有效数位,2位小数
                999999.99
            有效数位:从左边第1个非0数字开始,后面的都算
                100.05  5位有效数位,2位小数 
                0.0005  1位有效数位,4位小数 
                number(2, 4)        2位有效数位,4位小数 
                    0.0010  0.0099
    2、字符型
        定长:     char(n)     固定分配n个字符空间
        可变长:    varchar2(n)     可变长的字符串,最多n个字符
                            优化的类型  IBM  DB2也有这种类型, 向下兼容varchar(n)
                varchar(n)      旧版本
    3、日期型   date
        信息:世纪、年、月、日、时、分、秒
            使用sysdate查询系统当前时间:
                select sysdate from dual;
    

    三:sqlplus工具的使用

    可以执行两类命令:sqlplus命令、sql命令
    1、sqlplus环境的基本命令
        1)查看表结构
            sqlserver:使用存储过程    sp_help  表名
            oracle:使用sqlplus命令  describe  表名    (描述)
                    简写成:    desc         表名
                desc可以确定表是否存在,也可以查看表结构
        2)设置sqlplus的显示格式
            show linesize;      显示一行的   字符宽度        默认是80个字符
            set linesize 300;   设置一行的字符宽度       
        3)清空屏幕信息:
            clear screen
           win cmd清屏:cls
    2、SQL命令:数据库业内有标准的
        1)DDL   数据库定义语言 定义结构
            create drop alter
        2)DML   数据库操纵语言 操纵表中的数据
            insert delete update select
        3)TCL   事务控制语言 Transation
            commit  rollback  savepoint
        4) DCL  数据库控制语言 授权和回收       DBA来执行
            grant 授权    revoke 回收
            针对某个用户进行授权操作
            比如针对数据库、表设置操作权限:只读  读/写
    

    四:Oracle基本SQL

    1、函数:
        函数总结:
            单行函数:
                1.字符函数  length()    lower() upper() substr()
                2.数值函数  round() trunc() abs()
                3.日期函数  sysdate to_char()   to_date()   add_months()    last_day()  trunc()
                4.其它函数  nvl()
            多行函数:
                sum()   avg()   count() max()   min()
        单行函数:每条记录只返回一个结果
            1)字符处理函数    char    varchar2    varchar
                oracle  函数              java方法
                 length()       字符串长度       length()
                 lower()        大写转小写       toLowerCase()
                 upper()        小写转大写       toUpperCase()
                 substr()       求子串         substring()
                substr(处理的字符串,开始位置,截取字符数)
                    开始位置:
                        正数n:从左往右,第n个位置开始截取
                        负数-n: 从右往左,倒数第n个位置开始截取
                    数据库从1开始索引,java等开发语言从0开始索引
                查询44号部门的员工名字(原样,全大写,全小写)
                    select first_name,upper(first_name),lower(first_name) 
                    from s_emp 
                    where dept_id=44;
                经常用dual虚表(单行单列的表)测函数    
                    select lower(‘ABC’) from dual;
                    select length(‘ABC’) from dual;
                求每条记录first_name最后两个字符
                    select first_name,substr(first_name,-2,2) subs from s_emp;
                    select first_name,substr(first_name,length(first_name)-1,2) subs                        from s_emp;
            2)数值处理函数    number
                round() 四舍五入
                    select round(45.926,2) from dual;   45.93
                    select round(45.926,0) from dual;   46
                    select round(45.926,-1) from dual;  50
                    select round(45.926,-2) from dual;  0
                trunc() 截取(不考虑四舍五入,只考虑舍去,第2个参数为正数时,从小数点后几位开始截取,负数,从小数点前几位开始截取)
                    select trunc(45.926,2) from dual;   45.92
                    select trunc(45.926,0) from dual;   45
                    select trunc(45.926,-1) from dual;  40
                    select trunc(45.926,-2) from dual;  0
                abs()   绝对值
            3)日期处理函数    date
                3.0 日期类型中最常用的函数
                    sysdate 获取当前系统时间
                        sysdate+n   当前时间+n天
                    to_char()   date->char
                    to_date()   char->date
                    add_months(d1,n)    d1日期,在加n个月
                        select add_months(sysdate,2) from dual;
                        select add_months(sysdate,-2) from dual;    减2个月
                    last_day(sysdate)   sysdate对应用的最后1天,时分秒和sysdate日期的时分秒一致
                        select last_day(sysdate) from dual;
                    trunc(sysdate,’yyyy’)   针对sysdate对应的年份截取,年份以后全是初始值(当年第1月)
                    trunc(sysdate,’mm’)     针对sysdate对应的月份截取,月份以后全是初始值(当月的第1天)
                    trunc(sysdate)      针对sysdate对应的日期截取,日期以后全是初始值(当天的第0点)
                        trunc(sysdate,’dd’)     针对sysdate对应的日期截取,日期以后全是初始值(当天的第0点)
                    trunc(sysdate,’DAY’)    针对sysdate对应的周截取,回到当前周的第一天(周日)
                    trunc(sysdate,’hh’)     针对sysdate对应的小时截取,小时以后全是初始值(当时的第0分)
                    trunc(sysdate,’mi’)     针对sysdate对应的分钟截取,分钟以后全是初始值(当分的第0秒)
                    下个月第1天的0点
                        select trunc(add_months(sysdate,1),’mm’) from dual;     本月+1
                        select trunc(last_day(sysdate)+1) from dual;            回到本月最后1天,+1
                3.1常用的日期格式:
                      标准的日期格式:
                        yyyy mm dd hh24:mi:ss   
                        yyyy-mm-dd  hh24:mi:ss
                      默认的日期格式:
                        DD-MON-RR
                        日   月    年
                3.2查询系统当前时间
                    select sysdate from dual;
                3.3修改当前日期格式             
                    alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
                        NLS 区域语言支持
                        national  language support
                3.4对日期类型数据进行运算
                    加/减 1      单位:天
                        今天              明天              昨天
                        SYSDATE                     SYSDATE+1                   SYSDATE-1
                        -------------------         -------------------         -------------------
                        2016-02-03 22:05:38     2016-02-04 22:05:38     2016-02-02 22:05:38
                    求出距离当前时间,10分钟后的时间               
                        select sysdate,sysdate+1/24/6 十分钟后 from dual;
                    查找员工的名字和入职日期
                        select first_name,start_date from s_emp;
                    to_char函数:date数据->char数据
                        to_char(日期数据,’日期格式’);
                        select to_char(sysdate,’yyyy-mm-dd’) from dual;
                        select to_char(sysdate,’hh24:mi:ss’) from dual;
                        select to_char(sysdate,’yyyy-mm-dd hh24:mi:ss’) from dual;
                        
                        - - 查找员工的名字和入职日期
                        select first_name,to_char(start_date,’yyyy-mm-dd’) from s_emp;
                        select first_name,to_char(start_date,’hh24:mi:ss’) from s_emp;
                        select first_name,to_char(start_date,’yyyy-mm-dd hh24:mi:ss’) from s_emp;
                        
                        - - 查询哪些员工是3月份入职的
                        select first_name, start_date from s_emp where to_char(start_date,’mm’) =’03’;
                    如果插入日期类型的数据
                        1.隐式类型转换
                            满足当前会话日期格式的字符串->date
                                默认会话日期格式:’DD-MON-RR’, ’01-1月-16’    ’01-Jun-16’ 
                        2.显示类型转换:to_date函数
                    to_date函数:char数据-》date数据
                        to_date(‘日期字符串’,’格式字符串’)
                        to_date(‘2016-01-01’,’yyyy-mm-dd’)
                        to_date(‘01-1月-16’,’DD-MON-RR’)
                    练习:
                        drop table stu;
                        create table stu(
                            id      number(8) primary key,
                            name        varchar2(15) not null,
                            startdate   date
                        );
                        alter session set nls_date_format=‘DD-MON-RR’;
                        select siesta from dual;
        
                        insert into stu values(1, ’Tom’, ’01-9月-13’);
                        commit;     事件提交,大家访问数据库时都能看到
                        insert into stu values(2, ’James’, ’2013-09-01’);- - 会报错
                        insert into stu values(2, ’James’, to_date(’2013-09-01’,’yyyy-mm-dd’));
                        insert into stu values(3, ’Tom’, ’01-9月-13’);
    
                        向stu表中插入记录
                        3   Mary    2013-09-03  11:09:23(通过隐式转换)                        
                        4   Tony    2013-09-05  09:01:06(通过显示转换)
                        alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
                        insert into stu values(3, ‘Mary’, to_date(‘2013-09-03   11:09:23’,’yyyy-mm-dd hh24:mi:ss’));
                        commit;
                        insert into stu values(4, ‘Tony’, ‘2013-09-05 09:01:06’);
                        commit;
            4)其它函数:
                nvl(a,b)        空值替换函数(a如果是null,aa替换成b,前提是b要和a的数据类型一致)
    
        多行函数:多条记录只返回一个结果,也叫组函数、聚集函数
            SUM()       总和
            AVG()       平均值
            MAX()       最大值
            MIN()       最小值
            COUNT() 统计记录条数
                count(name) 统计所有name记录条数(null时不统计)
                count(*)    统计所有记录  
            查询所有员工的平均提成
                select avg(nvl(commission_pct,0))from s_emp;
    2、select
        select      *,字段名,表达式,函数调用...可以起别名  
        from        表1 别名1,表2 别名2,…
        where       分组前的过滤条件    组合and or not
                    =  >  >=  < <=  <> != between a and b  in
                    like
                        %, _  []  [^]
                    is null is not null
        group by 字段名    分组字段
        having      分组后的过滤条件
        order by 字段名/别名/序号      排序规则:[asc]/desc...
    
        执行顺序:
            from 确定表-》where选择行-》group by分组-》再计算select 组函数-》having过滤 选择行-》最后order by 排序
    
        例子1:找出员工的名字和薪水 
            select first_name,salary  from s_emp;
        例子2:找出员工的名字和年薪
            select first_name,salary*12  from s_emp;
            如何给字段、表达式起别名:
                1)as    别名  表头  使用别名代替      默认全部大写
                    select first_name,salary*12 as 年薪 from s_emp;
                2)省略as
                    select first_name,salary*12 yearsal from s_emp;
                3)使用双引号 可以有特殊字符,比如空格    能区分大小写
                    select first_name,salary*12 as “c年 薪C” from s_emp;
            select 1+2;
                会报错:- -》结论:oracle中的select语句,必须要有select和from关键字      
            select之后的表达式,有几条记录,就会计算几次
                select 1+2 from s_emp;
            dual虚表的应用:
                怎样才能只算一次,- - - 单行的表的虚表dual
                    select 1+2 from dual;
                查看当前的系统时间
                    select siesta from dual;
        
        例子3:查询出员工的全名:first_name  last_name
            如何进行字符的拼接
                SqlServer中:使用+
                    如果不是字符,需要使用str()函数进行转化
                    ’Hello‘ + str(123)  ‘asd’ + ‘fgh’
                oracle中:||表示字符串的拼接
                    select first_name || ‘ ’ || last_name “Full name” from s_emp;
            select first_name+last_name from s_emp;
        
            要求:查询当前数据库中有多少用户表?
                用户表由系统表user_tables来管理,
                用户表的表名称,通过table_name字段表示
                select table_name from user_tables;- - - 假如返回145行 
            要求:写一条sql,返回近似以下结果
                select * from S_EMP;        
                select * from S_DEPT;       
                select * from S_REGION;     
                select * from S_SALGRADE;   
                …
                一共也返回145行
                select ‘select * from’ || ’ ‘ || table_name || ‘;’ from user_tables;
                用途:生成一组批量的sql语句
        例子4:找出每个员工的年总收入 年薪+提成
            思路:表    s_emp
                月薪  salary
                年薪  salary * 12
                提成  commission_pct  10   12.5    17 百分比
                年总收入    年薪 * (1+提成/100)
            select first_name,salary * 12 from s_emp;
            select first_name, 
                salary * 12 * (1+nvl(commission_pct,0) / 100) as 年总收入 
            from s_emp;
        空值产生的影响:
                1:空值null参与运算,结果也是空
                    解决:使用空值的转换函数nvl(字段名,空值的替换值)
                        比如:nvl(commission_pct,0)
                            如果commission_pct为null,使用0代替
                            如果commission_pct不为null,使用原值
                            注意:代替值的数据类型和宽度必须和字段一致
                2:任何值包括null本身  和空值null比较,都为假,
                    空值不能直接比较,任何值和null值比较都为假,只能用:is null  /is not null
                 oracle中tab1表
                        c1(UK)      c2
                        null        null
                        null        null
                    是可以的,
    
        例子5:查看员工分布在哪些不同的部门?
                select dept_id  from s_emp; - - -有重复dept_id出现
            去除重复值?关键字distinct
                只能写在select之后,管的是之后的所有字段,
                在oracle9i或10g的某些版本中,不仅仅能去重,还会排序,
                    select distinct dept_id from s_emp;
                oracle历史版本:9i 10g 11g 12c
            查询出哪些部门和职位?
                select distinct dept_id,title from s_emp;
                distinct只能在select之后,如果有多个字段,表示联合唯一,组合在一起是唯一的
            红   黑
            红   蓝
            红   绿
            蓝   黑
            蓝   红   
        例子6:排序  根据员工薪水从小到大排序
            order by 字段名  排序规则, …
                           asc  从小到大    升序  默认可不写
                           desc 从大到小    降序
            select first_name,salary 
            from s_emp 
            order by salary sac;
        
            练习:查询出员工的信息:
                id,first_name,dept_id,salary,按照部门号升序排序
                    select id,first_name,dept_id,salary 
                    from s_emp 
                    order by dept_id asc;
                如果部门相同再按照薪水降序
                    select id,first_name,dept_id,salary
                    from s_emp 
                    order by dept_id asc,salary desc;
        例子7:查询id为10的员工信息    
                select id,first_name,dept_id,salary 
                from s_emp 
                where id=10;
                    如果提示未选定行(no rows):说明一行都没有,
            查询Mark一个月挣多少钱?
                select first_name,salary
                from s_emp
                where first_name=‘Mark’;
                
                select first_name,salary
                from s_emp
                where first_name=‘mark’;
                    报错:未选定行
                select * from s_dept;
                SELECT * FROM s_dept;
                    以上两句sql查询结果一样
                结论:oracle中值的比较区分大小写
                    oracle在功能上不区分大小写
                        但在性能上是区分的
                        建议sql格式要统一(统一的规范),减轻DBMS的负担,
                        比如:关键字全部大写,
        例子8:查询出薪水在1500〜2000之间的员工信息
            select id,first_name,dept_id,salary 
            from s_emp 
            where salary between 1500 and 2000;
        例子9:列出41、42、43部门员工的薪水情况
            select first_name,salary,dept_id
            from s_emp
            where dept_id in(41,42,43);
            或者
            select first_name,salary,dept_id
            from s_emp
            where dept_id =any(41,42,43);
            或者
            select first_name,salary,dept_id
            from s_emp
            where dept_id between 41 and 43;
        例子10:查询所有的表名为’S_‘开头的表的名称
            使用like进行模糊查询:
                字段名  like  ‘匹配字符串’       模糊查询
                            匹配字符串:
                                %   0个或多个字符(任意个字符)
                                _   任意1个字符
                                    如果想表示特殊的字符,比如_本身,需要转义,使用\_  表示_本身
        同时还需要使用escape关键字(只有oracle中要使用escape明确指定),来明确指定转义符
            like    ’S\_%’ escape ‘\’,  使用了转义符,能够取得字符的本意,推荐使用\
                                []  在范围内的1个字符
                                [^] 不在范围内的1个字符
            SELECT table_name FROM user_tables WHERE table_name like ’S_%’;
        例子11:找出哪些员工没有提成?
            判断某个字段是否为空:
                is null
                is not null
            select first_name, commission_pct from s_emp where commission_pct is null;
            select first_name, commission_pct from s_emp where commission_pct is not null;
            找出工资比1500高的并且有提成的员工信息?
                select id,first_name,salary,commission_pct from s_emp where salary>500 and commission_pct is not null;
            常用的比较连接词归纳
                肯定形式            否定形式
                in              not in
                    等价于=any         等价于<>all
                like                not like
                is null             is not null
                between  a  and b       not between a and b
            查询42部门的员工的年薪,年薪升序排序
                - - 推荐使用以下
                select id,dept_id, first_name,salary*12 yearsal
                from s_emp 
                where dept_id=42 
                order by yearsal;
                    sql执行顺序:先from决定表s_emp->再where选择行->再select 找列, 计算出salary*12 投影->最后order by排序
            
                - - 以下使用序号指定排序的字段,select后,从1开始递增
                select id,dept_id, first_name,salary*12 yearsal
                from s_emp 
                where dept_id=42 
                order by 3 asc;
        例子12:平均提成
                select avg(nvl(commission_pct,0)) from s_emp;
                有多少部门
                select count(distinct deept_id) from s_emp;
                统计出各个工薪级别有多少员工
                s_emp       s_salgrade
                salary      grade losal  hisal
    
                select s.grade 薪资级别,count(id) 对应员工数 
                from s_emp e
                right outer join s_salgrade s 
                on e.salary between s.losal and s.hisal 
                group by s.grade 
                order by s.grade;
            统计出工薪级别为5的员工人数
                select s.grade,count(id)
                from s_emp e
                right outer join s_salgrade s   
                on e.salary between s.losal and s.hisal 
                group by s.grade
                having s.grade=5;
        例子13,谁的工资最低 
            select id,first_name,salary from s_emp where salary=(select min(salary) from s_emp);
           谁和Mark从事同样的工作            
            select id,first_name,title
            from s_emp 
            where title=(select title from s_emp where first_name=‘Mark’) 
            group by id,first_name,title 
            having first_name<>’Mark’
            order by id;    
           找出哪些人是领导
            select first_name 
            from s_emp 
            where id in(select distinct manager_id from s_emp where manager_id is not null);
        找出哪些人不是领导
            select first_name
            from s_emp
            where id not in(select distinct manager_id from s_emp  where manager_id is not null);
        哪些部门的平均工资比41号部门的平均工资高?
            //select avg(salary) from s_emp where dept_id=41;
            select dept_id,avg(salary) from s_emp group by dept_id;
    
            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);
    
    
    3、表连接(重点)
        数据库的设计      使用table来存储业务数据
        关系型数据库      关系  二维表table    实体  实体间的关系
                    E-R模型   E-R图
        数据库具备良好的设计:
            1NF:每个属性不可在分(关系型数据库基本要求)
            2NF:提供PK主属性 保证实体完整性
            3NF:解除了非主属性之间的依赖关系  拆表(一般采用)
                3NF减少数据冗余,解决了数据的不一致问题,从而形成一种良好 设计
                3NF特点:将一张表拆分成n张表,数据分布在不同的表中,(合久必分)
        由于数据分布在不同的表中,为了一次获取不同表中的数据,就需要进行多表连接查询(分久必合)
        3.1如何实现两张表的关系?
            1)最主要的关系:主键- - 外键(主外键关系)
            员工表             部门表             区域表
            s_emp               s_dept          s_region
            id(PK)
            dept_id(FK)   *- - - 1  id(PK)
                            region_id(FK)  *- - - 1 id(PK)
           2)其它
        3.2如何进行表连接
            语法:from 表1,表2,…
            问题:会产生笛卡尔积  会匹配所有记录
                为了避免笛卡尔积,需要指定表连接条件
        3.3表连接的分类
             (1)内连接 inner join  on
                特点:记录会严格匹配
            1)等值连接
            2)非等值连接
            3)自连接
             (2)外连接 outer join on   对内连接的补充
                特点:解决的是一个都不能少的问题
            1)左外连接
            2)右外连接
            3)全外连接
        - - - - - - - - - - 
             (1)内连接 inner join on   
                特点:记录会严格匹配,可能造成记录丢失(空值的影响)
                标准sql写法:内连接:  from 表1 
                               inner  join 表2  
                               on  连接条件(都通用)
            1)等值连接:两个表的关系通过等值方式联系在一起(查询结果=FK所在表的记录条数)
                查询员工名称、和对应部门名称
                    select first_name,name 
                    from s_emp e,s_dept d 
                    where e.dept_id=d.id;   
    
                    select first_name,name
                    from s_emp e
                    inner join s_dept d
                    on e.dept_id=d.id;
                查询部门名称、和对应区域名称
                    select d.name,r.name 
                    from s_dept d,s_region r 
                    where d.region_id=r.id;
                查询Mark在哪个地区上班?(3张表,通过2个等值连接条件,联系在一起)
                    s_emp               s_dept          s_region
                    id(PK)
                    dept_id(FK)     =   id(PK)
                                    region_id(FK)   =   id(PK)
                    first_name                          name
    
                    select e.first_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 
                        and e.first_name=‘Mark’ ; 
            2)非等值连接
                >  >=  <  <=  <>  between and
                查询员工的名字、薪水、薪水等级
                    select e.first_name,e.salary,s.grade 
                    from s_emp e,s_salgrade s 
                    where e.salary between s.losal and s.hisal;
            3)自连接:如果1张表中两个字段之间有关系,可以采用自连接
                技巧:将1张表通过起别名的方式,模拟成2张表
                s_emp表  id(PK)          员工id
                        manager_id(FK)  领导id   参照于本表的id(s_emp的id)
                查询员工id,员工名字,对应的领导id
                    select id,first_name,manager_id from s_emp;
                查询员工的名字和其领导的名字
                    select e.first_name,ec.first_name 
                    from s_emp e, s_emp ec 
                    where e.manager_id=ec.id;
                        标准sql写法:内连接   inner  join  on  连接条件(不是常用)
                    select e.first_name,ec.first_name 
                    from s_emp e
                    inner join s_emp ec 
                    on e.manager_id=ec.id;
    
                    发现Carman这个员工不见了(他的领导id是null)
                        内连接实现不了,只能在用外连接来扩展
                    
             (2)外连接 outer join on   对内连接的补充
                特点:解决的是一个都不能少的问题
                //标准sql写法:外连接   :  from 表1 
                               outer  join 表2
                               on  连接条件(通用)
    
            1)左外连接  保证左边表的记录1个都不能少,
                oracle语法:
                    要想让左边表 记录1个都不能少, 在对方(右边)加(+)
                查询员工的名字和其领导的名字
                    select e.first_name,ec.first_name 
                    from s_emp e,s_emp ec
                    where e.manager_id=ec.id(+);
                        左边      右边
                   标准sql语法:from 左表 left outer join 右表 on  连接条件
                    select e.first_name,ec.first_name
                    from s_emp e
                    left outer join s_emp ec
                    on e.manager_id=ec.id;
                    
                    select e.first_name,ec.first_name
                    from s_emp e
                    outer join s_emp ec
                    on e.manager_id=ec.id;
            2)右外连接  保证右边表的记录1个都不能少,
                oracle语法:
                    要想让右边表 记录1个都不能少, 在对方(左边)加(+)
                   标准sql语法:from 左表 right outer join 右表 on  连接条件
            3)全外连接  保证两边表的记录1个都不能少,
                oracle语法:
                    不允许两边同时添加(+)
                   标准sql语法:from 左表 full outer join 右表 on  连接条件
        外连接sql脚本:outerjoin.sql,测试用
                t_emp       t_dept
            drop table t_emp;
            drop table t_dept;
    
            create table t_emp(
                id      number(5)   primary key,
                name        varchar2(15), 
                dept_id number(5)
            );
            insert into t_emp values(1, ’Tom’, 11);
            insert into t_emp values(2, ’James’, 12);
            insert into t_emp values(3, ‘Mary’, null);
            insert into t_emp values(4, ’Tony’, 13);
            insert into t_emp values(5, ’Ajax’, 11);
            insert into t_emp values(6, ’Nill’, 12);
            commit;
            create table t_dept(
                id      number(5)   primary key,
                name        varchar2(15) not null
            );
            insert into t_dept values(11, ‘Java’);      
            inserc          commit; 
    
                    t_emp表
            ID NAME                              DEPT_ID
            -- ------------------------------ ----------
             1 Tom                                    11
             2 James                                12
             3 Mary
             4 Tony                                   13
             5 Ajax                                   11
             6 Nill                                     12
                                t_dept表
                                 ID     NAME
                                ---     -----
                                 11     Java
                                 12     C++
                                 13     DB
                                 14     Web
            现象:Mary没有部门,14部门没有员工
            练习1:查询所有员工信息和对应的部门信息
                内连接(Mary对应的部门丢失)
                    select e.id,e.name,e.dept_id,d.name 
                    from t_emp e,t_dept d 
                    where e.dept_id=d.id;
                左外连接
                select e.id,e.name,e.dept_id,d.name 
                from t_emp e,t_dept d 
                where e.dept_id=d.id(+);        (=左边的表记录1个都不少)
                    select e.id,e.name,e.dept_id,d.name 
                    from t_emp e 
                    left outer join t_dept d            (outer join 的左边的表记录1个都不能少)
                    on e.dept_id=d.id;
                右外连接
                select e.id,e.name,e.dept_id,d.name 
                from t_emp e,t_dept d 
                where e.dept_id(+)=d.id;        (=右边的表记录1个都不少)
                    select e.id,e.name,e.dept_id,d.name 
                    from t_emp e 
                    right outer join t_dept d           (outer join 的右边的表记录1个都不能少)
                    on e.dept_id=d.id;
                全连接:只能用标准sql写法
                    select e.id,e.name,e.dept_id,d.name 
                    from t_emp e 
                    full outer join t_dept d            (outer join 的两边的表记录1个都不能少)
                    on e.dept_id=d.id;              
    
            练习1:查询所有员工信息和对应的部门信息
            练习1:查询所有员工信息和对应的部门信息
            练习1:查询所有员工信息和对应的部门信息
                select e.id,e.name,e.dept_id,d.name 
                from t_emp e,t_dept d 
                where d.id=e.dept_id(+);
    
                    select e.id,e.name,e.dept_id,d.name 
                    from t_emp e 
                    left outer join t_dept d 
                    on d.id=e.dept_id;

    相关文章

      网友评论

        本文标题:DB学习之Oracle(一)

        本文链接:https://www.haomeiwen.com/subject/spzolttx.html