數據庫的復,view,index,sequence

 

ORACLE SQL DAY08

Top

  1. 創建一張表account_90,表結構與account一致,沒有數據
  2. account_90表中包含所有的90後客戶
  3. 通過演示理解什麼是視圖
  4. 每個客戶選擇了哪些資費標準
  5. 視圖的維護
  6. 視圖中的with check option約束
  7. 視圖中的with read only約束
  8. 創建唯一性索引
  9. 創建聯合索引
  10. 創建函數索引
  11. 序列號的應用場景和實現

1 創建一張表account_90,表結構與account一致,沒有數據

1.1 問題

創建一張與account表結構一樣的表account_90,表中不包含數據。

1.2 方案

在create table中可以嵌套SELECT語句,即子查詢。若子查詢的返回記錄數爲0,新建的表就只有結構。1 = 2是永假式,任何表都不會返回記錄。

 
  1. where 1 = 2

1.3 實現

代碼實現:

 
  1. create tableaccount_90
  2. as
  3. select * from account
  4. where 1 = 2 ;

2 account_90表中包含所有的90後客戶

2.1 問題

account_90表中包含所有的90後客戶。

2.2 方案

在insert中可以嵌套SELECT語句,即子查詢。出生日期是90後的客戶通過子查詢實現。

 
  1. select * from account
  2. whereto_char(birthdate,'yyyy') between 1990 and 1999;

2.3 實現

代碼實現:

 
  1. insert intoaccount_90
  2. select * from account
  3. whereto_char(birthdate,'yyyy') between 1990 and 1999;

2.4 擴展

3 通過演示理解什麼是視圖

3.1 問題

理解什麼是視圖,通過實驗證明之。

3.2 方案

表是數據庫對象,視圖是另一種。它們既有相似之處,也有很大區別。通過演示,幫助同學們理解什麼是視圖?

3.3 實現

創建一張表,插入記錄,提交。

 
  1. drop table testpurge;
  2. create tabletest(
  3. c1number,
  4. c2number);
  5. insert into testvalues (1,1);
  6. insert into testvalues (1,2);
  7. insert into testvalues (2,2);
  8. commit;

用DDL語句創建一張視圖,我們可以像操作表那樣操作視圖。

 
  1. create or replace viewtest_v1
  2. as
  3. select * from test
  4. wherec1 = 1;
  5. desctest_v1
  6. NameNull? Type
  7. ----------------------------------------- -------- --------
  8. C1 NUMBER
  9. C2 NUMBER
  10. select * fromtest_v1;
  11. C1 C2
  12. ---------- ----------
  13. 1 1
  14. 1 2

向視圖test_v1中插入一條記錄(1,3),查看test_v1和test中的變化

 
  1. insert intotest_v1values (1,3);
  2. select * fromtest_v1;
  3. C1 C2
  4. ---------- ----------
  5. 1 1
  6. 1 2
  7. 1 3
  8. select * fromtest;
  9. SQL> select * fromtest;
  10. C1 C2
  11. ---------- ----------
  12. 1 1
  13. 1 2
  14. 2 2
  15. 1 3

向表test中插入一條記錄(1,4),查看test_v1和test中的變化:

 
  1. insert into testvalues (1,4);
  2. select * fromtest_v1;
  3. C1 C2
  4. ---------- ----------
  5. 1 1
  6. 1 2
  7. 1 3
  8. 1 4
  9. select * fromtest;
  10. C1 C2
  11. ---------- ----------
  12. 1 1
  13. 1 2
  14. 2 2
  15. 1 3
  16. 1 4

向視圖test_v1中插入一條記錄(2,3),查看test_v1和test中的變化

 
  1. insert intotest_v1values (2,3);
  2. select * fromtest_v1;
  3. C1 C2
  4. ---------- ----------
  5. 1 1
  6. 1 2
  7. 1 3
  8. 1 4
  9. select * fromtest;
  10. C1 C2
  11. ---------- ----------
  12. 1 1
  13. 1 2
  14. 2 2
  15. 1 3
  16. 1 4
  17. 2 3

通過上述演示,我們發現視圖類似於windows中的快捷方式。結論:視圖就是一條SELECT語句,不佔用單獨的存儲空間,從視圖中查詢實際是執行視圖對應的SELECT語句。

 
  1. selectview_name,text fromuser_views
  2. whereview_name = 'TEST_V1';
  3. VIEW_NAME     TEXT
  4. ---------- ---------------------------
  5. TEST_V1     select "C1","C2" from test
  6.     wherec1 = 1

3.4 擴展

4 每個客戶選擇了哪些資費標準

4.1 問題

創建一張視圖,包含客戶名稱account表的real_name,unix服務器ip地址service表的unix_host, 資費編號cost表的id,資費信息描述cost表的descr。結果集中值包含開通了遠程登錄業務的客戶。

圖 - 1

4.2 方案

寫創建視圖語句的核心是寫SELECT語句,視圖中包含的列來自account表、service表、cost表,即三張表的連接操作。

 
  1. from account a join service s
  2. ona.id = s.account_id
  3. join cost c
  4. ons.cost_id = c.id;

