zoukankan      html  css  js  c++  java
  • Oracle——索引,序列,触发器

    1.索引

      1)注意

        oracle创建主键时会自动在该列上创建索引

      2)索引原理

        A.  若没有索引,搜索某个记录时(例如查找name='wish')需要搜索所有的记录,因为不能保证只有一个wish,必须全部搜索一遍

        B. 若在name上建立索引,oracle会对全表进行一次搜索,将每条记录的name值哪找升序排列,然后构建索引条目(name和rowid),存储到索引段中,查询name为wish时即可直接查找对应地方

        C.创建了索引并不一定就会使用,oracle自动统计表的信息后,决定是否使用索引,表中数据很少时使用全表扫描速度已经很快,没有必要使用索引

      3)索引使用()

        A.创建索引的语法

    CREATE [UNIQUE] | [BITMAP] INDEX index_name  --unique表示唯一索引
    ON table_name([column1 [ASC|DESC],column2    --bitmap,创建位图索引
    [ASC|DESC],…] | [express])
    [TABLESPACE tablespace_name]
    [PCTFREE n1]                                 --指定索引在数据块中空闲空间
    [STORAGE (INITIAL n2)]
    [NOLOGGING]                                  --表示创建和重建索引时允许对表做DML操作,默认情况下不应该使用
    [NOLINE]
    [NOSORT];                                    --表示创建索引时不进行排序,默认不适用,如果数据已经是按照该索引顺序排列的可以使用

         B.修改索引

          重命名索引:alter index index_sno rename to bitmap_sno

          合并索引:表使用一段时间会产生数据碎片,此时重建索引或合并索引会很好:alter index index_sno coalesce;

          重建索引:alter index index_sno rebuild;

         C.删除索引

          drop index index_sno

         D.查看索引 

          create index index_sno on student('name');

          select * from all_indexes where table_name='student';

      4)索引分类

        A:B树索引

          就是我们不同的索引:create index index_sno on table('sno')

          应用场景:列基数大(列不重复数)时

        B:位图索引

          创建位图索引时,oracle会扫描整张表,并为索引列的每个取值建立一个位图(位图中,对表中每一行使用一位(bit,0或者1)来标识该行是否包含该位图的索引列的取值,如果为1,表示对应的rowid所在的记录包含该位图索引列值),最后通过位图索引中的映射函数完成位到行的ROWID的转换

          create bitmap index index_sno on table(sno);

          应用场景:基数小的列

        C:单列索引复合索引

        D:函数索引

          create index fbi on student (upper(name));

          select * from student where upper(name) ='WISH';
      

      5)原则

      1. 如果有两个或者以上的索引,其中有一个唯一性索引,而其他是非唯一,这种情况下oracle将使用唯一性索引而完全忽略非唯一性索引

      2. 至少要包含组合索引的第一列(即如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引)

      3. 小表不要简历索引

      4. 对于基数大的列适合建立B树索引,对于基数小的列适合简历位图索引

      5. 列中有很多空值,但经常查询该列上非空记录时应该建立索引

      6. 经常进行连接查询的列应该创建索引

      7. 使用create index时要将最常查询的列放在最前面

      8. LONG(可变长字符串数据,最长2G)和LONG RAW(可变长二进制数据,最长2G)列不能创建索引

      9.限制表中索引的数量(创建索引耗费时间,并且随数据量的增大而增大;索引会占用物理空间;当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度)

      6)注意事项

        

    1. 通配符在搜索词首出现时,oracle不能使用索引,eg:

    复制代码
    --我们在name上创建索引;
    
    create index index_name on student('name');
    
    --下面的方式oracle不适用name索引
    
    select * from student where name like '%wish%';
    
    --如果通配符出现在字符串的其他位置时,优化器能够利用索引;如下:
    
    select * from student where name like 'wish%';
    复制代码

     2. 不要在索引列上使用not,可以采用其他方式代替如下:(oracle碰到not会停止使用索引,而采用全表扫描)

    复制代码
    select * from student where not (score=100);
    
    select * from student where score <> 100;
    
    --替换为
    
    select * from student where score>100 or score <100
    复制代码

    3. 索引上使用空值比较将停止使用索引, eg:

    select * from student where score is not null;

    2.序列

      1)创建序列

      2)通过序列插入表数据自增长

        insert into textseq values(seq_textseq.nextval,'zs')

    3.同义词

      Create synonym dept for scott.dept;创建私有同义词

      drop synonym dept;删除私有同义词

      Create public synonym dept for scott.dept;创建共有同义词

      drop public sysnonym dept;删除共有同义词

      

     3.触发器

      http://blog.csdn.net/indexman/article/details/8023740/

      1)创建触发器的一般语法

        

    CREATE [OR REPLACE] TRIGGER trigger_name
    {BEFORE | AFTER }
    {INSERT | DELETE | UPDATE [OF column [, column …]]}
    [OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
    ON [schema.]table_name | [schema.]view_name 
    [REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
    [FOR EACH ROW ]
    [WHEN condition]
    PL/SQL_BLOCK | CALL procedure_name;

    BEFORE 和AFTER指出触发器的触发时序分别为前触发和后触发方式,前触发是在执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建的触发器。

           FOR EACH ROW选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操作影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则只能为行触发器。

               REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。

    WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。

        当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性。

     

      2)例子:建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。

    CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2; 
    CREATE OR REPLACE TRIGGER tr_del_emp 
       BEFORE DELETE --指定触发时机为删除操作前触发
       ON scott.emp 
       FOR EACH ROW   --说明创建的是行级触发器 
    BEGIN
       --将修改前数据插入到日志记录表 del_emp ,以供监督使用。
       INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
           VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );
    END;
    DELETE emp WHERE empno=7788;
    DROP TABLE emp_his;
    DROP TRIGGER del_emp;

      限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表

    CREATE OR REPLACE TRIGGER tr_dept_time
    BEFORE INSERT OR DELETE OR UPDATE 
    ON departments
    BEGIN
     IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日')) OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00') THEN
         RAISE_APPLICATION_ERROR(-20001, '不是上班时间,不能修改departments表');
     END IF;
    END;
  • 相关阅读:
    QQ空间留言的JS
    Session超时问题(AOP 过滤器)
    IFrame实现的无刷新(仿ajax效果)...
    NPOI帮助类(Excel转DataTable、DataTable转Excel)
    SignalR with ASP.NET MVC5 可用于倒计时同步
    我(webabcd)的文章索引
    WorkFlow4.0--入门到精通系列-专题索引
    Android利用Fiddler进行网络数据抓包
    IIS给网站地址配置成HTTPS的
    SQL SERVER 2005 获取表的所有索引信息以及删除和新建语句
  • 原文地址:https://www.cnblogs.com/xiaoping1993/p/6829509.html
Copyright © 2011-2022 走看看