第一篇:數據庫實驗心得
我在sql server 索引基礎知識系列中,第一篇就講了記錄數據的基本格式。那里主要講解的是,數據庫的最小讀存單元:數據頁。一個數據頁是8k大小。
對于數據庫來說,它不會每次有一個數據頁變化后,就存到硬盤。而是變化達到一定數量級后才會作這個操作。這時候,數據庫并不是以數據頁來作為操作單元,而是以64k的數據(8個數據頁,一個區)作為操作單元。
區是管理空間的基本單位。一個區是八個物理上連續的頁(即 64 kb)。這意味著 sql server 數據庫中每 mb 有 16 個區。
為了使空間分配更有效,sql server 不會將所有區分配給包含少量數據的表。sql server 有兩種類型的區:
統一區,由單個對象所有。區中的所有 8 頁只能由所屬對象使用。
混合區,最多可由八個對象共享。區中八頁的每頁可由不同的對象所有。
通常從混合區向新表或索引分配頁。當表或索引增長到 8 頁時,將變成使用統一區進行后續分配。如果對現有表創建索引,并且該表包含的行足以在索引中生成 8 頁,則對該索引的所有分配都使用統一區進行。
為何會這樣呢?
其實很簡單:
讀或寫 8kb 的時間與讀或寫 64 kb的時間幾乎相同。
在 8 kb 到 64 kb 范圍之內,單個磁盤 i/o 傳輸操作所花的時間主要是磁盤取數臂和讀/寫磁頭運動的時間。
因此,從數學上來講,當需要傳輸 64 kb 以上的 sql 數據時,盡可能地執行 64 kb 磁盤傳輸是有益的,即分成數個64k的操作。
因為 64 kb 傳輸基本上與 8 kb 傳輸一樣快,而每次傳輸的 sql server 數據是 8 kb 傳輸的 8 倍。
我們通過一個實例來看 有and 操作符時候的最常見的一種情況。我們有下面一個表,create table [dbo].[member]([member_no] [dbo].[numeric_id] identity(1,1)not null, [lastname] [dbo].[shortstring] not null, [firstname] [dbo].[shortstring] not null, [middleinitial] [dbo].[letter] null, [street] [dbo].[shortstring] not null, [city] [dbo].[shortstring] not null, [state_prov] [dbo].[statecode] not null, [country] [dbo].[countrycode] not null, [mail_code] [dbo].[mailcode] not null, [phone_no] [dbo].[phonenumber] null, [photograph] [image] null, [issue_dt] [datetime] not null default(getdate()), [expr_dt] [datetime] not null default(dateadd(year,1,getdate())), [region_no] [dbo].[numeric_id] not null, [corp_no] [dbo].[numeric_id] null, [prev_balance] [money] null default(0), [curr_balance] [money] null default(0), [member_code] [dbo].[status_code] not null default(' '))
這個表具備下面的四個索引:
索引名 細節 索引的列
member_corporation_link nonclustered located on primary corp_no
member_ident clustered, unique, primary key located on primary member_no
member_region_link nonclustered located on primary region_no
memberfirstname nonclustered located on primary firstname
當我們執行下面的sql查詢時候,select m.member_no, m.firstname, m.region_nofrom dbo.member as mwhere m.firstname like 'k%' and m.region_no > 6 and m.member_no < 5000go
sql server 會根據索引方式,優化成下面方式來執行。
select a.member_no,a.firstname,b.region_nofrom(select m.member_no, m.firstname from dbo.member as m where m.firstname like 'k%' and m.member_no < 5000)a ,--這個查詢可以直接使用 memberfirstname 非聚集索引,而且這個非聚集索引覆蓋了所有查詢列--實際執行時,只需要 邏輯讀取 3 次
(select m.member_no, m.region_no from dbo.member as mwhere m.region_no > 6)b
--這個查詢可以直接使用 member_region_link 非聚集索引,而且這個非聚集索引覆蓋了所有查詢列--實際執行時,只需要 邏輯讀取 10 次
where a.member_no = b.member_no
不信,你可以看這兩個sql 的執行計劃,以及邏輯讀信息,都是一樣的。
其實上面的sql,如果優化成下面的方式,實際的邏輯讀消耗也是一樣的。為何sql server 不會優化成下面的方式。是因為 and 操作符優化的另外一個原則。
1/26 的數據和 1/6 的數據找交集的速度要比 1/52 的數據和 1/3 的數據找交集速度要慢。
select a.member_no,a.firstname,b.region_nofrom(select m.member_no, m.firstname from dbo.member as mwhere m.firstname like 'k%'--1/26 數據)a,(select m.member_no, m.region_no from dbo.member as mwhere m.region_no > 6 and m.member_no < 5000--1/3 * 1/ 2 數據)bwhere a.member_no = b.member_no
當然,我們要學習sql 如何優化的話,就會用到查詢語句中的一個功能,指定查詢使用哪個索引來進行。
比如下面的查詢語句
select m.member_no, m.firstname, m.region_nofrom dbo.member as m with(index(0))where m.firstname like 'k%' and m.region_no > 6 and m.member_no < 5000go
select m.member_no, m.firstname, m.region_nofrom dbo.member as m with(index(1))where m.firstname like 'k%' and m.region_no > 6 and m.member_no < 5000goselect m.member_no, m.firstname, m.region_nofrom dbo.member as m with(index(membercovering3))where m.firstname like 'k%' and m.region_no > 6 and m.member_no < 5000goselect m.member_no, m.firstname, m.region_nofrom dbo.member as m with(index(memberfirstname, member_region_link))where m.firstname like 'k%' and m.region_no > 6 and m.member_no < 5000go
這里 index 計算符可以是 0,1,指定的一個或者多個索引名字。對于 0,1 的意義如下:
如果存在聚集索引,則 index(0)強制執行聚集索引掃描,index(1)強制執行聚集索引掃描或查找(使用性能最高的一種)。
如果不存在聚集索引,則 index(0)強制執行表掃描,index(1)被解釋為錯誤。
總結知識點:
簡單來說,我們可以這么理解:sql server 對于每一條查詢語句。會根據實際索引情況(sysindexes 系統表中存儲這些信息),分析每種組合可能的成本。然后選擇它認為成本最小的一種。作為它實際執行的計劃。
成本代價計算的一個主要組成部分是邏輯i/o的數量,特別是對于單表的查詢。
and 操作要滿足所有條件,這樣,經常會要求對幾個數據集作交集。數據集越小,數據集的交集計算越節省成本。的項目中,竟然出現了濫用聚集索引的問題??磥頉]有培訓最最基礎的索引的意義,代價,使用場景,是一個非常大的失誤。這篇博客就是從這個角度來羅列索引的基礎知識。
使用索引的意義
索引在數據庫中的作用類似于目錄在書籍中的作用,用來提高查找信息的速度。
使用索引查找數據,無需對整表進行掃描,可以快速找到所需數據。
使用索引的代價
索引需要占用數據表以外的物理存儲空間。
創建索引和維護索引要花費一定的時間。
當對表進行更新操作時,索引需要被重建,這樣降低了數據的維護速度。
創建索引的列
主鍵
外鍵或在表聯接操作中經常用到的列
在經常查詢的字段上最好建立索引
不創建索引的列
很少在查詢中被引用
包含較少的惟一值
定義為 text、ntext 或者 image 數據類型的列
heaps是staging data的很好選擇,當它沒有任何index時
excellent for high performance data loading(parallel bulk load and parallel index creation after load)
excellent as a partition to a partitioned view or a partitioned table
聚集索引提高性能的方法,在前面幾篇博客中分別提到過,下面只是一個簡單的大綱,細節請參看前面幾篇博客。
何時創建聚集索引?
clustered index會提高大多數table的性能,尤其是當它滿足以下條件時:
獨特, 狹窄, 靜止: 最重要的條件
持續增長的,最好是只向上增加。例如:
identity
date, identity
guid(only when using newsequentialid()function)
聚集索引唯一性(獨特型的問題)
由于聚集索引的b+樹結構的葉子節點必須指向具體數據。如果你要建立聚集索引的列不唯一,并且你指定的創建的聚集索引是非唯一的聚集索引,則會有以下情況:
如果未使用 unique 屬性創建聚集索引,數據庫引擎 將向表自動添加一個四字節 uniqueifier 列。必要時,數據庫引擎 將向行自動添加一個 uniqueifier 值,使每個鍵唯一。此列和列值供內部使用,用戶不能查看或訪問。
第二篇:數據庫實驗心得
沒接觸數據庫的時候總是覺得它比較深奧 或是不可接近的電腦知識,盡管自己對電腦 非常感興趣,其實還是有些心理上的陌生 感。學習電腦就和我們平時的其它科目學習一樣感覺它有永無止境的知識,在這從初接 觸電腦時連個電腦的鍵盤都不敢動到現在 連硬盤都也修理,其中的過程是多么長啊,數據庫是我在高中時候聽過,到了大學漸漸 了解了些,但就其原理性的內容還不知道,也就是根本就不清楚什么是數據庫,只是知 道一個所謂的中國字典里的名詞。經過此次 的課程設計,我初步明白了數據庫的基本原 理。也已經掌握了數據庫的基本知識。我想 對我以后的更深度學習打下了基礎。這次課 程設計讓我知道了讓 vb 連接 sql 的方法。其實就是前臺和后臺的連接。有了這個思 想,我相信對以后是大有裨益的。
我按照系統工程軟件設計的要求,從需求分析,概念設計,總體設計,詳細 設計,系統測試等各個步驟,分步完成系統的各項任務,實現了系統中的學生信 息查詢,學生信息更新,學生信息添加等模塊的功能。在這短短的五天里我收獲如下:
1、鞏固和加深了對 C#的理解,提高綜合運用本課程所學知識的能力。
2、培養了我選用參考書,查閱手冊及文獻資料的能力。培養獨立思考,深 入研究,分析問題、解決問題的能力。
3、通過實際編譯系統的分析設計、編程調試,掌握應用軟件的分析方法和 工程設計方法。根據我在課程設計中遇到的問題,我將在以后的學習當中注意以下幾點:
1、認真上好專業實驗課,多在實踐中鍛煉自己。
2、寫程序的過程中要考慮周到,嚴密。
3、在做設計的時候要有信心,有耐心,切勿浮躁。
4、認真的學習課本知識,掌握課本中的知識點,并在此基礎上學會靈活運 用。
5、在課余時間里多寫程序,熟練掌握在調試程序的過程中所遇到的常見錯 誤,以便能節省調試程序的時間
第三篇:數據庫實驗
實驗1.1 使用SQL Server工具(Microsoft SQL Server Management Studio Express)管理數據庫 實驗內容:
(1)使用SSMS(SQL Server Management Studio)加入實驗數據庫。(2)使用SSMS可視化建立、修改和刪除數據庫、表。(3)使用SSMS對數據庫進行備份和恢復。
(4)使用SSMS對表進行查詢、插入、修改、刪除。實驗步驟:
(1)加入School數據庫。(2)建立Test數據庫。
(3)在數據庫中建立人員表PERSON(P#,Pname,Page)。更改表設置P#為主鍵,增加屬性Ptype(類型是CHAR,長度是10)。
(4)用SSMS的查詢功能(新建查詢)對PERSON表進行查詢、插入、修改、刪除等操作:首先插入兩條記錄;修改第二條記錄;刪除第二條記錄。(5)備份Test數據庫。(6)刪除表PERSON。(7)恢復Test數據庫。(8)刪除Test數據庫。
第四篇:數據庫實驗
3.實驗步驟
在學生選課數據庫中實現其查詢操作,寫出T-SQL語句(注:學生選課數據庫為前三次實驗課所建立的數
據庫)
一、簡單查詢實驗
(1)查詢選修了課程的學生學號。
(2)查詢選修課程號為0101的學生學號和成績,并要求對查詢結果按成績降序排列,如果成績相同則按
學號升序排列。
(3)查詢選修課程號為0101的成績在80~90分之間的學生學號和成績,并將成績乘以系數0.8輸出。
二、連接查詢實驗
(1)查詢每個學生的情況以及他(她)所選修的課程。
(2)查詢選修離散散學課程且成績為90分以上的學生學號、姓名及成績。
(3)查詢每一門課的間接先行課(即先行課的先行課)
三、嵌套查詢操作
(1)查詢0101課程的成績高于張林的學生學號和成績。
(2)查詢其他系中年齡小于計算機系年齡最大者的學生。
(3)查詢同王洪敏“數據庫原理”課程分數相同的學生的學號。
(4)查詢選修了全部課程的學生的姓名。
(5)查詢與學號為09001103的學生所選修的全部課程相同的學生學號和姓名。
(6)查詢至少選修了學號為09001103的學生所選修的全部課程的學生學號和姓名。
四、組合查詢和分組查詢
(1)查找選修“計算機基礎”課程的學生成績比此課程的平均成績大的學生學號、成績。
(2)查詢年齡大于女同學平均年齡的男同學姓名和年齡。
(3)列出各系學生的總人數,并按人數進行降序排列。
(5)查詢選修計算機基礎和離散數學的學生學號和平均成績。
4、要求
請按題號依次作答,完成在word文檔中,寫明班級學號姓名,于周日之于周日之前發至xcf7@163.com,獨立完成,嚴禁抄
第五篇:數據庫實驗答案
實驗四
五、實驗方法和步驟:
1.向數據庫的USERS表空間添加一個大小為10M的數據文件userdata02.dbf。
Alter tablespace users add datafile ‘c:oracleoradataorcluserdata02.dbf’ size 10M;2.向數據庫的TEMP表空間添加一個大小為5N的臨時數據文件temp02.dbf。
Alter tablespace temp add tempfile’c:oracleoradataorcltemp02.dbf’ size 5M;3.修改userdata02.dbf為自動增長方式,每次增長512k,沒有限制大小。
Alter database datafile ‘c:oracleoradataorcluserdata02.dbf’ autoextend on next 512k maxsize unlimited;
4.取消userdata02.dbf的自動增長方式。
Alter database datafile ‘c:oracleoradataorcluserdata02.dbf’ autoextend off;5.將userdata02.dbf大小設置為8MB。
Alter database datafile ‘c:oracleoradataorcluserdata02.dbf’ resize 8M;6.將userdata02.dbf設置為脫機。
Alter database datafile ‘c:oracleoradataorcluserdata02.dbf’ offline;7.將userdata02設置為聯機。
Alter database datafile ‘c:oracleoradataorcluserdata02.dbf’ online;8.改變userdata02的名稱。
(1)alter tablespace users offline;
(2)將userdata02.dbf重命名為userdata002.dbf;(3)alter tablesace users rename datafile ‘c:oracleoradataorcluserdata02.dbf’,‘c:oracleoradataorcluserdata002.dbf’;(4)alter tablespace users online;
9.查詢數據文件信息(包括數據文件動態信息;數據文件詳細信息;臨時數據文件信息)。(1)select name,file#,status,checkpoint_change# from V$DATAFILE;
(2)select tablespace_name,bytes,autoextensible,file_name from DBA_DATA_FILES;(3)select tablespace_name,file_name,autoextensible from DBA_TEMP_FILES;
實驗五 表空間、段、區、塊的管理
五、實驗方法和步驟:
1.編輯一個腳本文件TEST,腳本文件內容為創建一個永久性的Student表空間,區自動擴展,段采用手動管理方式,并執行腳本文件。
Create tablespace student datafile ‘c:oracleoradataora404orcltbs1_1.dbf’ 2.為數據庫的student表空間添加一個大小為10MB的新的數據文件。
Alter tablespace student add datafile ‘c:oracleoradataora404orcltbs1_2.dbf’ size 10M 3.創建一個臨時表空間mytemp,并為臨時表空間添加一個大小為10MB的臨時數據文件。
Create temporary tablespace mytemp tempfile ‘c:oracleoradataora404orcltemp1_1.dbf’ size 20M extent management local uniform size 16M;
Alter tablespace mytemp add tempfile c:oracleoradataora404orltemp1_2.dbf’ size 10M 4.將student表空間新添加的數據文件的大小改為20MB。
Alter database datafile c:oracleoradataora404orcltbs1_2.dbf’ resize 20M 5.將studnet表空間設置為offline;再設置為online。Alter tablespace student offline;Alter tablespace student online;6.將student表空間設置為只讀狀態。Alter tablespace student read only;7.為student表空間創建一個回退段。
Create rollback segment student_roll tablespace student;8.刪除student表空間及其所有內容。
Drop tablespace student including contents;9.查詢表空間基本信息。
Select tablespace_name, extent_management,a llocation_type, contents from DBA_TABLESPACE;10.查詢表空間數據文件信息。
Select file_name, blocks, tablespace_name from DBA_DATA_FILES;11.統計表空間空閑空間信息。
SELECT TABLESAPCE_NAME “TABLESPACE”, FILE_ID, COUNT(*)“PIECES”, MAX(BLOCKS)“MAXIMUM”, MIN(BLOCKS)“MINIMUM”, AVG(BLOCKS)“AVERAGE”, SUM(BLOCKS)“TOTAL” FROM DBA_FREE_SPACE GROUP BY TABLESPACE_NAME, FILE_ID;
12.查詢表空間空閑空間大小。
SELECT TABLESPACE_NAME, SUM(BYTES)FREE_SPACES FROM DBA_FREE_SPACE GROUP BY TABLESPACE_NAME;
13.查詢scott用戶emp表的某個員工元組的物理地址(ROWID)。SELECT ROWID, EMPNO FROM SCOTT.EMP WHERE EMPNO=7369;
實驗六 模式對象管理—基礎表
五、實驗方法和步驟:
1、創建一個表
目標:創建一個名為STUDENT的表,該表有ID(學號)、NAME(姓名)、SEX(性別)、COURSE(課程)、SCORE(成績)字段,并保存在USER01表空間。
(1)在SQL*PLUS中執行使用CREATE TABLE語句在某一表空間中創建STUDENTS表,并通過INSERT、SELECT、UPDATE、DELETE語句對表進行操作,各舉一例。(2)通過OEM控制臺新的表,并查看新表情況。Create table student(Id number primary key, Name varchar2(20), Sex char(1),Course varchar2(20), Score number(5,2))tablespace users
Insert into student(id)values(1);Select id from student;
Update student set id=2 where id=1;Delete from student where id=2;
2、創建一個臨時表
目標:創建一個名為TEMP01的事務級別臨時表,該表有ID(學號)、NAME(姓名)字段,并保存在temp表空間中。
Create global temporary table temp01(id number(2)primary key, name varchar(20))on commit delete rows;
3、修改表
目標:修改STUDENTS表的存儲參數;為表分配新的存儲空間;添加一個新的列;設置列為無用狀態(UNUSED)。
(1)在SQL*PLUS中執行ALTER TABLE語句修改STUDENTS表的存儲參數(修改pctfree和pctused分別為20和40)。
Alter table student pctfree 20;Alter table student ptused 40;
(2)在SQL*PLUS中執行ALTER TABLE語句在STUDENTS表分配大小為400KB的新區。Alter table student allocate extent(size 400k);
(3)在SQL*PLUS中執行ALTER TABLE語句在STUDENTS表新增加一個AGE列,列的類型為NUMBER(2)。Alter table student add(age number(2));
(4)在SQL*PLUS中執行ALTER TABLE語句在將STUDENTS表中的AGE設置為無用狀態。Alter table student set unused(age);
4、截斷表
目標:刪除表STUDENTS中的所有記錄。
(1)在SQL*PLUS中執行TRUNCATE TABLE語句刪除STUDENTS表中的所有記錄。Truncate table student;
(2)在SQL*PLUS中執行SELECT語句查看STUDENTS表中的內容。Select * from student;
5、查詢ORACLE數據庫的模式對象信息
目標:使用管理工具(SQL*PLUS或OEM)獲得有關數據庫模式對象的有關信息。
(1)用SCOTT帳戶登錄SQL*PLUS,顯示用戶,并通過用戶視圖USER_TABLES、USER_VIEWS、USER_INDEXS、USER_OBJECTS、USER_TRIGGERS、USER_SEQUENCES等模式對象信息。Show user
Select table_name from user_tables;Select view_name from user_views;Select index_name from user_indexes;Select object_name from user_objects;Select trigger_name from user_triggers;Select sequence_name from user_sequence;
(2)使用SCOTT帳戶登錄數據庫,在OME控制臺中查看SCOTT用戶的各種模式對象信息。
6、給表student表的nane列添加一個唯一值約束,并刪除該約束 Alter table student add constraint p_uk unique(name);Alter table student drop drop constraint p_uk;
實驗七 模式對象管理—視圖
五、實驗方法和步驟:
1、創建基礎表BOOKS,包含BOOK_ID,數字型,BOOK_NAME,可變長50位,AUTHOR,可變長20位,PRESS可變長50位,Price數字型,PUBLISH_DATE,日期型;并插入10條數據。Create table books(Book_id number primary key, Book_name varchar2(50)not null, Author varchar2(20), Press varchar2(50), Price number, Publishdate date);
2、關系視圖
(1)建立關系視圖V_BOOKS,包含書名、作者、出版社。Create view v_books as
Select book_id 編號,author 作者,press 出版社
from books;(2)查看視圖定義。
Select text from user_views where view_name=’VW_BOOKS’;(3)查看視圖內容。
Select * from vw_books;
(4)修改視圖,增加一個列出版日期。
Create or replace view VW_BOOKS As
select book_id 編號,author 作者,press 出版社,publishdate 出版日期
from books;(5)向基礎表增加一個屬性列“價格”,數字型。查看視圖的可用性狀態。
alter table boks add price int;
Select object_name,status from user_objects where object_name=’VW_BOOKS’ and object_type=’VIEW’;
(6)重新編譯V_BOOKS視圖。再查看視圖的可用性狀態
alter view vw_books compile
Select object_name,status from user_objects where object_name=’VW_BOOKS’ and object_type=’VIEW’;(7)刪除該視圖。
drop view vw_books;
3、內嵌視圖
(1)查詢價格由高到低處于前三位的書本信息,注意采用內嵌視圖的方式實現。
select * from
(select book_id,book_name ,price from books
order by price desc)where rownum<=3;
(2)利用內嵌視圖將所有書籍的價格增加10元。
update(select price from books)set price=price+10
實驗十 PL/SQL程序結構
五、實驗方法和步驟:
1.在SQL*Plus中使用PL/SQL塊處理EMP表中職工號7788的職工,如果工資小于5000那么把工資更改為5000。
(1)首先采用SCOTT用戶登錄;(2)查詢7788員工的工資是多少;
(3)定義聲明塊和執行塊,修改該員工工資;(4)再查詢該員工工資是多少; SQL>DECLARE
X NUMBER(7,2);BEGIN
SELECT sal INTO x FROM emp WHERE empno = 7788;
IF x < 5000
THEN UPDATE emp SET sal = 5000 WHERE empno = 7788;END IF;END;
2.利用三種循環控制結構向表中插入150條記錄。(1)創建一張表,用來記錄循環指針的值;
Create table temp_table(num_col number, info_col char(10));(2)利用LOOP循環向表中插入前50條記錄; DECLARE
v_counter BINARY_INTEGER :=1;BEGIN
LOOP
INSERT INTO temp_table values(v_counter,’loop index’);
v_counter := v_counter+1;
EXIT WHEN v_counter>50;
END LOOP;END;
(3)利用WHILE循環向表中插入51-100條記錄; DECLARE
v_counter BINARY_INTEGER :=1;BEGIN
WHILE v_counter<100 LOOP
INSERT INTO temp_table values(v_counter,’loop index’);
v_counter := v_counter+1;
END LOOP;END;
(4)利用FOR循環向表中插入101-150條記錄; DECLARE
v_counter BINARY_INTEGER :=1;BEGIN FOR v_counter IN 101..150 LOOP
INSERT INTO temp_table values(v_counter,’loop index’);
END LOOP;END;
(5)查看表中的信息。
SLELECT * FROM TEMP_TABL
實驗十一 游標
五、實驗方法和步驟:
1.聲明顯式游標
聲明一個游標用來讀取基表EMP中部門號是20且工作為分析員的職工: DECLARE Cursor c1 IS
SELECT ename, sal, hiredate FROM emp WHERE deptno = 20 AND job = 'ANALYST';v_ename VARCHAR2(10);v_sal NUMBER(7,2);v_hiredate date;begin OPEN c1;
FETCH c1 INTO v_ename, v_sal, v_hiredate;CLOSE c1;end;
2.游標的應用
(1)利用游標修改數據,如果EMP中部門號是20,工作為分析員的職工工資小于5000,更改為5000: DECLARE CURSOR c1 IS
SELECT empno, sal, hiredate, rowid
FROM emp WHERE deptno = 20 AND job = 'ANALYST' FOR UPDATE OF sal;emp_record c1%ROWTYPE;BEGIN OPEN c1;LOOP
FETCH c1 INTO emp_record;EXIT WHEN c1%NOTFOUND;IF emp_record.sal <5000 THEN
UPDATE emp set sal = 5000 where empno = emp_record.empno;END IF;END LOOP;CLOSE c1;END;
(2)利用游標,如果部門是SALES,地址不是DALLAS的,地址更改為DALLAS;如果部門不是SALES,地址不是NEW YORK的,地址更改為NEW YORK: DECLARE CURSOR c1 IS SELECT dname, loc FROM dept FOR UPDATE OF loc;Dept_rec c1%ROWTYPE;BEGIN OPEN c1;LOOP
FETCH c1 INTO dept_rec;EXIT WHEN c1%NOTFOUND;
IF dept_rec.dname = 'SALES' AND dept_rec.loc!= 'DALLAS'
THEN UPDATE dept SET LOC = 'DALLAS' WHERE CURRENT OF C1;ELSE IF DEPT_REC.DNAME!= 'SALES' AND DEPT_REC.LOC!= 'NEW YORK' THEN UPDATE dept SET LOC = 'NEW YORK' WHERE CURRENT OF C1;END IF;END LOOP;CLOSE c1;END;
實驗十二 存儲過程和函數
1.編寫一個存儲過程,用它顯示scott.dept、scott.emp表中各部門的名稱、員工總
數以及員工的工資總和和平均工資。
set serverout on;
create or replace procedure outputEMP as begin declare
cursor cEMP is
select dname,count(*),avg(sal),sum(sal)
from scott.emp,scott.dept
where scott.emp.deptno=scott.dept.deptno
group by dname;
d_name varchar2(14);
count_EMP number;
sum_sal number(7,2);
avg_sal number(7,2);
begin
open cEMP;
fetch cEMP into d_name,count_EMP,avg_sal,sum_sal;
while cEMP %found loop
dbms_output.put_line(d_name||','||count_EMP||','||avg_sal||','||sum_sal);
fetch cEMP into d_name,count_EMP,avg_sal,sum_sal;
end loop;
close cEMP;
end;
end outputEMP;2.編寫一個函數,用它計算0到指定數字(作為函數輸入參數)之間的整數和。set sertverout on;
create or replace function get_sum(maxNUM number)return number as begin
declare sumNUM number;
i number;
begin
sumNUM:=0;
i:=maxNum;
while i>0 loop
sumNUM:=sumNUM+i;
i:=i-1;
end loop;
return sumNUM;
end;end get_sum;
實驗十三 觸發器
1.編寫一個觸發器,用它把數據庫系統的關閉事件記錄到一個表(表結構自己設計)內。Create table shutdown_log(shut_user varchar2(20),shut_time date,shut_action varchar2(20));
create or replace trigger shutdown_record before shutdown on database begin
insert into shutdown_log values(user,sysdate,'關閉數據庫');end;
2.編寫一個行觸發器,把emp表增、刪、改操作前后員工的姓名和工資前后變化情況顯示處理。create or replace trigger trg_emp_dml_row
Before insert or update or delete on scott.emp
For each row
Begin
If inserting then
Dbms_output.put_line(:new.empno||’ ’||:new.ename);
Elsif updating then
Dbms_output.put_line(:old.sal||’ ’||:new.sal);
Else
Dbms_output.put_line(:old.empno||’ ’||:old.ename);
End if;
End trg_emp_dml_row;