每多一張表會多一個join on操作。

4.3 實現

代碼實現:

 
  1. create or replace viewaccount_cost_v
  2. as
  3. selecta.real_name,s.unix_host,c.id,c.descr
  4. from account a join service s
  5. ona.id = s.account_id
  6. join cost c
  7. ons.cost_id = c.id;

4.4 擴展

所有的客戶都在結果集中

圖 - 2

代碼實現如下:

 
  1. create or replace viewaccount_cost_v
  2. as
  3. selecta.real_name,s.unix_host,c.id,c.descr
  4. from account a left join service s
  5. ona.id = s.account_id
  6. left join cost c
  7. ons.cost_id = c.id;
  8. create or replace viewaccount_cost_v
  9. selecta.real_name,t.unix_host,t.descr
  10. from account a left join
  11. (selects.account_id,s.unix_host,c.descr
  12. from service s join cost c
  13. ons.cost_id = c.id) t
  14. ona.id = t.account_id
  15. create or replace viewaccount_cost_v
  16. as
  17. selecta.real_name,s.unix_host,c.id,c.descr
  18. from account a left join service s
  19. ona.id = s.account_id
  20. left join cost c
  21. ons.cost_id = c.id;
  22. create or replace viewaccount_cost_v
  23. as
  24. selectreal_name,c.name
  25. from (select *
  26. from account a left join service s
  27. ona.id=s.account_id) aa left join cost c
  28. onaa.cost_id =c.id

5 視圖的維護

5.1 問題

若將源表刪除,基於源表的視圖會發生怎樣的變化?

5.2 方案

視圖是一個依賴表的數據庫對象,查詢視圖最終都要通過查詢源表實現。如果源表的結構發生變化,對視圖的操作就有可能出問題。查看視圖的狀態是幫助我們發現視圖是否可用的方法。

5.3 實現

代碼實現如下:

視圖test_v1基於表test,此時它的狀態爲valid:

 
  1. selectview_name,text fromuser_views
  2. whereview_name = 'TEST_V1';
  3. VIEW_NAME     TEXT
  4. ---------- ---------------------------
  5. TEST_V1     select "C1","C2" from test
  6.     wherec1 = 1
  7. columnobject_name format a15
  8. columnobject_type format a10
  9. selectobject_name,object_type,status fromuser_objects
  10. whereobject_name = 'TEST_V1';
  11. OBJECT_NAMEOBJECT_TYP STATUS
  12. --------------- ---------- ------
  13. TEST_V1 VIEW VALID

將test表刪除,檢查視圖test_v1的狀態:

 
  1. drop table testpurge;
  2. desctest_v1
  3. ERROR:
  4. ORA-24372: invalid object for describe
  5. 提示:視圖test_v1是無效的數據庫對象
  6. select * fromtest_v1;
  7. ERROR at line 1:
  8. ORA-04063: view "JSD1302.TEST_V1" has errors
  9. 提示:視圖test_v1有錯誤
  10. selectobject_name,object_type,status fromuser_objects
  11. whereobject_name = 'TEST_V1';
  12. OBJECT_NAMEOBJECT_TYP STATUS
  13. --------------- ---------- -------
  14. TEST_V1 VIEW INVALID
  15. 提示:test_v1的狀態轉變爲無效INVALID。
  16. alter viewtest_v1compile;
  17. Warning: View altered with compilationerrors.
  18. 提示:在不做任何修改的情況下,重新編譯視圖仍舊出錯。
  19. column text format a40
  20. column name format a10
  21. set linesize 200
  22. select * fromuser_errors;
  23. NAME TYPE SEQUENCE LINE POSITION TEXT ATTRIBUTEMESSAGE_NUMBER
  24. ------- ------ -- -- -- ------------------------------------- ----- -
  25. TEST_V1 VIEW 1 0 0 ORA-00942:table or view does not exist ERROR 0
  26. 提示:編譯出錯的原因是test表不存在。
  27. 創建test表以解決表不存在問題。
  28. create tabletest(c1number,c2number);
  29. selectobject_name,object_type,status fromuser_objects
  30. whereobject_name = 'TEST_V1';
  31. OBJECT_NAMEOBJECT_TYP STATUS
  32. --------------- ---------- -------
  33. TEST_V1 VIEW INVALID
  34. select * fromtest_v1;
  35. no rows selected
  36. OBJECT_NAMEOBJECT_TYP STATUS
  37. --------------- ---------- -------
  38. TEST_V1 VIEW VALID
  39. 原因:當drop源表,所有依賴源表的視圖都將變爲invalid。即視圖本身存在,因爲源表的丟失已經不能對視圖正常操作了;當重新定義源表後,再次查詢視圖,系統先會對其編譯:alterview_namecompile;若編譯成功,可以正常操作視圖。
  40. 結論:對源表進行DDL操作後,需要檢查數據庫對象的狀態是否有invalid,若有,需要改正。

5.4 擴展

6 視圖中的with check option約束

6.1 問題

通過視圖test_v1可以插入(2,3),但從視圖中不能查詢到該記錄,這樣的情況不符合邏輯,怎樣避免?

