zoukankan      html  css  js  c++  java
  • 初步学习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

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



  • 相关阅读:
    Eclipse 远程调试
    大数据处理方法bloom filter
    sicily 1259 Sum of Consecutive Primes
    sicily 1240. Faulty Odometer
    sicily 1152 简单马周游 深度优先搜索及回溯算法
    sicily 1050 深度优先搜索解题
    sicily 1024 邻接矩阵与深度优先搜索解题
    sicily 1156 二叉树的遍历 前序遍历,递归,集合操作
    sicily 1443 队列基本操作
    sicily 1006 team rankings 枚举解题
  • 原文地址:https://www.cnblogs.com/zz-newbie/p/15090652.html
Copyright © 2011-2022 走看看