• 就业培训学习记录-day005


    课堂任务

    触发器

    触发器是一种在事件发生时隐式地自动执行的PL/SQL块,不能接受参数,不能被显式调用。

    触发器类型

    根据触发器所创建的语句及所影响的对象的不同,将触发器分为以下3类。但今天的内容主要只说第一种。

    1. DML触发器
      对数据表进行DML语句操作(如insert、update、delete)时所触发的触发器。
      语法:
    create [or replace] trigger trigger_name
    {before | after} trigger_event
    on table_name
    [for each row]
    [when trigger_condition]
    trigger_body
    

    语法解释:
    trigger_name:触发器名称
    before | after:指定触发器是在触发事件发生之前触发还事件发生之后触发
    trigger_event:触发事件,在DML触发器中主要为insert、update、delete等
    table_name:表名,表示发生触发器作用的对象
    for each row:指定创建的是行级触发器,若没有该子句则创建的是语句级触发器
    when trigger_condition:添加的触发条件
    trigger_body:触发体,是标准的PL/SQL语句块

    1. 替代触发器(instead of触发器)
      对视图进行操作时定义的触发器,替代触发器只能定义在视图上。
      语法:
    create [or replace] trigger trigger_name
    instead of trigger_event
    on view_name
    for each row
    [when trigger_condition]
    trigger_body
    
    1. 系统事件触发器
      对数据库实例或某个用户模式进行操作时定义的触发器,可以分为:数据库系统触发器和用户触发器。

    创建触发器

    禁止在非工作时间(9点到18点)对表进行修改

    create or replace trigger tr_emp_time
    before insert or update or delete on emp
    begin
      if to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
        raise_application_error(-20003,'not time work');
      end if;
    end;
    

    如果想看效果,可以把上面的时间改一下,然后往emp表中插入一条数据即可。

    insert into emp values(5050,'JOE',null,null,sysdate,1000,null,10);
    

    在行: 1 上开始执行命令时出错 -
    insert into emp values(5050,'JOE',null,null,sysdate,1000,null,10)
    错误报告 -
    SQL 错误: ORA-20003: not time work
    ORA-06512: 在 "SCOTT.TR_EMP_TIME", line 3
    ORA-04088: 触发器 'SCOTT.TR_EMP_TIME' 执行过程中出错

    在插入新员工后,输出插入成功的提示信息

    create trigger tr_emp_insert
    after insert
    on emp
    declare
    begin
      dbms_output.put_line('成功插入新员工');
    end;
    

    关键字new,old

    oracle中,这两个变量只有在使用了关键字FOR EACH ROW时才存在,old代表老数据,new代表新数据,不过二者在使用时是有限制的。
    insert时,只有new,没有old 
    delete时,只有old,没有new
    update时,二者都可用

    修改员工工资后,输出新旧工资的值

    create or replace trigger checksal
    before update
    on emp
    for each row
    begin
    if :new.sal!=:old.sal then
      dbms_output.put_line('旧工资:'||:old.sal);
      dbms_output.put_line('新工资:'||:new.sal);
    end if;
    end checksal;
    

    执行:

    update emp set sal=sal+100 where empno=7566 or empno=7521;
    update emp set sal=sal+0 where empno=7788;
    

    删除触发器

    语法:

    drop trigger trigger_name;
    

    存储过程

    指存储在数据库中供所有用户程序调用的一组为了完成特定功能的SQL语句集,一次编译后永久有效。

    创建存储过程

    语法如下:

    create [or replace] procedure 过程名(参数列表)
    as
    begin
      plsql子程序体;
    end 过程名;
    
    1. 输出'hello procedure'
    create or replace procedure sayhello
    as
    begin
      dbms_output.put_line('hello procedure');
    end;
    

    调用方法1:

    set serveroutput on
    exec sayhello;
    

    1. 带参数的存储过程,不commit,谁调用谁commit
    create or replace procedure raiseSal(eno number)
    as
      --定义变量
      psal emp.sal%type;
    begin
      --获取涨前的薪水
      select sal into psal from emp where empno=eno;
      --涨工资
      update emp set sal=sal+100 where empno=eno;
      --此处不commit
      dbms_output.put_line('涨前:'||psal||'涨后:'||(psal+100));
    end raiseSal;
    

    调用方法2:

    set serveroutput on
    begin
      raiseSal(7566);
      --提交事务
      commit;
    end;
    

    删除存储过程

    语法:

    DROP PROCEDURE 过程名;
    

    存储函数

    函数(function)为一命名的存储程序,可带参数,并返回一计算值。函数和过程的结构类似,但必须有一个return子句,用于返回函数值。函数说明要指定函数名、结果值的类型,以及参数类型等。

    创建存储函数

    语法:

    cerate [or replace] function 函数名(参数列表)
    return 函数值类型
    as
    begin
      plsql子程序体;
    end 函数名;
    
    1. 查看指定员工的年收入(参数为员工编号)
    create or replace function queryEmpIncome(eno 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 queryEmpIncome;
    

    调用方法1:

    select queryEmpIncome(7839) from dual;
    
    1. 输入员工名,判断该员工是否存在
    create or replace function getCountsByName(name varchar2) return number
    as
      --定义变量
      counts number;
    begin
      select count(*) into counts from emp where ename=name;
      if counts>0 then
        dbms_output.put_line('用户名已存在');
      else
        dbms_output.put_line('用户名不存在');
      end if;
      return counts;
    end getCountsByName;
    

    调用方法2:

    declare
      counts number;
    begin
      counts:=getCountsByName('King');
      DBMS_OUTPUT.put_line(counts);
      counts:=getCountsByName('KING');
      DBMS_OUTPUT.put_line(counts);
    end;
    

    删除存储函数

    语法:

    DROP FUNCTION 函数名;
    

    存储函数和存储过程的区别

    • 存储过程的关键字是procedure,存储函数的关键字是function。
    • 存储函数比存储过程多两个return。
    • 本质上的区别就是存储过程没有返回值,而存储函数有返回值。
    • 我们可以使用存储函数有返回值的特性,来自定义函数。而存储过程不能用来自定义函数。

    课后任务

    通过编写储存过程和储存函数,来尝试设计一个系统。
    (PS:这个是和我一个同学写的练习作业,有需要的话参考学习即可,实际开发并不是这样写)

    功能设计

    打算模拟一个论坛系统,要实现的功能有:

    1. 注册
    2. 登录
    3. 查看所有的主题
    4. 查看某个主题下的帖子
    5. 查看某个帖子的主题
    6. 查看所有的主题,查看所有的帖子,按最后回复时间排序(分页)
    7. 查看某个用户发表的的言论
    8. 搜索帖子(模糊查找)
    9. 发布帖子(触发器,更新用户表中的发帖数)
    10. 回复帖子(触发器,更新帖子表中的回复数)
    11. 查看有哪些用户(分页)
    12. 隐藏/显示帖子(隐藏/显示某个用户的某个帖子)

    表设计

    点击查看详细内容
    --创建用户表
    create table UserT(
    	Usid int primary key,
    	Uname nvarchar2(100) not null,
    	Password nvarchar2(100) not null,
    	--帖子数
    	Pnum int not null
    );
    
    --创建主题表
    create table TopicT(
    	Tid int primary key,
    	Tname nvarchar2(100) not null
    );
    
    --创建帖子表
    create table PostT(
    	Tid int not null,
    	Pid int primary key,
    	--帖子名称
    	Pname nvarchar2(100) not null,
    	--帖子内容
    	Pcontent nvarchar2(1000) not null,
    	--发帖时间
    	Pdate timestamp default sysdate,
    	Usid int not null,
    	--回复数
    	Replynum int default 1,
    	--最后回复时间
    	Lastreplytime timestamp default sysdate,
    	--隐藏标识(0显示,1隐藏)
    	Screenmark int default 0,
    	foreign key(Tid) references TopicT(Tid),
    	foreign key(Usid) references UserT(Usid)
    );
    
    --创建回复表
    create table ReplyT(
    	Pid int not null,
    	--回复楼层
    	Replyfloor int default 2,
    	--回复内容
    	Replycontent nvarchar2(1000) not null,
    	--回复时间
    	Replytime timestamp default sysdate,
    	Usid int not null,
    	foreign key(Pid) references PostT(Pid),
    	foreign key(Usid) references UserT(Usid)
    );
    
    insert into UserT values(1,'test','test',1);
    insert into UserT values(2,'admin','admin',1);
    insert into UserT values(3,'root','root',2);
    insert into UserT values(4,'rose','rose',2);
    insert into UserT values(5,'tom','tom',0);
    
    insert into TopicT values(1,'疫情防控');
    insert into TopicT values(2,'智能家居');
    insert into TopicT values(3,'节约资源');
    insert into TopicT values(4,'就业指导');
    insert into TopicT values(5,'爱护环境');
    
    insert into PostT values(1,1,'打卡出校','不开西一门真麻烦',TO_TIMESTAMP('2019-02-01 14:00:00','yyyy-MM-dd hh24:mi:ss'),1,1,TO_TIMESTAMP('2019-02-01 14:00:00','yyyy-MM-dd hh24:mi:ss'),0);
    insert into PostT values(2,2,'智能空调','空调能自动开关就好了',TO_TIMESTAMP('2019-02-02 14:00:00','yyyy-MM-dd hh24:mi:ss'),2,1,TO_TIMESTAMP('2019-02-02 14:00:00','yyyy-MM-dd hh24:mi:ss'),0);
    insert into PostT values(3,3,'节约用水','随手关水龙头',TO_TIMESTAMP('2019-02-04 14:00:00','yyyy-MM-dd hh24:mi:ss'),3,2,TO_TIMESTAMP('2019-03-09 10:54:50','yyyy-MM-dd hh24:mi:ss'),0);
    insert into PostT values(4,4,'刷算法题','每日一题,慢慢积累',TO_TIMESTAMP('2019-02-05 14:00:00','yyyy-MM-dd hh24:mi:ss'),4,1,TO_TIMESTAMP('2019-03-05 14:54:50','yyyy-MM-dd hh24:mi:ss'),0);
    insert into PostT values(4,5,'刷面试题','好想进BAT',TO_TIMESTAMP('2019-02-06 14:00:00','yyyy-MM-dd hh24:mi:ss'),4,3,TO_TIMESTAMP('2019-02-06 14:00:00','yyyy-MM-dd hh24:mi:ss'),0);
    insert into PostT values(5,6,'爱护花草','周末去浇水',TO_TIMESTAMP('2019-02-07 14:00:00','yyyy-MM-dd hh24:mi:ss'),5,1,TO_TIMESTAMP('2019-02-07 14:00:00','yyyy-MM-dd hh24:mi:ss'),0);
    
    insert into ReplyT values(3,2,'随手关水龙头,好评',TO_TIMESTAMP('2019-03-09 10:54:50','yyyy-MM-dd hh24:mi:ss'),1);
    insert into ReplyT values(5,2,'BAT是什么',TO_TIMESTAMP('2019-02-06 12:00:00','yyyy-MM-dd hh24:mi:ss'),1);
    insert into ReplyT values(5,2,'百度阿里腾讯',TO_TIMESTAMP('2019-02-06 14:00:00','yyyy-MM-dd hh24:mi:ss'),2);
    
    --DROP TABLE ReplyT;
    --DROP TABLE PostT;
    --DROP TABLE TopicT;
    --DROP TABLE UserT;
    

    PL/SQL实现脚本

    点击查看详细内容
    --1.注册
    create or replace procedure zc(puname nvarchar2,pw nvarchar2)
    as
      cursor cemp is select uname from usert;
    --  cursor cemp1 is select max(usid) from usert;
      pname nvarchar2(100);
      puid int := 0;
      pmax int:=0;
      i number :=0;
    begin
      select max(usid)into pmax from usert;
      open cemp;
      loop
        fetch cemp into pname;
        exit when cemp%notfound;
        if pname=puname then i:=1;
          exit;
        else i:=0;
        end if;
      end loop;
      close cemp;
      
    --  open cemp1;
    --    fetch cemp1 into pmax;
    --  close cemp1;
      puid:=pmax+1;
      if i=1 then dbms_output.put_line('用户名已存在,请输入新的用户');
      else insert into usert values(puid,puname,pw,0);
      commit;
      end if;
    end;
    
    --2.登录
    create or replace procedure dl(puname nvarchar2,pw nvarchar2)
    as
      cursor cemp is select uname,password from usert;
      pname nvarchar2(100);
      ppw nvarchar2(100);
      i number :=0;
    begin
      open cemp;
      loop
        fetch cemp into pname,ppw;
        exit when cemp%notfound;
        if pname=puname and ppw=pw then i:=1;
          dbms_output.put_line('登录成功!');
          exit;
        else i:=0;
        end if;
      end loop;
      if i=0 then dbms_output.put_line('请输入正确的用户名或密码!');
      close cemp;
      end if;
    end;
    
    --3.查看所有的主题
    create or replace procedure ckt
    as
      cursor cemp is select tid,tname from topict;
      ptid int;
      ptname nvarchar2(100);
    begin
      open cemp;
      loop
        fetch cemp into ptid,ptname;
        exit when cemp%notfound;
        dbms_output.put_line(ptid||'  '||ptname);
      end loop;
      close cemp;
    end;
    
    --04.查看某个主题下的帖子
    create or replace procedure getPostByTid(ptid in topict.tid%type)
    as
      pres postt%rowtype;
    begin
    	select * into pres from postt where tid=ptid;
      DBMS_OUTPUT.PUT_LINE('主题ID:'||pres.tid);
      DBMS_OUTPUT.PUT_LINE('帖子ID:'||pres.pid);
      DBMS_OUTPUT.PUT_LINE('帖子标题:'||pres.pname);
      DBMS_OUTPUT.PUT_LINE('帖子内容:'||pres.pcontent);
      DBMS_OUTPUT.PUT_LINE('发帖日期:'||pres.pdate);
      DBMS_OUTPUT.PUT_LINE('作者ID:'||pres.usid);
      DBMS_OUTPUT.PUT_LINE('回复数:'||pres.replynum);
      DBMS_OUTPUT.PUT_LINE('最后回复时间:'||pres.lastreplytime);
      DBMS_OUTPUT.PUT_LINE('屏蔽状态:'||pres.screenmark);
    exception
      when no_data_found then RAISE_APPLICATION_ERROR(-20001,'帖子不存在,请确认输入的帖子ID无误');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end getPostByTid;
    
    --05.查看某个帖子的主题
    create or replace procedure getTopicByPid(ppid in topict.tid%type)
    as
      pres topict%rowtype;
      ptid postt.tid%type;
    begin
    	select tid into ptid from postt where pid=ppid;
      select * into pres from topict where tid=ptid;
      DBMS_OUTPUT.PUT_LINE('主题ID:'||pres.tid);
      DBMS_OUTPUT.PUT_LINE('主题名称:'||pres.tname);
    exception
      when no_data_found then RAISE_APPLICATION_ERROR(-20002,'主题不存在,请确认输入的主题ID无误');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end getTopicByPid;
    
    --06.查看所有的主题,查看所有的帖子,按最后回复时间排序(分页)
    create or replace procedure getAllTopicsAndPosts(row number,page number)
    as
      --定义游标
      cursor c1 is
      select *
      from (
        select rownum "序号",ttid "主题ID",tname "主题名称",pid "帖子ID",pname "帖子名称",pcontent "帖子内容",
            to_char(pdate,'yyyy-mm-dd hh24:mi:ss') pdate,uusid "发帖人ID",uname "发帖人",
              replynum "回复数",to_char(lastreplytime,'yyyy-mm-dd hh24:mi:ss') "最后回复时间"
        from(
          select t.tid ttid,tname,pid,pname,pcontent,pdate,u.usid uusid,uname,replynum,lastreplytime
          from topict t,postt p,usert u
          where t.tid=p.tid(+) and p.usid=u.usid and screenmark!=1
        ) e1
      where rownum <= row*page
      ) e2
      where e2."序号" > row*(page-1)
      order by e2."主题ID",e2."最后回复时间" desc;
      --定义异常
      page_too_big exception;
      number_error exception;
      --定义变量
      prownum number;
      ptid topict.tid%type;
      ptname topict.tname%type;
      ppid postt.pid%type;
      ppname postt.pname%type;
      ppcontent postt.pcontent%type;
      ppdate varchar(40);
      puusid usert.usid%type;
      puname usert.uname%type;
      preplynum postt.replynum%type;
      plastreplytime varchar(40);
      counts number;
      i number:=0;
    begin
      if regexp_like(row,'^[1-9]d*$') and
        regexp_like(page,'^[1-9]d*$') then
        DBMS_OUTPUT.PUT_LINE('输入的数值都为正整数');
      else
        raise number_error;
      end if;
      --获取未隐藏帖子的总数
      select count(tid) into counts from postt where screenmark!=1;
      --判断页码是否过大
      if row*(page-1) >= counts then
        raise page_too_big;
      end if;
    	open c1;
      loop
        --退出条件,不写或者写成c1%notfound会出bug
        exit when i=(counts-row*(page-1));
        fetch c1 into prownum,ptid,ptname,ppid,ppname,ppcontent,ppdate,puusid,puname,preplynum,plastreplytime;
        DBMS_OUTPUT.PUT_LINE(
        '序号:'||prownum||'  '||
        '主题ID:'||ptid||'  '||
        '主题名称:'||ptname||'  '||
        '帖子ID:'||ppid||'  '||
        '帖子名称:'||ppname||'  '||
        '帖子内容:'||ppcontent||'  '||
        '发帖日期:'||ppdate||'  '||
        '发帖人ID:'||puusid||'  '||
        '发帖人:'||puname||'  '||
        '回复数:'||preplynum||'  '||
        '最后回复时间:'||plastreplytime
        );
        i:=i+1;
      end loop;
    exception
      when page_too_big then RAISE_APPLICATION_ERROR(-20003, '页码过大');
      when number_error then RAISE_APPLICATION_ERROR(-20004, '输入的数值非正整数');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end getAllTopicsAndPosts;
    
    --7.查看某个用户发表的帖子
    create or replace procedure lookPostt(uid in int)
    as
      cursor cemp is select usid,pcontent from postt;
      cursor cemp1 is select usid,replycontent from replyt;
      content nvarchar2(100);
      rcontent nvarchar2(100);
      sid int;
    begin
      open cemp;
      loop
        fetch cemp into sid,content;
        exit when cemp%notfound;
        if uid=sid then dbms_output.put_line(content);
        end if;
      end loop;
      close cemp;
      open cemp1;
      loop
        fetch cemp1 into sid,rcontent;
        exit when cemp1%notfound;
        if uid=sid then dbms_output.put_line(rcontent);
        end if;
      end loop;
      close cemp1;
    end;
    
    --08.搜索帖子(模糊查找)
    create or replace procedure fuzzySearch(keyword varchar2)
    as
      --定义游标
      cursor c1 is
      select *
      from (
        select rownum "序号",ttid "主题ID",tname "主题名称",pid "帖子ID",pname "帖子名称",
          pcontent "帖子内容",to_char(pdate,'yyyy-mm-dd hh24:mi:ss') "发帖日期",pusid "发帖人ID",
            uname "发帖人",replynum "回复数",to_char(lastreplytime,'yyyy-mm-dd hh24:mi:ss') "最后回复时间",
              replyfloor "回复楼层",replycontent "回复内容",rusid "回复人ID",runame "回复人",
                to_char(replytime,'yyyy-mm-dd hh24:mi:ss') "回复时间"
        from(
          select t.tid ttid,tname,p.pid,pname,pcontent,pdate,p.usid pusid,
            (select uname from usert where usert.usid=p.usid) uname,replynum,
              lastreplytime,replyfloor,replycontent,r.usid rusid,
                (select uname from usert where usert.usid=r.usid) runame,replytime
          from topict t,postt p,replyt r
          where t.tid=p.tid(+) and p.pid=r.pid(+) and screenmark!=1
        ) e1
      ) e2
      where e2."主题名称" like '%'||keyword||'%' or e2."帖子名称" like '%'||keyword||'%' or 
        e2."帖子内容" like '%'||keyword||'%' or e2."发帖人" like '%'||keyword||'%' or 
          e2."回复内容" like '%'||keyword||'%' or e2."回复人" like '%'||keyword||'%'
      order by e2."最后回复时间" desc,e2."回复时间" asc nulls last;
      info_not_found exception;
      --定义变量
      prownum number;
      ptid topict.tid%type;
      ptname topict.tname%type;
      ppid postt.pid%type;
      ppname postt.pname%type;
      ppcontent postt.pcontent%type;
      ppdate varchar(40);
      puusid usert.usid%type;
      puname usert.uname%type;
      preplynum postt.replynum%type;
      plastreplytime varchar(40);
      preplyfloor replyt.replyfloor%type;
      preplycontent replyt.replycontent%type;
      prusid usert.usid%type;
      pruname usert.uname%type;
      preplytime varchar(40);
      counts number;
      i number:=0;
    begin
      select count(*) into counts
      from (
        select rownum "序号",ttid "主题ID",tname "主题名称",pid "帖子ID",pname "帖子名称",
          pcontent "帖子内容",to_char(pdate,'yyyy-mm-dd hh24:mi:ss') "发帖日期",pusid "发帖人ID",
            uname "发帖人",replynum "回复数",to_char(lastreplytime,'yyyy-mm-dd hh24:mi:ss') "最后回复时间",
              replyfloor "回复楼层",replycontent "回复内容",rusid "回复人ID",runame "回复人",
                to_char(replytime,'yyyy-mm-dd hh24:mi:ss') "回复时间"
        from(
          select t.tid ttid,tname,p.pid,pname,pcontent,pdate,p.usid pusid,
            (select uname from usert where usert.usid=p.usid) uname,replynum,
              lastreplytime,replyfloor,replycontent,r.usid rusid,
                (select uname from usert where usert.usid=r.usid) runame,replytime
          from topict t,postt p,replyt r
          where t.tid=p.tid(+) and p.pid=r.pid(+) and screenmark!=1
        ) e1
      ) e2
      where e2."主题名称" like '%'||keyword||'%' or e2."帖子名称" like '%'||keyword||'%' or 
        e2."帖子内容" like '%'||keyword||'%' or e2."发帖人" like '%'||keyword||'%' or 
          e2."回复内容" like '%'||keyword||'%' or e2."回复人" like '%'||keyword||'%'
      order by e2."最后回复时间" desc,e2."回复时间" asc nulls last;
      --判断是否有结果
      if counts=0 then
        raise info_not_found;
      end if;
    	open c1;
      loop
        --退出条件,不写或者写成c1%notfound会出bug
        exit when i=counts;
        fetch c1 into prownum,ptid,ptname,ppid,ppname,ppcontent,ppdate,puusid,puname,
          preplynum,plastreplytime,preplyfloor,preplycontent,prusid,pruname,preplytime;
        DBMS_OUTPUT.PUT_LINE(
        '序号:'||prownum||'  '||
        '主题ID:'||ptid||'  '||
        '主题名称:'||ptname||'  '||
        '帖子ID:'||ppid||'  '||
        '帖子名称:'||ppname||'  '||
        '帖子内容:'||ppcontent||'  '||
        '发帖日期:'||ppdate||'  '||
        '发帖人ID:'||puusid||'  '||
        '发帖人:'||puname||'  '||
        '回复数:'||preplynum||'  '||
        '最后回复时间:'||plastreplytime||'  '||
        '回复楼层:'||preplyfloor||'  '||
        '回复内容:'||preplycontent||'  '||
        '回复人ID:'||prusid||'  '||
        '回复人:'||pruname||'  '||
        '回复时间:'||preplytime||'  '
        );
        i:=i+1;
      end loop;
    exception
      when info_not_found then DBMS_OUTPUT.PUT_LINE('没有相关结果');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end fuzzySearch;
    
    --9.发布帖子(触发器,更新用户表中的发帖数)
    create or replace procedure postMessage(tnamee nvarchar2,pnamee nvarchar2,pcontentt nvarchar2,uid int)
    --主题,内容,用户id
    as 
      cursor cemp is select tname,tid from topict;
      tidmax int;
      pidmax int;
      pdate TIMESTAMP(6);
      date1 TIMESTAMP(6);
      name nvarchar2(100);
      id int;
      topictId int;
      i int;
    begin
      i:=0;
      open cemp;
      loop
        fetch cemp into name,id;
        exit when cemp%notfound;
        if name=tnamee then i:=1;
          dbms_output.put_line('主题表中有此主题!');
          exit;
        end if;
      end loop;
      close cemp;
    --  select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss')into pdate from dual;
      select max(pid) into pidmax from postt;
    --  帖子编号
      date1:=sysdate;
      if i=1 then insert into PostT values(id,pidmax+1,pnamee,pcontentt,date1,uid,1,date1,0);
      elsif i=0 then select max(tid) into topictId from topict;
        insert into topict values(topictId+1,tnamee);
        select max(tid) into tidmax from postt;
    --    主题编号
        insert into PostT values(tidmax+1,pidmax+1,pnamee,pcontentt,date1,uid,1,date1,0);
      end if;
      commit;
    end;
    
    --触发器
    create or replace trigger update1
    after insert
    on PostT
    for each row
    begin
      update usert set pnum=pnum+1 where usid=:new.usid;
      dbms_output.put_line('数据已更新!');
    end update1;
    
    --10.回复帖子(触发器,更新帖子表中的回复数)
    create or replace trigger tr_replyt_insert
    after insert
    on replyt
    for each row
    begin
      update postt set replynum=replynum+1 where pid=:new.pid;
      dbms_output.put_line('回复数已自动更新');
    end;
    
    create or replace procedure reply(in_pid number,in_floor number,in_content nvarchar2,in_usid number)
    as
      counts_pid number:=0;
      counts_usid number:=0;
      post_not_exist exception;
      user_not_exist exception;
      length_illegal exception;
      floor_illegal exception;
    begin
      select count(pid) into counts_pid from postt where pid=in_pid and screenmark!=1;
      select count(usid) into counts_usid from usert where usid=in_usid;
      if counts_pid=0 or in_pid is null then
        raise post_not_exist;
      end if;
      if counts_usid=0 or in_usid is null then
        raise user_not_exist;
      end if;
      if length(in_content)=0 or in_content is null then
        raise length_illegal;
      end if;
      if in_floor<=1 or in_floor is null then
        raise floor_illegal;
      end if;
      insert into replyt values(in_pid,in_floor,in_content,sysdate,in_usid);
      DBMS_OUTPUT.PUT_LINE('已回复');
    exception
      when post_not_exist then RAISE_APPLICATION_ERROR(-20005, '回复的帖子不存在');
      when user_not_exist then RAISE_APPLICATION_ERROR(-20006, '回复的用户不存在');
      when length_illegal then RAISE_APPLICATION_ERROR(-20007, '回复内容非法');
      when floor_illegal then RAISE_APPLICATION_ERROR(-20008, '回复楼层非法');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end reply;
    
    --11.查看有哪些用户(分页)
    create or replace procedure paging(row in int,page in int)
    as
      cursor cemp is select t.uname,t.usid
      FROM (SELECT ROWNUM AS rowno,usert.*
              FROM usert
               where ROWNUM <= row*page)t
     WHERE t.rowno >row*(page-1);
     uame nvarchar2(100);
     uid int;
    begin
      open cemp;
      loop
        fetch cemp into uame,uid;
        exit when cemp%notfound;
        dbms_output.put_line(uame||' '||uid);
      end loop;
      close cemp;
    end;
    
    --12.隐藏/显示帖子(隐藏/显示某个用户的某个帖子)
    create or replace procedure changePostStatus(in_usid number,in_pid number,in_status number)
    as
      counts_pid number:=0;
      counts_usid number:=0;
      post_not_exist exception;
      user_not_exist exception;
      status_illegal exception;
    begin
      select count(pid) into counts_pid from postt where pid=in_pid;
      select count(usid) into counts_usid from usert where usid=in_usid;
      if counts_pid=0 or in_pid is null then
        raise post_not_exist;
      end if;
      if counts_usid=0 or in_usid is null then
        raise user_not_exist;
      end if;
      if in_status not in (0,1) then
        raise status_illegal;
      end if;
      update postt set screenmark=in_status where pid=in_pid;
      if in_status=1 then
        DBMS_OUTPUT.PUT_LINE('帖子已隐藏');
      else
        DBMS_OUTPUT.PUT_LINE('帖子已显示');
      end if;
    exception
      when post_not_exist then RAISE_APPLICATION_ERROR(-20009, '帖子不存在');
      when user_not_exist then RAISE_APPLICATION_ERROR(-20010, '用户不存在');
      when status_illegal then RAISE_APPLICATION_ERROR(-20011, '状态设置非法');
      when others then RAISE_APPLICATION_ERROR(-20000,'其他异常');
    end changePostStatus;
    
    /*
    01.注册
    02.登录
    03.查看所有的主题
    04.查看某个主题下的帖子
    05.查看某个帖子的主题
    06.查看所有的主题,查看所有的帖子,按最后回复时间排序(分页)
    07.查看某个用户发表的的言论
    08.搜索帖子(模糊查找)
    09.发布帖子(触发器,更新用户表中的发帖数)
    10.回复帖子(触发器,更新帖子表中的回复数)
    11.查看有哪些用户(分页)
    12.隐藏/显示帖子(隐藏/显示某个用户的某个帖子)
    */
    --预处理
    set serveroutput on
    --程序入口
    declare 
    begin
    --  zc('abc','123456');  --01.注册,参数:用户名,密码
    --  dl('Abc','123456');  --02.登录,参数:用户名,密码
    --  ckt();  --03.查看所有的主题,参数:无
    --  getPostByTid(1);  --04.查看某个主题下的帖子,参数:主题ID
    --  getTopicByPid(4);  --05.查看某个帖子的主题,参数:帖子ID
    --  getAllTopicsAndPosts(3,2);  --06.查看所有的主题,查看所有的帖子,按最后回复时间排序(分页),参数:每页行数,查看第几页
    --  lookPostt(2);  --07.查看某个用户发表的的言论,参数:用户ID
    --  fuzzySearch('BATT');  --08.搜索帖子(模糊查找),参数:关键词
    --  postMessage('疫情防控','健康饮食','多吃蔬菜少吃油炸食品',3);  --09.发布帖子(触发器,更新用户表中的发帖数),参数:主题名称,帖子名称,帖子内容,用户ID
    --  reply(5,2,'冲冲冲!',1);  --10.回复帖子(触发器,更新帖子表中的回复数),参数:帖子ID,回复楼层,回复内容,用户ID
    --  paging(5,2);  --11.查看有哪些用户(分页),参数:每页行数,查看第几页
    --  changePostStatus(1,1,1);  ---12.隐藏/显示帖子(隐藏/显示某个用户的某个帖子),参数:用户ID,帖子ID,隐藏状态(0显示,1隐藏)
    end;
    
  • 相关阅读:
    centos6.8升级python3.5.2
    钓鱼
    斯诺登的密码
    模板,堆,小根堆
    哥德巴赫猜想(升级版)
    哥德巴赫猜想
    线性筛素数
    乒乓球
    数的重心模板
    笨小猴
  • 原文地址:https://www.cnblogs.com/ast935478677/p/14717711.html
Copyright © 2020-2023  润新知