6.2 方案

可以對視圖定義約束,with check option約束就是用來解決能對視圖進行DML操作卻不能SELECT的問題。

 
  1. whereos_usernamelike 'h%'

6.3 實現

在創建視圖時增加with check option約束,該約束要求通過視圖插入的記錄必須符合where條件。

 
  1. create or replace viewtest_ck
  2. as
  3. select * from test
  4. wherec1 = 1 with checkoption;
  5. insert intotest_ckvalues (2,3);
  6. ERROR at line 1:
  7. ORA-01402: view WITH CHECK OPTIONwhere-clause violation

6.4 擴展

7 視圖中的with read only約束

7.1 問題

對於簡單視圖來說,如何實現不允許DML操作?

7.2 方案

在創建視圖時增加with read only約束,該約束能夠實現只讀。

7.3 實現

在創建視圖時增加with read only約束,該約束要求對視圖只能查詢,不能做DML操作。

 
  1. create or replace viewtest_ro
  2. as
  3. select * from test
  4. wherec1 = 1 with readonly;
  5. insert intotest_rovalues (1,5);
  6. ERROR at line 1:
  7. ORA-01733: virtual column not allowed here

7.4 擴展

8 創建唯一性索引

8.1 問題

爲表中的列創建唯一性索引。

8.2 方案

oracle提供了一種索引形式是唯一性索引,語法是:

 
  1. create unique index indname
  2. ontabname (colname);

要求該列的取值必須唯一。

8.3 實現

代碼實現:

 
  1. create tabletest(
  2. c1 number constrainttest_c1_pk primarykey);
  3. insert into testvalues (1);
  4. insert into testvalues (1);
  5. ERROR at line 1:
  6. ORA-00001: uniqueconstraint (JSD1302.TEST_C1_PK) violated
  7. 第二條insert語句違反了唯一性約束
  8. alter table test drop primarykey;
  9. create unique indextest_c1_uniidx
  10. ontest(c1);
  11. insert into testvalues (1);
  12. insert into testvalues (1);
  13. ERROR at line 1:
  14. ORA-00001: uniqueconstraint (JSD1302.TEST_C1_UNIIDX) violated
  15. 注意:唯一性約束的名字是唯一性索引的名字
  16. 結論:唯一性約束是通過唯一性索引實現的,二者是等價的。

8.4 擴展

9 創建聯合索引

9.1 問題

爲表中的多列創建索引。

9.2 方案

oracle提供了一種索引形式是多列索引,在on關鍵字後的()裏可以跟多列。如果有兩列經常在一起查詢,適合建多列索引。

9.3 實現

代碼實現

 
  1. create tabletest(
  2. c1 number constrainttest_c1_pk primarykey,
  3. c2number,
  4. c3number);
  5. create indextest_c2_c3_idx
  6. ontest(c2,c3);

9.4 擴展

10 創建函數索引

10.1 問題

oracle爲什麼提供函數索引?怎樣創建函數索引?

10.2 方案

若在c2列上創建普通索引,where round(c2) = 10是用不了該索引的,oracle仍然會用全表掃描的方式查詢數據,要想提高查詢效率,必須使用函數索引。

 
  1. ontabname (funame(colname,..))

10.3 實現

代碼實現

 
  1. create tabletest(
  2. c1 number constrainttest_c1_pk primarykey,
  3. c2number,
  4. c3number);
  5. create indextest_c2_funidx
  6. ontest(round(c2));

10.4 擴展

11 序列號的應用場景和實現

11.1 問題

oracle爲什麼提供sequence?怎樣創建sequence?

11.2 方案

表中的PK/UK列要求取值一定要唯一,在程序執行尤其是併發執行時,怎樣保證每次插入的值是唯一的。oracle提供了自己的解決方案:使用sequence。

 
  1. create sequenceseq_name
  2. [increment by 1|integer]
  3. [start withinteger]
  4. [maxvalueinteger|nomaxvalue]
  5. [minvalueinteger|nominvalue]
  6. [cycle|nocycle]
  7. [cache 20|integer|nocache]

11.3 實現

代碼實現

 
  1. drop table testpurge;
  2. create tabletest(
  3. c1 number constrainttest_c1_pk primarykey);
  4. drop sequences_test_c1;
  5. create sequences_test_c1
  6. start with 1302001;
  7. insert into testvalues (s_test_c1.nextval);
  8. insert into testvalues (s_test_c1.nextval);
  9. commit;
  10. insert into testvalues (s_test_c1.nextval);
  11. rollback;
  12. insert into testvalues (s_test_c1.nextval);
  13. select * fromtest;
  14. C1
  15. ----------
  16. 1302001
  17. 1302002
  18. 1302004
  19. selects_test_c1.currval fromdual;
  20. CURRVAL
  21. ----------
  22. 1302004
  23. selectsequence_name,cache_size,last_number
  24. fromuser_sequences;
  25. SEQUENCE_NAMECACHE_SIZELAST_NUMBER
  26. ------------------------------ ---------- -----------
  27. S_TEST_C1 20 1302021

11.4 擴展

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章