zoukankan      html  css  js  c++  java
  • oracle入门(二)

    ### 一,视图


    ```
    1. 什么是视图
        视图是一张虚表, 可以把视图看成表使用(增删改查),视图中没有数据,所有的数据都在基本表中(tables)
        封装了一个复杂的DQL
        操作视图就是操作table
        视图一般不作为修改数据使用, 只用作查询
    2. 语法
        create [or replace] view 视图名 as DQL;
    3. 栗子
        create or replace view emp_view as select * from emp;

        select * from emp_view;
        select * from emp;

        insert into emp_view(empno ,ename) values(1000, 'rose');
        -- 作用一 : 可以屏蔽敏感列
        create or replace view employee
        as select empno ,ename ,job ,mgr, hiredate ,deptno from emp;  
        select * from emp_view;
        -- 作用二:可以定义只读的视图
        create or replace view employee
        as select empno ,ename ,job ,mgr, hiredate ,deptno from emp with read only;  
        -- 错误:virtual column not allowed here
        insert into employee(empno ,ename) values(1001, 'rose');
        
        
    ```

    ### 二、索引

    ```
    1. 索引的目的
        提高检索效率
        前提:百万条记录以上, 不经常的修改列 , 经常查询的列
    2. 语法: create index 索引  on 表(列1,列2)
    3. 测试效率
        准备表,数据
        create table a(
           b number primary key ,
           c varchar2(200)
        )

        create sequence a_seq;

        select sys_guid() from dual;

        declare

        begin
               for i in 1..1000000 loop
                   insert into a values(a_seq.nextval ,sys_guid() );
               end loop;
        end;
        添加索引前查询
        select * from a where c = '1407AB1D7E26496797E63E2C7DA76DB9'; -- 0.546
        添加索引
        create index a_index on a(c);
        添加索引后查询
        select * from a where c = '9C4CD7D2251348E4B02756BEE7558C46'; -- 0.063
    4. 复合索引的触发条件(了解)   address  age
       where address = '' and age = ''   触发索引
       where address = '' or age = ''    不能触发索引
       where address = ''     触发索引
       where age = ''    不能触发索引   
    ```

    ### 三、plsql的基本语句(过程化语言)

    ```
    1. plsql  P: procedure 过程化
    2. 过程化语言的基本结构
        declare
            -- 声明语句
        begin
            --- 过程化语言
        [exception]
        end;
    3. 声明变量
        declare
            -- 声明普通变量
            i  number;
            -- 声明变量且赋值
            j number default 200;
            -- 引用类型:引用某表.某列的类型
            pname emp.ename%type;
            pjob emp.job%type;
            -- 记录类型:引用表的一行的列
            emp_row emp%rowtype;
        begin
            -- 赋值语句
            i := 100;
            -- 打印
            dbms_output.put_line(i);
            --  || 连接符
            dbms_output.put_line('j = ' || j);
            --赋值语句: select 查询的列 into 变量;
            select ename, job into pname,pjob from emp where empno = 7788;
            dbms_output.put_line(pname || '::' ||pjob);

            select * into emp_row from emp where empno = 7788;
            dbms_output.put_line(emp_row.ename || '::' ||emp_row.job || emp_row.hiredate);
        end;
    4 . if语句
        格式
        if 条件 then
             SQL语句;
        end if;
        if 条件 then
             SQL语句;
        else
            sql语句;
        end if;
        if 条件 then
             SQL语句;
        elsif 条件 then
            sql语句;
        ....
        else
            sql语句;
        end if;
    -- 输入一个整数,如果大于0,打印正数,如果小于,打印负数,否则打印零
    declare
       i number;

    begin
       i := &请输入;
       if i > 0 then
         dbms_output.put_line('正数');
       elsif i<0 then
         dbms_output.put_line('负数');
       else
         dbms_output.put_line('零');
       end if;
    end;
    5. 循环
     1) for 循环
         /*
             for 变量  in 集合|游标 loop
             
             end loop;
         */-- 打印1-10所有的整数
    declare

    begin
      for i in 1..10 loop
        dbms_output.put_line(i);
      end loop;
    end;
    2) 语法
        /*    
            loop
                循环体;
                退出条件; exit when 条件;
            end loop;
        */
        -- 打印1-10所有的整数
        declare
           i number default 1;
        begin
          loop
            dbms_output.put_line(i);
            exit when i = 10;
            i := i + 1;
          end loop;
        end;
      3) 语法
          /*
              while 条件 loop
                  循环体;
              end loop;
          */
          -- 打印1-10所有的整数
    declare
       i number default 1;
    begin
      while i <= 10 loop
        dbms_output.put_line(i);
        i := i + 1;
      end loop;
    end;
    ```

    ### 四、游标

    ```
    1. 什么是游标(主要使用在存储过程中)
        就是一个集合
        主要作用处理返回多行记录的问题
    2. 声明游标
        cursor 游标名 is DQL;
    3. 遍历游标
        1) 打开游标
            open 游标名
        2) 提取单行的记录
            fetch 游标名 into 变量中;
        3) 使用循环
            结束语句: exit when 游标名%notfound;
        4) 关闭游标
            close 游标名;
    4. 栗子
        -- 使用游标在控制台打印20号部门的员工信息
        declare
           cursor cur is select * from emp where deptno = 20;
           erow emp%rowtype;
        begin
            open cur;
             loop
              fetch cur into erow;
              exit when cur%notfound;  -- 判断是否提取到了记录
              dbms_output.put_line(erow.empno || erow.ename ||erow.job);   
            end loop;
            close cur;
        end;
        select * from emp where deptno = 20;
    -- 给20号部门的所有员工涨工资
    declare
       cursor cur is select empno from emp where deptno = 20;
    begin
       -- for 特点:自动打开和关闭游标
       -- a 是一个记录变量, 存放游标一行的记录
       for a in  cur loop
         update emp set sal = sal +1 where empno = a.empno;
       end loop;
       commit;
    end;
    ```

    ### 五、存储过程(重点)

    ```
    1. 什么是存储过程
        封装了一组sql语句, 提前编译,存储在服务端,
        一般是由dba定义
    2. 存储过程的使用场景
        网上买了一件商品:商品表(update),订单表(insert), 余额表(update),销量表(update),物流表(insert)
                       日志表(insert)
    3. 语法
        create or replace procedure 过程名(参数1 in | out 数据类型, 参数2  in | out 数据类型,...)
        as|is
            -- 声明语句
        begin
            -- plsql
        end;
    4 .栗子  -- 只有输入参数
    给某员工涨工资, 在控制台上打印涨前的工资和涨后的工资
    create or replace procedure updateSal(eno in number, psal  in number)
    is
            oldsal emp.sal%type;
          newsal emp.sal%type;
    begin
            
          select sal into oldsal from emp where empno = eno;
          dbms_output.put_line('涨前的工资:'||oldsal );
          
          update emp set sal = sal + psal where empno = eno;
          commit;
          select sal into newsal from emp where empno = eno;
          dbms_output.put_line('涨后的工资:'||newsal );
    end;

    -- 访问存储过程
    call updateSal(7788,5);
    5. 栗子   有输入有输出参数的存储过程
    -- 获取某员工的年薪
    create or replace procedure getYearSalByEno(eno in number, yearsal  out number)
    as

    begin
        select sal * 12 + nvl(comm , 0) into yearsal from emp where empno = eno;

    end;

    -- 访问存储过程
    declare
       yearsal number;
    begin
      getYearSalByEno(7902, yearsal);
      dbms_output.put_line('年薪:' || yearsal);
    end;
    6. 栗子: 输出参数为游标类型
    -- 获取某部门的所有员工信息
    -- cursor :静态的游标
    -- sys_refcursor:动态的游标,动态的指定sql语句
    create or replace procedure getEmpsByDeptno(dno in number ,emps out sys_refcursor)
    as

    begin
           -- 动态游标赋值sql语句
        open emps for
             select * from emp where deptno = dno;
    end;
    -- 访问带有输出参数为游标的存储过程
    declare
       emps sys_refcursor;
       erow emp%rowtype;
    begin
       getEmpsByDeptno(20 ,emps);
       -- 遍历游标
       loop
          fetch emps into erow;
          exit when emps%notfound;
          dbms_output.put_line(erow.empno ||erow.ename);
       end loop;
       close emps;
    end;
    ```

    ### 六、存储函数(重点)

    ```
    1. 什么是存储过程
        封装了一组sql语句, 提前编译,存储在服务端
        一般是由dba定义
        一般在存储函数中没有输出参数
    2. 与存储过程的区别
        存储函数必须有一个返回值
        存储函数可以使用select语句访问
    3. 语法
        create or replace function 函数名(参数1 in | out 数据类型, 参数2  in | out 数据类型,...)
        retrun 类型
        as|is
        
        begin
            return 值;
        end;
    4. 栗子: 获取某员工的年薪
    create or replace function getYearSalByEnoFun(eno in number) return number
    as
        yearsal number;
    begin
        select sal * 12 + nvl(comm , 0) into yearsal from emp where empno = eno;
        return yearsal;
    end;
    -- 访问存储函数
    declare
      yearsal number;
    begin
      yearsal := getYearSalByEnoFun(7902);
      dbms_output.put_line(yearsal);
    end;
    5. 可以用在select语句中    
    select getYearSalByEnoFun(7902) from dual;
    select length('abc') from dual;    
        
    ```

    ### 七,触发器

    ```
    1. 什么是触发器
        监听器: 监听表的数据是否发生改变(insert ,update ,delete)
    2. 语法
        create or replace trigger 触发器名称
        before | after
        insert |update |delete
        on 表
        触发器的级别
            表级触发器:默认的
            行级触发器:更新一条记录,执行一次,
                如果使用old,new ,必须使用行级触发器
                for each row
        declare
        
        begin
        
        end;
    3. 栗子1
        添加一条记录,在控制台打印 ’添加了一条记录‘
    create or replace trigger insertEmp
    after
    insert
    on emp

    declare
        
    begin
        dbms_output.put_line('添加了一条记录');
    end;


    insert into emp(empno ,ename) values(1002 ,'mike');
    4. 栗子2:不能给员工降薪
    create or replace trigger notUpdateEmpLowerSal
    before
    update
    on emp
    for each row
    declare

    begin
      if :old.sal > :new.sal  then
           -- 提示:不能降薪
        --dbms_output.put_line('不能降薪');
        -- raise_application_error(p1,p2)
           -- p1 : 错误的编号(-20001 ~~~ -20999)
           -- p2: 错误的提示信息
           raise_application_error(-20001, '不能降薪');
      end if;
    end;

    update emp set sal = sal + 1 where empno = 7788;
        
    ```

    ![1535171397687](assets/1535171397687.png)    

    ### 八,JDBC调用存储过程和存储函数

    ```
    package com.jjy;


    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;

    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import oracle.jdbc.driver.OracleCallableStatement;
    import oracle.jdbc.driver.OracleTypes;

    public class JDBCTest {
        
        String driver = "oracle.jdbc.driver.OracleDriver";
        String url = "jdbc:oracle:thin:@192.168.***.***:1521:orcl";
        String username = "scott";
        String password = "tiger";
        Connection conn;
        PreparedStatement pst;
        CallableStatement cst;
        ResultSet rs;
        /**
         * 在执行test方法之前执行before
         */
        /**
         * 初始化信息
         * @throws Exception
         */
        @Before
        public void init() throws Exception{
            Class.forName(driver);
            conn = DriverManager.getConnection(url, username, password);
        }
        
        /**
         * 访问存储过程
         * create or replace procedure getYearSalByEno(eno in number, yearsal  out number)
         * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
         */
        @Test
        public void testProcedure()throws Exception{
            //声明sql语句
            String sql = "{call getYearSalByEno(?,?)}";
            //创建statement对象
            cst = conn.prepareCall(sql);
            //设置占位符
            cst.setInt(1, 7902);
            //设置输出参数的类型
            cst.registerOutParameter(2, OracleTypes.NUMBER);
            //执行sql语句
            cst.executeUpdate();
            //获取结果
            int yearsal = cst.getInt(2);
            System.out.println("年薪:" + yearsal);
        }
        /**
         * 访问存储过程
         * create or replace procedure getEmpsByDeptno(dno in number ,emps out sys_refcursor)
         * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
         */
        @Test
        public void testProcedureOutCursor() throws Exception{
            //声明sql语句
            String sql = "{call getEmpsByDeptno(?,?)}";
            //创建statement对象
            cst = conn.prepareCall(sql);
            //设置占位符
            cst.setInt(1, 20);
            //设置输出参数的类型
            cst.registerOutParameter(2, OracleTypes.CURSOR);
            //执行sql语句
            cst.executeUpdate();
    //        //获取结果
            //OracleCallableStatement ocst = (OracleCallableStatement) cst;
            
    //        rs = (ResultSet) cst.getObject(2);
    //        while(rs.next()){
    //            System.out.println(rs.getInt("empno")   + rs.getString("ename"));
    //        }
        }
        
        /**
         * 访问存储函数
         * {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
         * create or replace function getYearSalByEnoFun(eno in number) return number
         */
        @Test
        public void testFunction()throws Exception{
            //声明sql语句
            String sql = "{?= call getYearSalByEnoFun(?)}";
            //创建statement对象
            cst = conn.prepareCall(sql);
            //设置占位符
            cst.registerOutParameter(1, OracleTypes.NUMBER);
            cst.setInt(2, 7902);
            //执行sql语句
            cst.executeUpdate();
            //获取结果
            int yearsal = cst.getInt(1);
            System.out.println("年薪:" + yearsal);
        }
        
        /**
         * 查询员工中的记录
         * @throws Exception
         */
        @Test
        public void test()throws Exception {
            String sql = "select * from emp";
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getInt("empno")   + rs.getString("ename"));
            }
        }
        /**
         * 关闭资源
         */
        @After
        public void close()throws Exception{
            if(rs != null){
                rs.close();
            }
            if(pst != null){
                pst.close();
            }
            if(cst != null){
                cst.close();
            }
            if(conn != null){
                conn.close();
            }
        }

    }

    ```

  • 相关阅读:
    form.submit 方法 并不会触发 form.onsubmit 事件
    火狐 a 标签 download 属性,要在 a 标签添加到页面中才生效;
    git、git bash、git shell的区别
    maven安装本地jar包
    JFinal极速开发框架使用笔记(四) _JFinalDemoGenerator实体类生成及映射自动化
    JFinal极速开发框架使用笔记(三) 分析Model和ActiveRecord
    JFinal极速开发框架使用笔记(二) 两个问题,一个发现
    Java常用工具类之Excel导出
    Java常用工具类之删除文件
    Java常用工具类之自定义访问对象
  • 原文地址:https://www.cnblogs.com/itworkerlittlewrite/p/9537728.html
Copyright © 2011-2022 走看看