天天看點

oracle學習筆記——視圖、索引

  1.視圖(VIEW)

1.1 概念

       視圖-----是由SELECT查詢語句(可以是單表或者多表查詢)定義的一個"邏輯表",隻有定義而無資料,是一個"虛表". 在建立視圖時,隻是将視圖的定義資訊儲存在資料字典中, 而并不将實際的資料複制到任何地方, 即不需要在表空間中為視圖配置設定存儲空間. 視圖是檢視和操縱基表資料的一種方法, 可以像使用表一樣使用視圖.

        tips: 查詢視圖沒有什麼限制, 插入/更新/删除視圖的操作會受到一定的限制; 所有針對視圖的操作都會影響到視圖的基表; 為了防止使用者通過視圖間接修改基表的資料, 可以将視圖建立為隻讀視圖(帶上with read only選項).

        視圖中的資料會随基表的更新而自動更新.

         視圖猶如基表的一個"視窗", 通過這個"視窗", 可以實施許多管理. 在一個視圖中可以定義的最大列數為1000, 與表的限制相同.

         視圖限制: 允許在視圖上生成限制, 如"主鍵限制、唯一鍵限制、外鍵限制、檢查限制"等. 但視圖上的限制不是強制性的, 而是聲明性的. 視圖限制的文法與表相同. 在建立視圖時, 可以使用with check option選項,給視圖定義check限制,使其隻能查詢、操作滿足check限制的記錄行.

1.2 作用

         1)提供各種資料表現形式, 可以使用各種不同的方式将基表的資料展現在使用者面前, 以便符合使用者的使用習慣(主要手段: 使用别名).

         2)隐藏資料的邏輯複雜性并簡化查詢語句, 多表查詢語句一般是比較複雜的, 而且使用者需要了解表之間的關系, 否則容易寫錯; 如果基于這樣的查詢語句建立一個視圖, 使用者就可以直接對這個視圖進行"簡單查詢"而獲得結果. 這樣就隐藏了資料的複雜性并簡化了查詢語句. 這也是oracle提供各種"資料字典視圖"的原因之一,all_constraints就是一個含有2個子查詢并連接配接了9個表的視圖(在catalog.sql中定義).

         3)執行某些必須使用視圖的查詢. 某些查詢必須借助視圖的幫助才能完成. 比如, 有些查詢需要連接配接一個分組統計後的表和另一表, 這時就可以先基于分組統計的結果建立一個視圖, 然後在查詢中連接配接這個視圖和另一個表就可以了.

        4)提供某些安全性保證. 視圖提供了一種可以控制的方式, 即可以讓不同的使用者看見不同的列, 而不允許通路那些敏感的列, 這樣就可以保證敏感資料不被使用者看見.

        5)簡化使用者權限的管理. 可以将視圖的權限授予使用者, 而不必将基表中某些列的權限授予使用者, 這樣就簡化了使用者權限的定義.

1.3 建立視圖

        權限: 要在目前方案中建立視圖, 使用者必須具有create view系統權限; 要在其他方案中建立視圖, 使用者必須具有create any view系統權限. 視圖的功能取決于視圖擁有者的權限.

        文法: create [ or replace ] [ force ] view [schema.]view_name

                      [ (column1,column2,...) ]

                      as

                      select ...

                      [ with check option ] [ constraint constraint_name ]

                      [ with read only ];

        tips:

        or replace: 如果存在同名的視圖, 則使用新視圖"替代"已有的視圖

        force: "強制"建立視圖,不考慮基表是否存在,也不考慮是否具有使用基表的權限

        column1,column2,...:視圖的列名, 列名的個數必須與select查詢中列的個數相同; 如果select查詢包含函數或表達式, 則必須為其定義列名. 此時, 既可以用column1, column2指定列名, 也可以在select查詢中指定列名.

        with check option: 指定對視圖執行的dml操作必須滿足“視圖子查詢”的條件即,對通過視圖進行的增删改操作進行"檢查",要求增删改操作的資料, 必須是select查詢所能查詢到的資料,   否則不允許操作并傳回錯誤提示. 預設情況下, 在增删改之前"并不會檢查"這些行是否能被select查詢檢索到.

        with read only:建立的視圖隻能用于查詢資料, 而不能用于更改資料.

