zoukankan      html  css  js  c++  java
  • oracle第三天

    HelloWorld.sql

    set serveroutput on

    declare
    --说明部分
    begin
    --程序
    dbms_output.put_line('Hello World');
    end;
    /

    if语句.sql

    --判断用户输入的数字

    set serveroutput on

    --接收键盘输入
    --num: 地址值,在该地址上,存了输入的值
    accept num prompt '请输入一个数字';

    declare
    --定义变量保存输入的数字
    --隐式转换
    pnum number := #
    begin

    if pnum = 0 then dbms_output.put_line('您输入的是0');
    elsif pnum = 1 then dbms_output.put_line('您输入的是1');
    elsif pnum = 2 then dbms_output.put_line('您输入的是2');
    else dbms_output.put_line('其他数字');
    end if;
    end;
    /

    带参数的光标.sql

    --查询某个部门中员工的姓名

    set serveroutput on

    declare
    --带参数的光标
    cursor cemp(dno number) is select ename from emp where deptno=dno;
    pename emp.ename%type;
    begin
    open cemp(20);
    loop
    fetch cemp into pename;
    exit when cemp%notfound;

    dbms_output.put_line(pename);

    end loop;
    close cemp;
    end;
    /

    给员工涨工资.sql

    --涨工资 总裁1000 经理800 其他400

    set serveroutput on

    declare
    cursor cemp is select empno,empjob from emp;
    pempno emp.empno%type;
    pjob emp.empjob%type;
    begin
    rollback;

    open cemp;
    loop
    --取一个员工 涨工资
    fetch cemp into pempno,pjob;
    exit when cemp%notfound;

    --判断职位
    if pjob = 'PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
    elsif pjob = 'MANAGER' then update emp set sal=sal+800 where empno=pempno;
    else update emp set sal=sal+400 where empno=pempno;
    end if;

    end loop;

    close cemp;

    --事务的隔离级别
    commit;

    dbms_output.put_line('涨工资完成');
    end;
    /

     光标

    --使用游标查询员工姓名和工资,并打印

    /*
    1. 光标的属性
    %isopen: 是否打开
    %rowcount: 行数
    %notfound: 没有记录

    2. 默认允许一次打开300个光标(修改光标: 第四天 管理方案)
    SQL> show parameters cursor

    NAME TYPE VALUE
    ------------------------------------ ----------- -------
    cursor_sharing string EXACT
    cursor_space_for_time boolean FALSE
    open_cursors integer 300
    session_cached_cursors integer 20
    */

    set serveroutput on

    declare
    --定义光标代表员工集合
    cursor cemp is select ename,sal from emp;
    pename emp.ename%type;
    psal emp.sal%type;
    begin
    open cemp;

    loop
    --取一个员工
    fetch cemp into pename,psal;

    --退出条件
    exit when cemp%notfound;

    dbms_output.put_line(pename||'的薪水是'||psal);

    end loop;

    close cemp;
    end;
    /

     记录型变量

    ----查询并打印7839的姓名和薪水


    set serveroutput on

    declare
    --记录型变量 代表一行
    emp_rec emp%rowtype;
    begin

    select * into emp_rec from emp where empno=7839;

    dbms_output.put_line(emp_rec.ename||'的薪水是'||emp_rec.sal);
    end;
    /

    实例1

    /*
    实例1:统计每年入职的员工个数。

    SQL语句
    1. select to_char(hiredate,'RR') from emp; --> 光标 --> 循环(notfound)
    2. count80 number := 0;
    count81 number := 0;
    count82 number := 0;
    count87 number := 0;
    */
    set serveroutput on

    declare
    cursor cemp is select to_char(hiredate,'RR') from emp;
    phiredate varchar2(4);

    --计数器
    count80 number := 0;
    count81 number := 0;
    count82 number := 0;
    count87 number := 0;
    begin
    open cemp;
    loop
    --取一个员工
    fetch cemp into phiredate;
    exit when cemp%notfound;

    --判断年份
    if phiredate = '80' then count80:=count80+1;
    elsif phiredate = '81' then count81:=count81+1;
    elsif phiredate = '82' then count82:=count82+1;
    else count87:=count87+1;
    end if;

    end loop;
    close cemp;

    dbms_output.put_line('Total:'||(count80+count81+count82+count87));
    dbms_output.put_line('80:'||count80);
    dbms_output.put_line('81:'||count81);
    dbms_output.put_line('82:'||count82);
    dbms_output.put_line('87:'||count87);
    end;
    /

     实例2

    /*
    为员工长工资。从最低工资调起每人长10%,但工资总额不能超过5万元,
    请计算长工资的人数和长工资后的工资总额,并输出输出长工资人数及工资总额。

    SQL语句:
    1. select empno,sal from emp order by sal;-->光标 -->循环(1. > 5w 2. 涨完)
    2. countEmp number := 0;
    3. 长工资后的工资总额: *. select sum(sal) from emp
    *. 涨后=涨前+sal*0.1 (*)

    练习: 工资<5w
    */
    set serveroutput on
    declare
    cursor cemp is select empno,sal from emp order by sal;
    pempno emp.empno%type;
    psal emp.sal%type;

    --人数
    countEmp number := 0;

    --工资总额
    salTotal number;
    begin
    --初始的工资总额
    select sum(sal) into salTotal from emp;

    open cemp;
    loop
    --第一个退出条件
    exit when salTotal> 50000;

    --取一个员工
    fetch cemp into pempno,psal;

    --第二个退出条件
    exit when cemp%notfound;

    --涨工资
    update emp set sal =sal *1.1 where empno=pempno;

    --人数
    countEmp := countEmp+1;


    --工资总额
    salTotal := salTotal + psal *0.1;
    end loop;
    close cemp;

    commit;

    dbms_output.put_line('人数:'||countEmp||' 工资总额:'||salTotal);

    end;
    /

    实例3

    /*
    用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)
    统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)

    SQL语句
    1. 部门: select deptno from dept; --> 光标 --> 循环
    2. 部门中员工的薪水: select sal from emp where deptno=??? --> 带参数的光标 --> 循环
    3. count1 number; count2 number; count3 number;
    4. 部门工资总额: salTotal number;
    select sum(sal) into salTotal from emp where deptno=???
    */
    set serveroutput on

    declare
    --部门
    cursor cdept is select deptno from dept;
    pdeptno dept.deptno%type;

    --部门中员工的薪水
    cursor cemp(dno number) is select sal from emp where deptno=dno;
    psal emp.sal%type;

    --计数器
    count1 number; count2 number; count3 number;

    --部门的工资总额
    salTotal number;
    begin
    open cdept;
    loop
    --取一个部门
    fetch cdept into pdeptno;
    exit when cdept%notfound;

    --初始化
    count1:=0;count2:=0;count3:=0;

    --部门的工资总额
    select sum(sal) into salTotal from emp where deptno=pdeptno;

    --部门中员工的薪水
    open cemp(pdeptno);
    loop
    --取一个员工的薪水cl
    fetch cemp into psal;
    exit when cemp%notfound;

    --判断
    if psal< 3000 then count1:=count1+1;
    elsif psal>=3000 and psal<6000 then count2:=count2+1;
    else count3:=count3+1;
    end if;

    end loop;
    close cemp;

    -- 保存当前结果
    insert into msg1 values(pdeptno,count1,count2,count3,nvl(salTotal,0));

    end loop;
    close cdept;

    commit;

    dbms_output.put_line('完成');
    end;
    /

    系统例外

    --被0除

    set serveroutput on

    declare
    pnum number;
    begin
    pnum := 1/0;

    exception
    when Zero_Divide then dbms_output.put_line('1:0不能做被除数');
    dbms_output.put_line('2:0不能做被除数');
    when Value_error then dbms_output.put_line('算术或转换错误');
    when others then dbms_output.put_line('其他例外');
    end;
    /

    --打印1~10

    set serveroutput on

    declare
    pnum number := 1;
    begin
    loop
    --退出循环
    exit when pnum > 10;

    dbms_output.put_line(pnum);

    --加一
    pnum := pnum + 1;

    end loop;
    end;
    /

    引用型变量

    --查询并打印7839的姓名和薪水

    set serveroutput on

    declare
    --定义引用型变量
    pename emp.ename%type;
    psal emp.sal%type;
    begin

    --查询7839的姓名和薪水
    select ename,sal into pename,psal from emp where empno=7839;

    -- 打印
    dbms_output.put_line(pename||'的薪水是'||psal);
    end;
    /

    自定义例外

    --查询50号部门的员工

    set serveroutput on

    declare
    cursor cemp is select ename from emp where deptno=50;
    pename emp.ename%type;

    --自定义例外
    no_emp_found exception;
    begin
    open cemp;

    --取一个员工
    fetch cemp into pename;

    if cemp%notfound then
    --抛出例外
    raise no_emp_found;
    end if;

    --当抛出例外,自动关闭
    close cemp;

    exception
    when no_emp_found then dbms_output.put_line('没有找到员工');
    when others then dbms_output.put_line('其他例外');
    end;
    /

    out参数

    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;
    查询并返回某个员工的姓名 月薪和职位

    思考: out参数太多???
    */
    create or replace procedure queryEmpInfo(eno in number,
    pename out varchar2,
    psal out number,
    pjob out varchar2)
    as
    begin
    select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;

    end;
    /

    触发器应用场景二

    /*
    数据确认

    涨后的薪水不能少于涨前的薪水
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    [FOR EACH ROW [WHEN(条件) ] ]
    PLSQL 块

    */
    create or replace trigger checksal
    before update
    on emp
    for each row
    begin
    --if 涨后的薪水< 涨前的薪水 then
    if :new.sal < :old.sal then
    raise_application_error(-20002,'涨后的薪水不能少于涨前的薪水.涨前:'||:old.sal||' 涨后:'||:new.sal);
    end if;
    end;
    /

    触发器应用场景一

    /*
    实施复杂的安全性检查

    禁止在非工作时间 往emp表中插入数据
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    PLSQL 块

    周末:to_char(sysdate,'day') in ('星期六','星期日')
    上班前 下班后: to_number(to_char(sysdate,'hh24')) not between 9 and 18
    */
    create or replace trigger securityEmp
    before insert
    on emp
    begin
    if to_char(sysdate,'day') in ('星期六','星期日') or
    to_number(to_char(sysdate,'hh24')) not between 9 and 18 then

    raise_application_error(-20001,'不能在非工作时间插入数据');

    end if;
    end;
    /

    存储函数

    /*
    CREATE [OR REPLACE] FUNCTION 函数名(参数列表)
    RETURN 函数值类型
    AS
    PLSQL子程序体;

    查询某个员工的年收入

    */
    create or replace function queryEmpIncome(eno in number)
    return number
    as
    psal emp.sal%type;
    pcomm emp.comm%type;
    begin

    select sal,comm into psal,pcomm from emp where empno=eno;

    return psal*12+nvl(pcomm,0);
    end;
    /

    带参数的存储过程

    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;

    为指定的员工涨100块钱 并打印涨前和涨后的薪水
    */
    create or replace procedure raiseSalary(eno in number)
    as
    psal emp.sal%type;
    begin
    --涨前薪水
    select sal into psal from emp where empno=eno;

    --涨100
    update emp set sal=sal+100 where empno=eno;

    --要不要commit???

    dbms_output.put_line('涨前:'||psal||' 涨后:'||(psal+100));

    end;
    /

    第一个触发器

    /*
    成功插入员工后,自动输出“成功插入一个新员工”
    CREATE [or REPLACE] TRIGGER 触发器名
    {BEFORE | AFTER}
    {DELETE | INSERT | UPDATE [OF 列名]}
    ON 表名
    PLSQL 块

    */
    create or replace trigger sayNewEmp
    after insert
    on emp
    begin
    dbms_output.put_line('成功插入一个新员工');
    end;
    /

    第一个存储过程

    /*
    create [or replace] PROCEDURE 过程名(参数列表)
    AS
    PLSQL子程序体;

    打印Hello World

    调用存储过程
    1. exec sayHelloWorld();
    2. begin
    sayHelloWorld();
    sayHelloWorld();
    end;
    /
    */

    create or replace procedure sayHelloWorld
    as
    --说明部分
    begin
    dbms_output.put_line('Hello World');

    end;
    /

  • 相关阅读:
    Shell bash脚本查询Mysql并简单处理查询结果
    Caused by: java.lang.ClassNotFoundException: org.apache.flink.streaming.api.scala.StreamExecutionEnv
    Flink的部署方式
    Flink线上环境搭建
    数仓及数据治理相关
    Hive动态分区详解及注意的问题
    lateral view explode行转列的简单使用
    MachineLearning
    Linux 查看CPU信息,机器型号,内存等信息
    redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect time out
  • 原文地址:https://www.cnblogs.com/zszitman/p/5634589.html
Copyright © 2011-2022 走看看