• 初步学习Oracle


    一、Oracle前言

    • 数据定义语言(DDL):create drop alter

    • 数据操纵语言(DML):insert select delete update

    • 事务控制语言(TCL):commit savepoint rollback

    • 数据控制语言(DCL):grant revoke

    --注意:建议Oracle代码不区分大小写:建议尽量用大写(因为写进去的小写最后会被转换为大写在去执行!)

    --建议尽量每行代码的后面加一个分号,因为在PLSQL Developer中可以执行,但是在SQL Plus中却执行不出来结果,另外一种情况下也执行不了!(全部选起来,再去点击执行按钮会报错)。

    二、Oracle中创建表和删除表以及添加约束和修改约束

    创建表及约束:

    create table student(
    sno number not null primary key,
    sname varchar2(30) not null unique,
    ssex char(6) default '女',
    sage number(3,0) check(sage>18 and sage<30),
    saddress varchar2(50)
    );
    --删除刚才创建的表
    drop table student;
    --插入一条数据
    insert into student
     (sno, sname, ssex, sage, saddress)
    values
     (1, 'aa', '男', 20, '教室');
    --查询
    select * from student;  
    --删除
    delete student where sno=1;
    --或者
    delete from student where sno=1;
    --修改
    update student set sage = 21 where sno=1;

    创建表及添加修改约束:

     --创建老师表
    create table teacher(
    tno number(10),
    sno number,
    name varchar(30)
    );
    --设置tno为主键
    alter table teacher add constraint tno_pk primary key(tno);
    --设置外键
    alter table teacher add constraint sno_fk foreign key(sno) references student(sno);
    --修改名字可以为空约束
    alter table student modify(sname null);
    --多行添加
    insert into student
     (select 2,'张三','男',24,'长沙' from dual
     union
     select 3,'李四','男',25,'武汉' from dual
     union
     select 4,'王五','男',25,'武汉' from dual
    );
    --注意:多行插入也可以和MySQL一样

    三、伪表和伪列

    伪表:

    --dual:伪表
    select 1+1 from dual;
    select lower('SDA') from dual;

    伪列:

    --伪列
    --rowid rownum
    --rowid:唯一性
    --rowid:让每一条记录都唯一起来。
    --伪列上查看前三条数据
    select a.*,rownum from student a where rownum<4;
    --或者
    select a.*,rownum from student a where rownum<=3;
    --注意:rownum只能小于或者小于等于,不能大于或单独的等于,oracle没有limit。

    连接:

    --||:连接符号,将两列并入一列
    select sname||sage from student;

    四、Oracle中创建表空间和删除

    一、创建表空间:
    --注意要用数据库管理员的身份创建(scott的权限不足)

    --1.创建一个比较简单的表空间
    create tablespace stu1
    --创建表空间名为stu
    --tablespace:表空间的关键字
    datafile 'd:stu1.dbf'
    --数据文件保存在d:/stu.dbf (文件的后缀名为dbf)
    --datafile:数据文件
    --注意:Oracle中的字符串用单引号('')
    size 100m
    --大小为100m
    --2.创建比较复杂的表空间
    create tablespace stu
    --创建表空间名为stu
    --tablespace:表空间的关键字

    datafile 'd:stu.dbf'

    size 100m

    AUTOEXTEND ON NEXT 32M MAXSIZE UNLIMITED
    --autoextend on:表空间大小不够用时自动扩展
    --next 32m 自动扩展增量为32MB
    --MAXSIZE UNLIMITED :最大空间:无限制
    LOGGING
    --logging 是对象的属性,创建数据库对象时,oracle 将日志信息记录到练级重做日志文件中。代表空间类型为永久型!
    EXTENT MANAGEMENT LOCAL
    --extent management local   代表管理方式为本地
    SEGMENT SPACE MANAGEMENT AUTO;
    --磁盘扩展管理方法:
    --使用该选项时区大小由系统自动确定。由于 Oracle 可确定各区的最佳大小,所以区大小是可变的。
    --删除表空间
    drop tablespace stu1

    ORACLE中,表空间是数据管理的基本方法,所有用户的对象要存放在表空间中,也就是用户有空间的使用权,才能创建用户对象.否则是不允许创建对象,因为就是想创建对象,如表,索引等,也没有地方存放,Oracle会提示:没有存储配额.

    因此,在创建对象之前,首先要分配存储空间.分配存储,就要创建表空间:

      创建表空间示例如下:

    CREATE TABLESPACE "SAMPLE"
    LOGGING
    DATAFILE D:ORACLEORADATAORA92LUNTAN.ora SIZE 5M
    EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO

    上面的语句分以下几部分:

    第一: CREATE TABLESPACE "SAMPLE"  创建一个名为 "SAMPLE" 的表空间.(对表空间的命名,遵守Oracle 的命名规范就可了.)

    ORACLE可以创建的表空间有三种类型:

    (1)TEMPORARY: 临时表空间,用于临时数据的存放;

    创建临时表空间的语法如下:

    CREATE TEMPORARY TABLESPACE "SAMPLE"......

    (2)UNDO : 还原表空间. 用于存入重做日志文件.

    创建还原表空间的语法如下:

    CREATE UNDO TABLESPACE "SAMPLE"......

    (3)用户表空间: 最重要,也是用于存放用户数据表空间

    可以直接写成: CREATE TABLESPACE "SAMPLE"

    TEMPORARY 和 UNDO 表空间是ORACLE 管理的特殊的表空间.只用于存放系统相关数据.

    第二: LOGGING

    有 NOLOGGING 和 LOGGING 两个选项,

    NOLOGGING: 创建表空间时,不创建重做日志.

    LOGGING 和NOLOGGING正好相反, 就是在创建表空间时生成重做日志.

    用NOLOGGING时,好处在于创建时不用生成日志,这样表空间的创建较快,但是没能日志,数据丢失后,不能恢复,但是一般我们在创建表空间时,是没有数据的,按通常的做法,是建完表空间,并导入数据后,是要对数据做备份的,所以通常不需要表空间的创建日志,因此,在创建表空间时,选择 NOLOGGING,以加快表空间的创建速度.

    第三: DATAFILE 用于指定数据文件的具体位置和大小.

    如: DATAFILE D:ORACLEORADATAORA92LUNTAN.ora SIZE 5M

    说明文件的存放位置是 D:ORACLEORADATAORA92LUNTAN.ora , 文件的大小为5M.

    如果有多个文件,可以用逗号隔开:

    DATAFILE D:ORACLEORADATAORA92LUNTAN.ora SIZE 5M,

    D:ORACLEORADATAORA92dd.ora SIZE 5M

    但是每个文件都需要指明大小.单位以指定的单位为准如 5M 或 500K.

    对具体的文件,可以根据不同的需要,存放大不同的介质上,如磁盘阵列,以减少IO竟争.

    指定文件名时,必须为绝对地址,不能使用相对地址.

    第四: EXTENT MANAGEMENT LOCAL 存储区管理方法

    在Oracle 8i以前,可以有两种选择,一种是在字典中管理(DICTIONARY),另一种是本地管理(LOCAL ),从9I开始,只能是本地管理方式.因为LOCAL 管理方式有很多优点.

    在字典中管理(DICTIONARY): 将数据文件中的每一个存储单元做为一条记录,所以在做DM操作时,就会产生大量的对这个管理表的Delete和Update操作.做大量数据管理时,将会产生很多的DM操作,严得的影响性能,同时,长时间对表数据的操作,会产生很多的磁盘碎片,这就是为什么要做磁盘整理的原因.

    本地管理(LOCAL): 用二进制的方式管理磁盘,有很高的效率,同进能最大限度的使用磁盘. 同时能够自动跟踪记录临近空闲空间的情况,避免进行空闲区的合并操作。

    第五: SEGMENT SPACE MANAGEMENT

    磁盘扩展管理方法:

    SEGMENT SPACE MANAGEMENT: 使用该选项时区大小由系统自动确定。由于 Oracle 可确定各区的最佳大小,所以区大小是可变的。

    UNIFORM SEGMENT SPACE MANAGEMENT:指定区大小,也可使用默认值 (1 MB)。

    第六: 段空间的管理方式:

    AUTO: 只能使用在本地管理的表空间中. 使用LOCAL管理表空间时,数据块中的空闲空间增加或减少后,其新状态都会在位图中反映出来。位图使 Oracle 管理空闲空间的行为更加自动化,并为管理空闲空间提供了更好的性,但对含有LOB字段的表不能自动管理.

    MANUAL: 目前已不用,主要是为向后兼容.

    第七: 指定块大小. 可以具体指定表空间数据块的大小.

    创建例子如下:

    1 CREATE TABLESPACE "SAMPLE"

    2 LOGGING

    3 DATAFILE D:ORACLEORADATAORA92SAMPLE.ora SIZE 5M,

    4 D:ORACLEORADATAORA92dd.ora SIZE 5M

    5 EXTENT MANAGEMENT LOCAL

    6 UNIFORM SEGMENT SPACE MANAGEMENT

    7* AUTO

    表空间已创建。

    要删除表空间,可以

    DROP TABLESPACE SAMPLE;

    五、Oracle中创建角色赋权和收权

    --创建角色、赋权、收权时注意要用数据库管理员的身份创建(scott的权限不足)

    --1.创建一个简单的角色
    create user sb
    --创建一个用户:用户名为sb
    identified by 123
    --该账号的密码为123

    --2.创建一个带有表空间的角色
    create user sc
    --创建一个用户:用户名为sc
    identified by 456
    --该账号的密码为456
    default tablespace stu
    --默认表空间为:stu

    --把CONNECT、RESOURCE角色授予用户sb
    GRANT CONNECT,RESOURCE TO sb;
    --允许用户查看 EMP 表中的记录
    GRANT SELECT ON emp TO sb;
    --允许用户更新 EMP 表中的记录
    GRANT UPDATE ON emp TO sb;

    --撤销用户epet的RESOURCE角色
    REVOKE RESOURCE FROM sb;

    --常用系统预定义角色
    --CONNECT:临时用户。
    --RESOURCE:更为可靠和正式的用户。
    --DBA:数据库管理员角色,拥有管理数据库的最高权限。

    六、PL/SQL

    --打印Hello World
    begin
    dbms_output.put_line('Hello World1');//输出语句
    dbms_output.put_line('Hello World2');
    end;

    --利用声明变量实现查询7369的所有信息
    --%type:取现有的数据表中的数据的类型
    --%rowtype:取表中一行的数据类型
    declare
    eid emp.empno%type:=7369; //将emp表中的empno列的数据类型赋给eid,并给eid赋值为7369
    emprow emp%rowtype; //将emp表中的一行赋给emprow
    begin
     select * into emprow from emp where empno=eid; //从emp表中取出一行,并赋值给emprow
    dbms_output.put_line('编号为'||eid||'的员工姓名为'||emprow.ename);
    end;

    斐波那契数列

    --斐波那契数列

    --loop循环
    declare
    a number:=1;
    b number:=0;
    c number:=0;
    i number:=1;
    begin
     loop
      c:=a+b;
      a:=b;
      b:=c;
      i:=i+1;
       exit when i>6;
       end loop;
      dbms_output.put_line(c);
    end;

    --while循环
    declare
    a number:=1;
    b number:=0;
    c number:=0;
    i number:=1;
    begin
     while(i<=6)loop
    c:=a+b;
    a:=b;
    b:=c;
    i:=i+1;
     end loop;
    dbms_output.put_line(c);
    end;

    --for循环
    declare
    a number:=1;
    b number:=0;
    c number:=0;
    i number:=1;
    begin
     for i in 1..30
       loop
        c:=a+b;
        a:=b;
        b:=c;
         end loop;
        dbms_output.put_line(c);
    end;
    --if-else语句
    --查询员工编号为7369的薪水,如果薪水大于600输出高薪水,如果小于600底薪水
    declare
    eid number(10):=7369;
    sal emp.sal%type;
    begin
     select sal into sal from emp where empno=eid;
     if sal>600 then
      dbms_output.put_line('高薪水');
       else dbms_output.put_line('底薪水');
       end if;
    end;

    --查询员工编号为7369的薪水,如果薪水大于1500输出高薪水,如果小于1500-900中等薪水,
    --小于900底薪水
    declare
    eid number(10):=7369;
    sal emp.sal%type;
    begin
     select sal into sal from emp where empno=eid;
     if(sal>1500) then
    dbms_output.put_line('高薪水');
    elsif(sal>900) then
    dbms_output.put_line('中等薪水');
     else dbms_output.put_line('底薪水');
     end if;
    end;

    --case
    --查询员工编号为7369的工资等级。注意:只能为固定值
    --800 A     950   B   1100   C    else   no
    --方法一:
    declare
    eid number(10):=7369;
    sal emp.sal%type;
    begin
     select sal into sal from emp where empno=eid;
     case sal
       when '800' then dbms_output.put_line('A');
       when '950' then dbms_output.put_line('B');
       when '1100' then dbms_output.put_line('C');
       else dbms_output.put_line('no');
     end case;
    end;

    函数递归

    --递归实现1+2+3+4加到100的和
    create or replace function test01(n in number)
    return number is
    begin
     if n=1 then return 1;
     else return (n+test01(n-1));
     end if;
     end test01;
     
    select test01(100) from dual;
    drop function test01;

    --递归求出第21位 1,1,2,3,5,8,13,21...(此处非递归)
    create or replace function test02(n in number)
    return number is
    a number(10):=1;
    b number(10):=0;
    c number(10):=0;
    begin
     for i in 1..n
       loop
        c:=a+b;
        a:=b;
        b:=c;
         end loop;
         return c;
     end test02;

    select test02(6) from dual;
    drop function test02;

    --1.编写一个函数,要求能将阿拉伯数字(a,b,c,d,e,f,g,h,i)分别替换为
    --(1,2,3,4,5,6,7,8,9),非数字全部替换为0,禁止使用replace
    create or replace function test03(str in varchar2)
    return varchar2 is
    newStr varchar2(100):='';
    r varchar2(2):='';
    begin
     for i in 1..length(str)
       loop
         select substr(str,i,1) into r from dual;
         case r
           when 'a' then newStr:=newStr||1;
           when 'b' then newStr:=newStr||2;
           when 'c' then newStr:=newStr||3;
           when 'd' then newStr:=newStr||4;
           when 'e' then newStr:=newStr||5;
           when 'f' then newStr:=newStr||6;
           when 'g' then newStr:=newStr||7;
           when 'h' then newStr:=newStr||8;
           when 'i' then newStr:=newStr||9;
             else newStr:=newStr||0;
         end case;
       end loop;
       return newStr;
     end test03;
     
    select test03('abcdklgasngoeirg;ajldgqeoihoiqehglds') from dual;
    drop function test03;

    --2.要求编写函数,要求能将传进来的字符串反序输出,比如'abcdef',要求输出为'fedcba'
    create or replace function test04(str in varchar2)
    return varchar2 is
    newStr varchar2(100):='';
    r varchar2(1):='';
    begin
     for i in 1..length(str)
       loop
        newStr:=substr(str,i,1)||newStr;
       end loop;
       return newStr;
     end test04;

    select test04('123456789') from dual;
    drop function test04;

    异常

    --系统自带异常
    --no_data_found、too_many_rows......
    --8.编写一个程序块,接受一个雇员名,从emp表中显示该雇员的工作岗位与薪水,
    --若输入的雇员名不存在,显示“该雇员不存在”信息。
    declare
    ejob emp.job%type;
    esal emp.sal%type;
    ename1 emp.ename%type:='SMITH';
    begin
     select job,sal into ejob,esal from emp where ename=ename1;
      dbms_output.put_line('工作岗位:'||ejob);
      dbms_output.put_line('薪水:'||esal);
      exception when no_data_found then dbms_output.put_line('该雇员不存在');
     end;
    --自定义异常
    declare
    eid emp.empno%type:=7369;
    esal emp.sal%type;
    mye exception; --声明异常
    begin
     select sal into esal from emp where empno=eid;
     if esal>2500 then
      dbms_output.put_line('不错不错');
       else
        raise mye; --抛异常
         end if;
        exception when mye then --处理异常
          dbms_output.put_line('加工资');
     end;

    --
    declare
    n_s number(5);
    e_my exception;
    pragma exception_init(e_my,-20001);
    begin
    select count(ename) into n_s from emp where ename like 'S%';
    if n_s=0 then
    raise e_my;
    end if;
    dbms_output.put_line('数量是'||n_s);
    exception
    when e_my then
    dbms_output.put_line('人员为空');
    end;

    游标

    --5.某公司要根据雇员的职位来加薪,公司决定按下列加薪结构处理:
    --             Designation   Raise
                 -----------------------
    --             Clerk         500
    --             Salesman       1000
    --             Analyst       1500
    --             Otherwise     2000
    --编写一个程序块,接受一个雇员名,从emp表中实现上述加薪处理。
    declare
    ejob emp.job%type;
    esal emp.sal%type;
    cursor myr(enames emp.ename%type) is select job,sal from emp where ename=enames for update of ename;
    begin
     open myr('SMITH');
     fetch myr into ejob,esal;
     case ejob
       when 'CLERK' then
         update emp set sal=(esal+500) where current of myr;
        dbms_output.put_line('加薪后的薪水:'||(esal+500));
       when 'SALESMAN' then
         update emp set sal=(esal+1000) where current of myr;
        dbms_output.put_line('加薪后的薪水:'||(esal+1000));
       when 'ANALYST' then
         update emp set sal=(esal+1500) where current of myr;
        dbms_output.put_line('加薪后的薪水:'||(esal+1500));
    --   when 'OTHERWISE' then dbms_output.put_line('加薪后的薪水:'||sal+2000);
       else
         update emp set sal=(esal+2000) where current of myr;
        dbms_output.put_line('加薪后的薪水:'||(esal+2000));
       end case;
       close myr;
     end;

    select * from emp
    --6.编写一个程序块,将emp表中雇员名全部显示出来。
    declare
    enames varchar(30);
    cursor myr is select ename from emp;
    begin
     open myr;
     loop
       fetch myr into enames;
       exit when myr%notfound;
      dbms_output.put_line(enames);
       end loop;
       close myr;
     end;


    --7.编写一个程序块,将emp表中前5人的名字显示出来。
    declare
    enames varchar(30);
    cursor myr is select ename from emp
    where rownum<=5;
    begin
     open myr;
     loop
     fetch myr into enames;
     exit when myr%notfound;
    dbms_output.put_line(enames);
     end loop;
     close myr;
     end;
     
     --2. 使用For循环,接受一个部门号,从emp表中显示该部门的所有雇员的姓名,工作和薪水。
    declare
    --enames emp.ename%type;
    --ejob emp.job%type;
    --esal emp.sal%type;-
    cursor myr(eid emp.deptno%type) is select ename,job,sal from emp where deptno=eid;
    begin
       for i in myr(30)
       loop
         --fetch myr into enames,ejob,esal;
        dbms_output.put_line(i.ename||'::'||i.job||'::'||i.sal);
         --dbms_output.put_line(enames||'::'||ejob||'::'||esal);
         end loop;
     end;


    select * from emp;

    --3. 使用带参数的游标,实现第2题。
    declare
    --enames emp.ename%type;
    --ejob emp.job%type;
    --esal emp.sal%type;-
    cursor myr(eid emp.deptno%type) is select ename,job,sal from emp where deptno=eid;
    begin
       for i in myr(30)
       loop
         --fetch myr into enames,ejob,esal;
        dbms_output.put_line(i.ename||'::'||i.job||'::'||i.sal);
         --dbms_output.put_line(enames||'::'||ejob||'::'||esal);
         end loop;
     end;


    --4.编写一个PL/SQL程序块,从emp表中对名字以“A”或“S”开始的所有雇员按他们基本薪水的10%给他们加薪。
    declare
    nums number(10):=0;
    cursor myr is select * from emp where ename like 'A%' or ename like 'S%' for update
    of ename;
    begin
     for i in myr
       loop
        nums:=i.sal*1.1;
         update emp set sal=nums where current of myr;
         end loop;
     end;
     
    select * from emp;
    --5. emp表中对所有雇员按他们基本薪水的10%给他们加薪,如果所增加后的薪水大于5000卢布,则取消加薪。
    declare
    nums number(10);
    cursor myr is select * from emp for update;
    begin
     for i in myr
       loop
        nums:=i.sal*1.1;
         if nums<=5000 then
           update emp set sal=nums where current of myr;
           end if;
         end loop;
     end;

    游标嵌套

    --游标嵌套
    --for循环
    declare
    cursor myr1 is select deptno from dept;
    cursor myr2(deptno1 dept.deptno%type) is select ename from emp where deptno=deptno1;
    begin
    for i in myr1
    loop
    for j in myr2(i.deptno)
    loop
    dbms_output.put_line(i.deptno||':'||j.ename);
    end loop;
    end loop;
    end;

    --loop循环
    declare
    deptno1 dept.deptno%type;
    enames emp.ename%type;
    cursor myr1 is select deptno from dept;
    cursor myr2(deptno2 dept.deptno%type) is select ename from emp where deptno=deptno2;
    begin
    open myr1;
    loop
    fetch myr1 into deptno1;
    exit when myr1%notfound;
    open myr2(deptno1);
    loop
    fetch myr2 into enames;
    exit when myr2%notfound;
    dbms_output.put_line(deptno1||' '||enames);
    end loop;
    close myr2;
    end loop;
    close myr1;
    end;

    REF游标和动态SQL

    --游标嵌套
    --for循环
    declare
    cursor myr1 is select deptno from dept;
    cursor myr2(deptno1 dept.deptno%type) is select ename from emp where deptno=deptno1;
    begin
     for i in myr1
       loop
          for j in myr2(i.deptno)
            loop
              dbms_output.put_line(i.deptno||':'||j.ename);
              end loop;
        end loop;
     end;
     
    --loop循环
    declare
    deptno1 dept.deptno%type;
    enames emp.ename%type;
    cursor myr1 is select deptno from dept;
    cursor myr2(deptno2 dept.deptno%type) is select ename from emp where deptno=deptno2;
    begin
     open myr1;
     loop
       fetch myr1 into deptno1;
       exit when myr1%notfound;
       open myr2(deptno1);
       loop
         fetch myr2 into enames;
         exit when myr2%notfound;
        dbms_output.put_line(deptno1||' '||enames);
         end loop;
         close myr2;
       end loop;
       close myr1;
     end;


    --REF游标
    --1、REF游标分为强类型和弱类型

    --2、强类型
    --查询emp表中所有的数据
    declare
    type myr1 is ref cursor return emp%rowtype;
    myr2 myr1;
    enames emp%rowtype;
    begin
     open myr2 for select * from emp;
     loop
       fetch myr2 into enames;
       exit when myr2%notfound;
      dbms_output.put_line(enames.ename);
       end loop;
       close myr2;
     end;
     
    --3、弱类型
    --查询emp表中所有的数据
    declare
    type myr1 is ref cursor;
    myr2 myr1;
    emps emp%rowtype;
    begin
     open myr2 for select * from emp;
     loop
       fetch myr2 into emps;
       exit when myr2%notfound;
      dbms_output.put_line(emps.ename);
       end loop;
       close myr2;
     end;


    --4、动态sql案例
    declare
    sal1 emp.sal%type:=1500;
    sal2 emp.sal%type:=2000;
    type myr1 is ref cursor;
    myr2 myr1;
    emps emp%rowtype;
    begin
     open myr2 for 'select * from emp where sal>:1 and sal<:2 order by sal desc'
     using sal1,sal2;
     loop
       fetch myr2 into emps;
       exit when myr2%notfound;
      dbms_output.put_line(emps.ename);
       end loop;
       close myr2;
     end;


    select ename from emp where sal>1500 and sal<2000;


    select * from scott.student;


    七、SQL高级

    同义词

    --同义词
    --私有同义词和公有同义词
    --创建一个同义词
    create synonym emm for scott.emp;
    --删除同义词
    drop synonym emm;
    --创建一个同义词
    create or replace synonym a for scott.emp;
    --运用
    select * from a;
    --创建一个公有的同义词
    grant create public synonym to scott;
    create or replace public synonym b for scott.emp;
    create or replace public synonym c for scott.emp;
    select * from b;
    select * from c;
    --授权
    grant drop public synonym to scott;
    drop public synonym b;
    --收权
    revoke drop public synonym from scott;

    序列

    --序列
    create sequence aa
    start with 1
    increment by 1
    maxvalue 100
    minvalue 1
    --查询序列
    select aa.nextval from dual;
    --查看当前值
    select aa.currval from dual;
    --删除序列
    drop sequence aa;
    --修改序列
    alter sequence aa maxvalue 1000;
    --序列使用
    create table stu(
    sid number,
    names varchar2(10)
    );

    insert into stu values(aa.nextval,'zzz');
    select * from stu;
    drop table stu;

    视图、索引

    --视图
    create or replace view bb
    as
    select * from stu;

    create or replace force view cc
    as
    select * from stu;

    drop view aa;
    drop view cc;

    --索引
    create index dd on stu(sid);
    drop index dd;

    存储过程

    --存储过程
    --不带参数存储过程
    create or replace procedure getname
    as
    enames varchar2(30);
    begin
     select ename into enames from emp where empno=7369;
    dbms_output.put_line(enames);
     end;

    --调用
    begin
    getname;
     end;
    call getname();
    drop procedure getname;

    --带参数的存储过程
    --根据员工编号查询的名字。
    create or replace procedure getnames(eno number)
    as
    enames varchar2(30);
    begin
     select ename into enames from emp where empno=eno;
    dbms_output.put_line(enames);
    exception when no_data_found then
      dbms_output.put_line('此人不存在');
       when others then
        dbms_output.put_line('有错!');
     end;
     
    --调用
    begin
    getnames(131);
    end;
    call getnames(131);

    --in和out参数(只能用begin  end;调用)
    --根据编号查询名字(名字要返回出来,存储过程中不打印)
    create or replace procedure selectname(eid in number ,enames out varchar2)
    as
    enames1 varchar2(30);
    begin
     select ename into enames1 from emp where empno=eid;
    enames:=enames1;
     end;

    --调用
    declare
    eid number(6):=7369;
    ename varchar2(30);
    begin
    selectname(eid,ename);
    dbms_output.put_line(ename);
     end;
     

    --c.in out 参数
    --实现a 和b的值交换。
    create or replace procedure selectname(a in out number,b in out number)
    as
    c number(4);
    begin
    c := a;
    a := b;
    b := c;
     end;

    --调用
    declare
    a number(4):=10;
    b number(4):=20;
    begin
    selectname(a,b);
    dbms_output.put_line('原来a为10,a:'||a);
    dbms_output.put_line('原来6为20,b:'||b);
     end;

    --总结:
    --in参数:只作为参数传进去。
    --out参数:返回的结果。
    --in out参数:既要作为参数传进去,又要作为结果返回出来。

    --存储过程的调用
    --begin end;可以调用所有的存储过程
    --call只能调用带参数的存储过程。调用无参数的时要加().不建议使用。容易和创建的()混淆。

    触发器

    --不能删除李文才
    --创建触发器
    create or replace trigger tridel  --创建触发器
    after delete--什么操作
    on stuInfo--表
    for each row --行触发
    begin
      --条件
      if(:old.stuName='李文才') then
      raise_application_error(-20004,'该生不能删除!');
      end if;
      end;
     
    --序列
    create sequence a
    start with 0
    increment by 1
    maxvalue 2000
    minvalue 0

    create table s3(
    no number(6),
    name varchar2(30)
    )

    insert into s3(name) values('cc')

    --创建触发器
    create or replace trigger triInsert
    before insert
    on s3
    for each row
     begin
       :new.no:=a.nextval;
       end;
       
    select * from s3;
    --禁用触发器
    alter trigger triInsert disable
    --启用
    alter trigger triInsert enable
    --删除触发器
    drop trigger triInsert
     
     
    --触发器
    --表级触发器
    create or replace trigger modify_stu
    before insert or update or delete on student
    begin
      if deleting then
        raise_application_error(-20001,'该表不允许删除数据');
      elsif updating then
        raise_application_error(-20002,'该表不允许修改数据');
      elsif inserting then
        raise_application_error(-20003,'该表不允许插入数据');
       end if;
    end;

    --行级触发器
    --after
    --创建触发器:将对student表的操作都记录到stu_log表中(update of 用于指定一个
    --或多个字段,指定字段被更新时才会触发触发器)
    create or replace trigger modify_stu
    after insert or delete or update of stu_name
    on student
    for each row
     begin
       if inserting then
         insert into stu_log values(1,'insert',sysdate,:new.stu_name);
      elsif deleting then
          insert into stu_log values(2,'delete',sysdate,:old.stu_name);
      elsif updating then
         insert into stu_log values(3,'update_old',sysdate,:old.stu_name);
         insert into stu_log values(4,'update_new',sysdate,:new.stu_name);
        end if;
    end;

    --before
    --创建触发器:实现id的隐式自增
    create or replace trigger modify_stu
    before insert on student
    for each row
    declare
    next_id number;
    begin
     select seq_test.nextval into next_id from dual;
     :new.id :=next_id;
    end;

    程序包

    --程序包
    --分为两部分:规范、主体
    --规范
    --1.程序包(函数和存储过程)
    --存储过程(根据编号查名字)
    --函数(根据编号查名字)
    --规范部分
    create or replace package pg is--或者as   创建程序包规范
    procedure noname(eid number);--声明存储过程
    function selectname(eid number) return varchar2;--声明函数
    end pg;--结束程序包规范
    --主体
    create or replace package body pg is--创建程序包主体
    procedure noname(eid number)--完成储存过程的主体
    is
    enames varchar2(30);
    begin
     select ename into enames from emp where empno=eid;
    dbms_output.put_line(enames);
     end;
    --函数
    function selectname(eid number) return varchar2--完成函数体
    is
    enames varchar2(30);
    begin
     select ename into enames from emp where empno=eid;
     return enames;
     end;
    end pg;

    --删除规范
    drop package pg;
    --删除主体
    drop package body pg;

    --执行顺序问题:先执行规范,再执行主体。

    --调用存储过程
    call pg.noname(7369);
    begin
    pg.noname(7369);
     end;
    --调用函数
    select pg.selectname(7369) from dual;


    --2.程序包(存储过程和游标嵌套使用)
    --根据编号查询
    --规范
    create or replace package pb is
    cursor c_emp(eid number) return emp%rowtype;--游标声明
    procedure pro;--根据编号查询
    end pb;

    --主体
    create or replace package body pb is
    cursor c_emp(eid number) return emp%rowtype --声明游标
    is
    select * from emp where empno=eid;
    procedure pro--声明存储过程
    is
    emprow emp%rowtype;
    begin
     open c_emp(7369);
     fetch c_emp into emprow;
    dbms_output.put_line(emprow.ename);
     close c_emp;--结束游标
     end;--结束存储过程
     end pb;--结束程序包


    --调用
    begin
    pb.pro;
     end;

    事务


    --commit:提交
    --rollback:回滚
    --savepoint:保存点

    --commit:提交
    --自动提交:(关键字有:alter 、 create 、 drop 、 grant 、 revoke等)
    --显示提交:(关键字有:insert、 update 、delete 等)
    --rollback:回滚
    --savepoint:保存点

    --创建表
    create table stu(
    sno number(3),
    sname varchar2(15)
    );

    select * from stu;

    insert into stu(sno, sname) values(1, 'aa');
    commit;

    insert into stu(sno, sname) values(2, 'bb');

    select * from stu;

    insert into stu(sno, sname) values(2, 'bb');
    commit;

    insert into stu(sno, sname) values(3, 'bb');
    rollback;

    insert into stu(sno, sname) values(4, 'bb');
    insert into stu(sno, sname) values(5, 'bb');
    savepoint aa;
    insert into stu(sno, sname) values(6, 'bb');
    insert into stu(sno, sname) values(7, 'bb');
    insert into stu(sno, sname) values(8, 'bb');
    rollback to aa;

    --总结:
    --commit:对显示操作,进行数据的提交
    --rollback:回滚到上次提交的位置。
    --savepoint:设置一个保存点。可以回滚到设置的那个点的位置。
    --PL/SQL Developer:软件在关闭的时候会帮我们提交我们没有提交的数据。

    八、SQL优化

    --数据库性能化

    --数据库性能优化采取的工作可以分为6个部分。
    --1.优化数据库结构设计。
    --2.优化SQL语句。
    --3.调整服务器内存分配。
    --4.调整硬盘I/O。
    --5.调整操作系统参数。
    --6.使用Oracle工具优化。

    --SQL语句优化。
    --1.选择合理的表名顺序
    --注意:列少的应放在最后面。(因为从右往左解释)。
    select * from emp;--8列
    select * from dept;--3列
    --性能差
    select * from dept a,emp b
    where a.deptno=b.deptno;
    --性能好
    select * from emp b,dept a
    where a.deptno=b.deptno;

    --2.避免使用*
    --差
    select * from dept;
    --好
    select deptno,dname,loc from dept;

    --3.高效删除重复的记录。
    delete from emp a
    where a.rowid > (select min(x.rowid)from emp x where x.empno=a.empno);

    --1.
    select * from student;
    --2.
    select a.*,a.rowid from student a;
    --3.
    select min(x.rowid)from student x;
    --4.
    select * from student a
    where a.rowid > (select min(x.rowid)from student x where x.sno=a.sno);
    --0  1
    -- 0 1 2 3 4 5 6 7
    -- 0 1 2 3 4 5 6 7 8 9
    -- 0 1 2 3 4 5 6 7 8 9 A B C D E F 10

    --4.减对表的查询(子查询)
    select * from emp;
    --3次
    select * from emp where sal=(select max(sal) from emp) and comm=(select max(comm) from emp);
    --优化
    select * from emp where (sal,comm)=(select max(sal),max(comm) from emp);
    --总结:适当的可以用where条件代替子查询

    --5.使用表别名
    select a.ename,b.dname from emp a,dept b where a.deptno=b.deptno;

    --6.exists代替in
    --找出deptno的薪水
    select ename from emp where deptno=20;

    select sal from emp where ename in(select ename from emp where deptno=20);

    select sal from emp a where exists(select * from emp b where deptno=20 and a.empno=b.empno );

    --7.用not exists 代替 not in.
    select sal from emp where ename not in(select ename from emp where deptno=20);

    select sal from emp a where not exists(select * from emp b where deptno=20 and a.empno=b.empno );
    --8.用表连接替换exists
    select ename from emp a where exists(select * from dept b where a.deptno=b.deptno and deptno=30);

    --优化
    select ename from emp a ,dept b where a.deptno=b.deptno and b.deptno=30;

    select ename from emp a
    inner join
    dept b
    on a.deptno=b.deptno and b.deptno=30;

    --9.用exists替换distinct
    select distinct deptno from emp;
    --优化
    select deptno from dept a where exists(select deptno from emp b where a.deptno=b.deptno);
    --10.索引优化。

    --总结:
    --1.在两表联查时,列少的写后面,l列多的写前面。
    --2.查询语句时,尽量少用*
    --3.尽量用where条件代替两表联查。
    --4.用exists替换distinct
    --5.使用表别名
    --6.exists代替in

    --这里优化只是属于一部分。



  • 相关阅读:
    什么时候用到存储过程
    Group By
    李航统计学习方法(第二版)(五):k 近邻算法简介
    数据可视化之powerBI基础(十三)熟练使用Power BI的日期切片器
    数据可视化之powerBI基础(十二)PowerBI导入Excel数据有哪几种方式?
    数据可视化之powerBI基础(十一)Power BI中的数据如何导出到Excel中?
    数据可视化之powerBI基础(十)快速度量值,帮你更快的进行数据分析
    数据可视化之powerBI基础(九)Power BI中的“新表”,你会用吗?
    数据可视化之powerBI基础(八)PowerBI的表格,你真的会用吗
    数据可视化之powerBI基础(七)一文带你熟悉PowerBI建模视图中的功能
  • 原文地址:https://www.cnblogs.com/zz-newbie/p/15090652.html
Copyright © 2020-2023  润新知