1.3.1 建立簡單視圖

         是指基于單個表建立的,不包含任何函數、表達式和分組資料的視圖。

         示例1:基于emp表建立一個vw_emp視圖

         create view vw_emp

         as

         select empno,ename,job,hiredate,deptno from emp; --------建立簡單視圖          desc vw_emp; --------象表一樣使用

         select * from vw_emp where deptno=10;--------查詢

         insert into vw_emp values(1234,'JACK','CLERK','29-4月-1963',10);--------增加

         update vw_emp set ename='劉德華' where ename='JACK';--------更新

         delete vw_emp where ename='劉德華'; --------删除

         create view vw_emp_readonly

         as

         select empno,ename,job,hiredate,deptno from emp

         with read only ; --------建立隻讀視圖,隻能用于執行select語句          delete from vw_emp_readonly where empno=1234;--------删除失敗          create view vw_emp_check

         as

         select empno,ename,job,hiredate,deptno

         from emp where deptno=10

         with check option constraint vw_emp_chk ;

         --------建立檢查視圖:對通過視圖進行的增删改操作進行檢查,

                                       要求增删改操作的資料必須是select查詢所能查詢到的資料。          

         insert into vw_emp_check

         values(1235,'JACK','CLERK','29-4月-1963',20);

         --------20号部門不在查詢範圍内,違反檢查限制

         delete from vw_emp_check where empno=1234;

         --------所删除的資料在查詢範圍内,不違反檢查限制 1.3.2 建立連接配接視圖

        是指基于多個表所建立的視圖,即,定義視圖的查詢是一個連接配接查詢。 主要目的是為了簡化連接配接查詢

         示例1: 查詢部門編号為10和30的部門及雇員資訊

              create view vw_dept_emp

              as

              select a.deptno,a.dname,a.loc,b.empno,b.ename,b.sal

              from dept a , emp b

              where a.deptno=b.deptno

              and a.deptno in (10,30);               select * from vw_dept_emp;

1.3.3 建立複雜視圖

        是指包含函數、表達式、或分組資料的視圖。主要目的是為了簡化查詢。 主要用于執行查詢操作,并不用于執行DML操作。

          注意:當視圖的select查詢中包含函數或表達式時,必須為其定義列别名。

          示例1:查詢目前每個崗位的平均工資、工資總和、最高工資和最低工資。

              create view vw_emp_job_sal

              (job,avgsal,sumsal,maxsal,minsal)

              as

              select job,avg(sal),sum(sal),max(sal),min(sal)

              from emp

              group by job;               select * from vw_emp_job_sal; 1.3.4 強制建立視圖

        正常情況下,如果基表不存在,建立視圖就會失敗。但是可以使用force選項強制建立視圖(前提:建立視圖的語句沒有文法錯誤!),此時該視圖處于失效狀态。

         示例1:

              create force view vw_test_tab

              as

              select c1,c2 from test_tab;--------會出現“警告: 建立的視圖帶有編譯錯誤。”               select object_name,status from user_objects

              where object_name='VW_TEST_TAB';--------視圖狀态:INVALID

              select * from vw_test_tab;--------報錯               create table test_tab--------先建表

              (c1 number(9) primary key, c2 varchar2(20),c3 varchar2(30));

              select * from vw_test_tab;--------自動編譯失效的視圖

              select object_name,status from user_objects

              where object_name='VW_TEST_TAB';--------視圖狀态:VALID                1.4 更改視圖

          在對視圖進行更改(或重定義)之前,需要考慮如下幾個問題:

          之一——由于視圖隻是一個虛表,其中沒有資料,是以更改視圖隻是改變資料字典中對該視圖的

                       定義資訊,視圖的所有基礎對象都不會受到任何影響

          之二——更改視圖之後,依賴于該視圖的所有視圖和PL/SQL程式都将變為INVALID(失效)狀态

          之三——如果以前的視圖中具有with check option選項,但是重定義時沒有使用該選項,

                       則以前的此選項将自動删除。 1.4.1 更改視圖的定義

          方法——執行create or replace view語句。這種方法代替了先删除(“權限也将随之删除”)

                       後建立的方法,會保留視圖上的權限,但與該視圖相關的存儲過程和視圖會失效。

          示例1:create or replace view v_test_tab

                      as

                      select c1,c2||' + '||c3 c23 from test_tab;

