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 索引名