### 一,视图

```
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();
        }
    }

}

```

oracle入门(二)的更多相关文章

  1. 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

    前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...

  2. Swift语法基础入门二(数组, 字典, 字符串)

    Swift语法基础入门二(数组, 字典, 字符串) 数组(有序数据的集) *格式 : [] / Int / Array() let 不可变数组 var 可变数组 注意: 不需要改变集合的时候创建不可变 ...

  3. Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)

    原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问 ...

  4. DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表

    原文:DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的, ...

  5. Oracle入门4-REF Cursor

    Oracle入门4-REF Cursor 转自:http://blog.sina.com.cn/s/blog_55dbebb00100gxsc.html 自:http://blog.csdn.net/ ...

  6. css入门二-常用样式

    css入门二-常用样式总结 基本标签样式 背景色background-color 高度height; 宽度width; 边框对齐以及详细设定举例 width/*宽度*/: 80%; height/*高 ...

  7. 微服务(入门二):netcore通过consul注册服务

    基础准备 1.创建asp.net core Web 应用程序选择Api 2.appsettings.json 配置consul服务器地址,以及本机ip和端口号信息 { "Logging&qu ...

  8. IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

    1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...

  9. 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...

随机推荐

  1. Sql Server关于日期查询时,如果表中日期到具体某个时间

    1.如果查询日期参数为'2017/02/21',而数据库表中的字段为'2017/02/21 12:34:16.963',则需要格式化一下日期才能查询出来,如下 select * from table ...

  2. 书籍管理系统 -----没有form组件

    urls: from django.contrib import admin from django.urls import path,re_path from first import views ...

  3. [翻译] DoActionSheet

    DoActionSheet https://github.com/donobono/DoActionSheet An replacement for UIActionSheet : block-bas ...

  4. java获取中文拼音首字母

    import net.sourceforge.pinyin4j.PinyinHelper; public class PinyinHelperUtil { /** * 得到中文首字母(中国 -> ...

  5. 内置的HTTP服务器【Modern PHP】

    目录 启动服务器 配置服务器 路由器脚本 判断是否为内置的服务器 PHP5.4.0起,PHP内置了Web服务器.对本地开发是个极好的工具,便捷,无需安装WAMP.XAMP或大新那个web服务器,就能在 ...

  6. 沉淀,再出发:百度地图api的使用浅思

    沉淀,再出发:百度地图api的使用浅思 一.前言   百度地图想必大家都使用过,但是看到别人使用百度地图的API时候是不是一头雾水呢,其实真正明白了其中的意义就像是调用豆瓣电影api的接口一样的简单, ...

  7. zabbix监控服务器时间问题

    zabbix中有自带对linux服务器时间进行监控的模板,用的key是system.localtime返回当前的系统时间,而配置tigger报警时是用的fuzzytime(N)方法,该方法是将返回的系 ...

  8. August 09th 2017 Week 32nd Wednesday

    Find hope from despair, life will become brilliant. 从绝望中寻找希望,人生终将辉煌. Have you ever seen the movie Ba ...

  9. 021.11 IO流 序列流

    序列流:SequenceInputStream特点:流对象有序排列解决问题:将多个输入流合并成一个输入流,将多个源合并成一个源,对于多个源的操作会变简单. 构造函数参数就是输入流,一初始化就合并了多个 ...

  10. 【OpenCV】三种方式操作图像像素

    OpenCV中,有3种访问每个像素的方法:使用at方法.使用迭代器方法.使用指针 运行如下程序后可以发现使用at方法速度最快. 代码如下: //操作图像像素 #include <opencv2/ ...