1.4.2 視圖的重新編譯

           文法:alter view 視圖名 compile;

           作用:當視圖依賴的基表改變後,視圖會“失效”。為了確定這種改變“不影響”視圖和依賴于該視圖的

                     其他對象,應該使用 alter view 語句“明确的重新編譯”該視圖,進而在運作視圖前發現重新

                     編譯的錯誤。視圖被重新編譯後,若發現錯誤,則依賴該視圖的對象也會失效;若沒有錯誤,

                     視圖會變為“有效”。

           權限:為了重新編譯其他模式中的視圖,必須擁有alter any table系統權限。

           注意:當通路基表改變後的視圖時,oracle會“自動重新編譯”這些視圖。

           示例1:select last_ddl_time,object_name,status

                       from user_objects

                       where object_name='V_TEST_TAB';——視圖的狀态:有效                        alter table test_tab modify (c2 varchar2(30));——修改c2列的長度                        select last_ddl_time,object_name,status

                       from user_objects

                       where object_name='V_TEST_TAB';——視圖的狀态:失效                        alter view v_test_tab compile;——明确的重新編譯                        select last_ddl_time,object_name,status

                       from    user_objects

                       where object_name='V_TEST_TAB';——視圖的狀态:有效

            思考:若上述代碼修改的不是列長,而是表名,結果又會如何?

                      <警告:更改的視圖帶有編譯錯誤;視圖狀态:失效>

