zoukankan      html  css  js  c++  java
  • Oracle中的PL/SQL 过程化sql语言

    数据库的设计(DataBase Design):
    针对于用户特定的需求,然后我们创建出来一个最使用而且性能高的数据库!

    数据库设计的步骤:
    01.需求分析
    02.概念结构设计
    03.逻辑结构设计
    04.物理结构设计
    05.数据库的实施
    06.数据库的运行和维护

    数据库的3大范式:
    1.确保每列的原子性!每一列都是一个不可再分的数据!
    2.确保每列都和主键相关!
    3.确保每列都和主键有直接的管理,而不是间接依赖(传递依赖)!

    PL/SQL: (Procedural  Language)  过程化sql语言!

    数据库在执行PL/SQL语句的时候,PL和SQL是分别执行的!

    PL/SQL运算符

    算术运算符

    下表列出了所有PL/SQL支持的算术运算符。假设变量A=10和可变B=5,则:

    BEGIN 
       dbms_output.put_line( 10 + 5);
       dbms_output.put_line( 10 - 5);
       dbms_output.put_line( 10 * 5);
       dbms_output.put_line( 10 / 5);
       dbms_output.put_line( 10 ** 5);
    END;
    算数运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

    关系运算符

    关系运算符比较两个表达式或值,并返回一个布尔结果。下表列出了所有PL/SQL支持的关系运算符。假设变量A=10,变量B=20,则:

    DECLARE  --声明
       a number (2) := 21;
       b number (2) := 10;
    BEGIN    --开始
       IF (a = b) then
          dbms_output.put_line('Line 1 - a is equal to b');
       ELSE
          dbms_output.put_line('Line 1 - a is not equal to b');
       END IF;  --结束循环
    
       IF (a < b) then
          dbms_output.put_line('Line 2 - a is less than b');
       ELSE
          dbms_output.put_line('Line 2 - a is not less than b');
       END IF;  --结束循环
       
       IF ( a > b ) THEN
          dbms_output.put_line('Line 3 - a is greater than b');
       ELSE
          dbms_output.put_line('Line 3 - a is not greater than b');
       END IF;  --结束循环
    
       -- Lets change value of a and b
       a := 5;
       b := 20;
       IF ( a <= b ) THEN
          dbms_output.put_line('Line 4 - a is either equal or less than b');
       END IF;
    
       IF ( b >= a ) THEN
          dbms_output.put_line('Line 5 - b is either equal or greater than a');
       END IF;
       
       IF ( a <> b ) THEN
          dbms_output.put_line('Line 6 - a is not equal to b');
       ELSE
          dbms_output.put_line('Line 6 - a is equal to b');
       END IF;
    
    END; --结束
    关系运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

    比较运算符

    比较运算符用于一个表达比较到另一个。结果总是 TRUE,FALSE或NULL。

    --LIKE 运算符
    --这个程序测试LIKE运算符,将学习如何在PL/ SQL程序使用,但这里用一个程序来显示LIKE运算符的功能:
    DECLARE
    PROCEDURE compare (value  varchar2,  pattern varchar2 ) is
    BEGIN
       IF value LIKE pattern THEN
          dbms_output.put_line ('True');
       ELSE
          dbms_output.put_line ('False');
       END IF;
    END;
    
    BEGIN
       compare('Zara Ali', 'Z%A_i');
       compare('Nuha Ali', 'Z%A_i');
    END;
    Like运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

    --BETWEEN运算符
    --下面的程序显示了运算符BETWEEN的用法
    DECLARE
       x number(2) := 10;
    BEGIN
       IF (x between 5 and 20) THEN
          dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
       
       IF (x BETWEEN 5 AND 10) THEN
          dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
       
       IF (x BETWEEN 11 AND 20) THEN
          dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
    END;
    BETWEEN运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

    --IN和IS NULL运算符
    --下面的程序显示IN和IS NULL运算符的用法
    DECLARE
       letter varchar2(1) := 'm';
    BEGIN
       IF (letter in ('a', 'b', 'c')) THEN
          dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
     
       IF (letter in ('m', 'n', 'o')) THEN
           dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
       
       IF (letter is null) THEN
        dbms_output.put_line('True');
       ELSE
          dbms_output.put_line('False');
       END IF;
    END;
    IN和IS NULL运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

     

    逻辑运算符

    下表显示了PL/SQL支持的逻辑运算符。所有这些操作符布尔运算,并产生布尔结果。假设变量A=true,变量B=false

    DECLARE
       a boolean := true;
       b boolean := false;
    BEGIN
       IF (a AND b) THEN
          dbms_output.put_line('Line 1 - Condition is true');
       END IF;
       IF (a OR b) THEN
          dbms_output.put_line('Line 2 - Condition is true');
       END IF;
       IF (NOT a) THEN
          dbms_output.put_line('Line 3 - a is not true');
       ELSE
          dbms_output.put_line('Line 3 - a is true');
       END IF;
       IF (NOT b) THEN
          dbms_output.put_line('Line 4 - b is not true');
       ELSE
          dbms_output.put_line('Line 4 - b is true');
       END IF;
    END;
    逻辑运算符

     当上述代码在SQL提示符执行时,它产生了以下结果:

    PL/SQL运算符优先级

    运算符优先级确定表达式分组。这会影响一个表达式是如何进行计算。某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级比加法运算高:

    例如 x =7 + 3* 2; 这里,x被赋值13,而不是20,因为运算符*具有优先级高于+,所以它首先被乘以3 * 2,然后再加上7。

    这里,具有最高优先级的操作出现在表的顶部,那些具有最低出现在底部。在表达式,更高的优先级运算符将首先计算。

    DECLARE
       a number(2) := 20;
       b number(2) := 10;
       c number(2) := 15;
       d number(2) := 5;
       e number(2) ;
    BEGIN
       e := (a + b) * c / d;      -- ( 30 * 15 ) / 5
       dbms_output.put_line('Value of (a + b) * c / d is : '|| e );
    
       e := ((a + b) * c) / d;   -- (30 * 15 ) / 5
       dbms_output.put_line('Value of ((a + b) * c) / d is  : ' ||  e );
    
       e := (a + b) * (c / d);   -- (30) * (15/5)
       dbms_output.put_line('Value of (a + b) * (c / d) is  : '||  e );
    
       e := a + (b * c) / d;     --  20 + (150/5)
       dbms_output.put_line('Value of a + (b * c) / d is  : ' ||  e );
    END;
    运算符

    当上述代码在SQL提示符执行时,它产生了以下结果:

    || 拼接字符串
    := 赋值运算符
    = 比较运算符 类似与java中的==
    .. 范围运算符  1-10
    != <> ~= ^=  4种不等于
    and 逻辑与
    or 逻辑或
    not 取反

    PL/SQL语法:

    1.declare 可选部分 ==》声明

    2.begin 必须有 ==》书写sql 和 pl/sql

    3.exception 可选部分 ==》异常

    4.end 必须有 ==》pl/sql代码块结束

     事例1:loop循环语法

    --loop循环语法:
    declare    --声明部分
      i number;
    begin      --开始
      i:=1;
      loop     --循环开始
        dbms_output.put_line(i);   --输出语句
        i:=i+1;
        exit when i=10;
      end loop; --循环结束
      
    end;  --结束
    loop循环语法

    事例2:while循环语法

    declare    --声明部分
      i number;
    begin      --代码开始
      
      i:=1;
     while i<8 loop     --循环开始
        dbms_output.put_line(i);   --输出语句
        i:=i+1;
      end loop; --循环结束
    end;        --结束部分
    while循环语法

    事例3:for循环语法

    declare    --声明部分
      i number;
      
    begin      --代码开始
      
     for  i in 1..9 loop     --循环开始
        dbms_output.put_line(i);   --输出语句
      end loop; --循环结束
      
    end;        --结束部分
    for循环语法

    事例4:根据老师的薪水输出不同的语句!

    declare
      t_name  teacher.tname%type;  --说t_name的类型根据teacher表中tname的类型来决定
      t_sal   teacher.sal%type;
      t_result  varchar2(50);
    begin    --开始
      select  tname,sal into t_name,t_sal   from teacher where tno=1002; --查询指定老师的薪水
      
        if t_sal>5000 and t_sal<10000 then   -- 多重if
          t_result:='一级';
        elsif t_sal>=10000 and t_sal<20000 then
          t_result:='二级';
        else
          t_result:='高级';
        end if;  
        --根据t_result的值来判断输入语句    switch
        case t_result
            when '一级' then
            dbms_output.put_line('哈哈....');
            when '二级' then
            dbms_output.put_line('一般般....');
            when '高级' then
            dbms_output.put_line('可以啊....');      
        end case;
    end;     --结束
    根据老师的薪水输出不同语句

    事例5:函数,将身份证中的出生日期隐藏起来

    create or replace  function fn_teacher_tid(f_tid varchar2)
    return varchar2     --创建一个函数  传递一个varchar2类型的值 返回一个varchar2类型的值
    is
     f_result varchar2(50);    --声明变量
    begin      --开始书写函数内容
      if length(f_tid)!=18 then
        dbms_output.put_line('身份证格式不正确');
        else
        dbms_output.put_line('身份证格式正确'); 
      end if;
        f_result:= substr(f_tid,1,6)||'********'||substr(f_tid,15);
        return f_result;
    end fn_teacher_tid;   --函数结束
    
    --调用函数  需要现将函数执行 放入到Functions中  没有出错时再调用方法
    select fn_teacher_tid('41302619921215935X') from dual;
    函数,将身份证中的出生日期隐藏起来

    执行结果出生日期8位数字被隐藏

    事例6:隐式游标

    begin    --  隐式游标    自动创建
         update teacher set tname='我是隐式游标' where tno=1002;  --修改
        if sql%found  then
           dbms_output.put_line('教师的信息已经更改'||sql%rowcount);
           else
           dbms_output.put_line('更改失败');
        end if;      
    end;
    隐式游标

     

     事例7:显示游标

    declare    --声明 显示游标
      c_tname  teacher.tname%type;
      c_sal    teacher.sal%type;
    cursor  teacher_cursor
    is
    select tname,sal from teacher where tno<1005;  --游标数据来源
    begin
      open teacher_cursor;  --打开游标
       fetch teacher_cursor into c_tname,c_sal;--使用游标
        while teacher_cursor%found  loop      
          dbms_output.put_line('教师的姓名是==》'||c_tname);
          dbms_output.put_line('教师的薪水是==》'||c_sal); 
          fetch teacher_cursor into c_tname,c_sal;--逐行读取  
        end loop;
      close teacher_cursor;   --关闭游标
    end;
    显示游标

     

    判断条件tno<1005  显示老师的姓名和工资

     

    游标 :
    01.是oracle系统给我们用户开设的一个数据缓冲区!
    02.存放的是sql语句执行的结果集!
    03.每个游标区都有一个名称,用户通过游标逐行获取需要的数据!

    分类:
    01.隐式游标: 非查询语句
    只要我们使用pl/sql,程序在执行sql语句的时候 自动创建! 游标区===》sql
    02.显示游标: 返回多行记录
    03.REF游标(动态游标): 处理运行时才能确定的动态sql查询结果

    游标的常用属性:
    01.sql%found 影响了一行或者多行数据 返回true
    02.sql%notfound 没有影响行 返回true
    03.sql%rowcount 返回true影响行数
    04.sql%isopen 游标是否打开!始终是false

    使用游标的步骤:
    01.声明游标
    02.打开游标
    03.使用游标获取记录
    04.关闭游标

    事例8:触发器

    触发器只针对于增删改! 

    update :old :new
    insert :new
    delete :old

    :old 代表修改之前的值
    :new 代表修改之后的值

    -- 创建一个用于保存teacher操作记录的表
    create  table  teacher_log
    (
    logid  number  not null,
    old_value varchar2(150),
    create_date date,
    log_type  number,
    t_no number
    );
    --创建主键
    alter  table  teacher_log add  constraint pk_teacher_logid 
    primary key(logid);
    
    -- 创建序列
    create  sequence sq_teacherLog_logid
    minvalue 1
    maxvalue 99999999999
    start with 1
    increment by 1;
    
    --  创建触发器
    create or replace trigger  tr_teacher
    after insert or update or delete    --会在增删改之后 触发
    on teacher for each row   --作用在teacher表中的每一行
    declare   --声明变量
    old_value    teacher_log.old_value%type;
    log_type     teacher_log.log_type%type;
    t_no         teacher_log.t_no%type;
    begin
        if inserting  then
          log_type:=1; --新增
          t_no:=:new.tno;
          old_value:=:new.tname||'*****'||:new.sal;
        elsif deleting  then
           log_type:=2; --删除
          t_no:=:old.tno;
          old_value:=:old.tname||'*****'||:old.sal;
         else
           log_type:=3; --修改
           t_no:=:old.tno;
          old_value:=:old.tname||'*****'||:old.sal||'现在的薪水:'||:new.sal;
        end  if;  
      
    --把用户修改的数据 放入 teacher_log
    insert into  teacher_log
    values(sq_teacherLog_logid.nextval,old_value,sysdate,log_type,t_no);    
    end tr_teacher;  --结束
    select * from teacher
    select * from teacher for update
    select * from teacher_log
    触发器

     先执行添加语句  打开表中的锁、修改金额、点击对号,提交事务

    select * from teacher for update

    执行查询teacher_log表,可以看到被修改的数据

    select * from teacher_log

    删除表中第二条数据 TNO=1009  秦亚杰 打开表中的锁、删除字段、点击对号,提交事务

     

    执行查询teacher_log表,可以看到被删掉的数据

    select * from teacher_log

    偷偷增加一条数据,自己人将工资多给点,打开表中的锁、添加行、新增数据、点击对号,提交事务

    执行查询teacher_log表,可以看到增加信息

     

     在Oracle中增删改都需要手动去提交事务

    事例9:存储过程

    为了完成一个特定的功能而实现编写一组sql语句的集合!

    新增数据时,如果身份证号码不足18位,报错!

    create or replace  procedure  pro_addTeacher   --存储过程
    (
    p_no      teacher.tno%type,
    p_name     teacher.tname%type,
    p_tid      teacher.tid%type
    )
    is
    ex_tidException  exception;  --异常类型
    
    begin
       if length(p_tid)!=18 then
         raise ex_tidException;   --抛出异常
        end if; 
        
        --新增
        insert  into  teacher(tno,tname,tid)
        values(p_no,p_name,p_tid);
        commit;  --- 自动提交
        
    exception    -- 异常处理部分
       when ex_tidException then
         dbms_output.put_line('身份证号不正确');
        when others then
         dbms_output.put_line('其他异常');
      
    end pro_addTeacher;   --结束
    
    --调用存储过程
    call pro_addTeacher(1000,'新增','112222222222222222');
    select * from teacher
    select * from teacher for update
    存储过程

     

     

    身份证号等于18位时,数据添加成功

     

    name teacher.tname%type :会根据表中字段的类型,自动改变!

    teacherRow teacher%rowtype: 一整行的记录,包括很多字段!

    teacherRow.name

  • 相关阅读:
    Nginx 高级配置
    nginx安装和优化配置
    location语法介绍
    iptables
    通过 loganalyzer 展示数据库中的系统日志
    ubuntu_server16.04详细安装步骤
    内存控制mmap的原型和使用方法
    C语言中open函数read函数lseek函数是如何使用的
    gdb调试工具的基本使用
    C语言如何制作静态库
  • 原文地址:https://www.cnblogs.com/wqtzhaoqiang/p/7853486.html
Copyright © 2011-2022 走看看