1.5 删除視圖

        可以删除目前模式中的任何視圖;

        如果要删除其他模式中的視圖,必須擁有DROP ANY VIEW系統權限;

        視圖被删除後,該視圖的定義會從詞典中被删除,并且在該視圖上授予的“權限”也将被删除。

        視圖被删除後,其他引用該視圖的視圖及存儲過程等都會失效。

       示例1:drop view vw_test_tab; 1.6 檢視視圖

        使用資料字典視圖

         dba_views——DBA視圖描述資料庫中的所有視圖

         all_views——ALL視圖描述使用者“可通路的”視圖

         user_views——USER視圖描述“使用者擁有的”視圖          dba_tab_columns——DBA視圖描述資料庫中的所有視圖的列(或表的列)

         all_tab_columns——ALL視圖描述使用者“可通路的”視圖的列(或表的列)

         user_tab_columns——USER視圖描述“使用者擁有的”視圖的列(或表的列)          示例1:查詢目前方案中所有視圖的資訊

         desc user_views;

         set long 400;

         select view_name,text from user_views;

         示例1:查詢目前方案中指定視圖(或表)的列名資訊

         select * from user_tab_columns where table_name='VW_DEPT'; 1.7 在連接配接視圖上執行DML操作

         在視圖上進行的所有DML操作,最終都會在基表上完成;

         select 視圖沒有什麼限制,但insert/delete/update有一些限制 1.7.1 在視圖上執行DML操作的步驟和原理

         第一步:将針對視圖的SQL語句與視圖的定義語句(儲存在資料字典中)“合并”成一條SQL語句

         第二步:在記憶體結構的共享SQL區中“解析”(并優化)合并後的SQL語句

         第三步:“執行”SQL語句

                      示例:

                      假設視圖v_emp的定義語句如下:

                      create view v_emp

                      as

                      select empno,ename,loc

                      from employees emp,departments dept

                      where emp.deptno=dept.deptno and dept.deptno=10;                       當使用者執行如下查詢語句時:

                      select ename from v_emp

                      where empno=9876;                       oracle将把這條SQL語句與視圖定義語句“合并”成如下查詢語句:

                      select ename

                      from employees emp,departments dept

                      where emp.deptno=dept.deptno and dept.deptno=10

                      and empno=9876;         然後,解析(并優化)合并後的查詢語句,并執行查詢語句 1.7.2 查詢視圖“可更新”(包括“增删改”)的列

        使用資料字典視圖

         dba_updatable_columns——顯示資料庫所有視圖中的所有列的可更新狀态

         all_updatable_columns——顯示使用者可通路的視圖中的所有列的可更新狀态                                    

        user_updatable_columns——顯示使用者擁有的視圖中的所有列的可更新狀态

         示例1: 查詢v_stu_dept中的哪些列是可更新的

              select table_name,column_name,insertable,updatable,deletable

              from    user_updatable_columns

              where table_name='V_STU_DEPT'; 1.7.3 可更新連接配接視圖

        如果建立連接配接視圖的select查詢“不包含”如下結構,

        并且遵守連接配接視圖的“更新準則”,

       則這樣的連接配接視圖是“可更新”的:

        之一:集合運算符(union,intersect,minus)

        之二:DISTINCT關鍵字

        之三:GROUP BY,ORDER BY,CONNECT BY或START WITH子句

        之四:子查詢

        之五:分組函數

        之六:需要更新的列不是由“清單達式”定義的

        之七:基表中所有NOT NULL列均屬于該視圖 1.7.4 鍵值儲存表

        如果連接配接視圖中的一個“基表的鍵”(主鍵、唯一鍵)在它的視圖中仍然存在,

         并且“基表的鍵”仍然是“連接配接視圖中的鍵”(主鍵、唯一鍵);

         即,某列在基表中是主鍵|唯一鍵,在視圖中仍然是主鍵|唯一鍵

         則稱這個基表為“鍵值儲存表”。

         一般地,由主外鍵關系的2個表組成的連接配接視圖,外鍵表就是鍵值儲存表,而主鍵表不是。 1.7.5 連接配接視圖的更新準則

        之一:一般準則——(講)

                        任何DML操作,隻能對視圖中的鍵值儲存表進行更新,

                        即,“不能通過連接配接視圖修改多個基表”;

                        在DML操作中,“隻能使用連接配接視圖定義過的列”;

                        “自連接配接視圖”的所有列都是可更新(增删改)的

         之二:insert準則

                       在insert語句中不能使用“非鍵值儲存表”中的列(包括“連接配接列”);

                       執行insert操作的視圖,至少應該“包含”鍵值儲存表中所有設定了限制的列;

                       如果在定義連接配接視圖時使用了WITH CHECK OPTION 選項,

                       則“不能”針對連接配接視圖執行insert操作                                     

        之三:update準則

                        鍵值儲存表中的列是可以更新的;

                        如果在定義連接配接視圖時使用了WITH CHECK OPTION 選項,

                        則連接配接視圖中的連接配接列(一般就是“共有列”)和基表中的“其他共有列”是“不可”更新的,

                        連接配接列和共有列之外的其他列是“可以”更新的

       之四:delete準則

                        如果在定義連接配接視圖時使用了WITH CHECK OPTION 選項,

                        依然“可以”針對連接配接視圖執行delete操作 2 索引

       目标是為了提高查詢的速度,當使用者對查詢速度不滿意而需要對資料庫的性能進行調校時,優先考慮建立索引。

       資料庫中索引的概念與書索引的概念非常類似,

       不同之處在于資料庫索引用來在表中查找特定的行。

       索引缺點:

                      向表中“添加/删除”行時,必須花費額外的時間來更新該行的索引。

       建立索引的時機:

                      當需要從大表中檢索少數幾行時,都應該對列建立索引。

       基本準則:

                      當任何單個查詢要檢索的行<=整個表行數的10%時,索引就非常有用。

       索引的候選列:

                      應該是用來存儲很大範圍的值的列

       自動建立索引:

                      表的主鍵和唯一鍵将自動建立索引

2.1 文法

       create [unique] index 索引名 -------unique指定索引列中的值是唯一的,索引名建議以idx打頭

       on 表名(列1, 列2... ...) --------可以對多列建立索引,這種索引稱為“複合索引”

       [tablespace 表空間名]; --------省去後,索引将被存儲到使用者的預設表空間中

       提示:

       出于性能方面的原因,通常應該将索引與表存儲到不同的表空間中

       示例:

       create index idx_customers_lastname on customers(last_name);

2.2 查詢索引和索引列的資訊

      select * from user_indexes where table_name in('CUSTOMERS', 'EMPLOYEES');

      select * from user_ind_columns where table_name in('CUSTOMERS', 'EMPLOYEES');

2.3 修改索引

      alter index 索引名 rename to 新索引名

2.4 删除索引

      drop index 索引名