1 -- Create table 學生信息 2 drop table HAND_STUDENT; 3 create table HAND_STUDENT 4 ( 5 STUDENT_NO VARCHAR2(10) not null, 6 STUDENT_NAME VARCHAR2(20), 7 STUDENT_AGE NUMBER(2), 8 STUDENT_GENDER VARCHAR2(5) 9 ); 10 -- Add comments to the table 11 comment on table HAND_STUDENT 12 is '學生信息表'; 13 -- Add comments to the columns 14 comment on column HAND_STUDENT.STUDENT_NO 15 is '學號'; 16 comment on column HAND_STUDENT.STUDENT_NAME 17 is '姓名'; 18 comment on column HAND_STUDENT.STUDENT_AGE 19 is '年齡'; 20 comment on column HAND_STUDENT.STUDENT_GENDER 21 is '性別'; 22 -- Create/Recreate primary, unique and foreign key constraints 23 alter table HAND_STUDENT add primary key (STUDENT_NO); 24 25 -- Create table 教師信息表 26 drop table HAND_TEACHER; 27 create table HAND_TEACHER 28 ( 29 TEACHER_NO VARCHAR2(10) not null, 30 TEACHER_NAME VARCHAR2(20), 31 MANAGER_NO VARCHAR2(10) 32 ); 33 -- Add comments to the table 34 comment on table HAND_TEACHER 35 is '教師信息表'; 36 -- Add comments to the columns 37 comment on column HAND_TEACHER.TEACHER_NO 38 is '教師編號'; 39 comment on column HAND_TEACHER.TEACHER_NAME 40 is '教師名稱'; 41 comment on column HAND_TEACHER.MANAGER_NO 42 is '上級編號'; 43 -- Create/Recreate primary, unique and foreign key constraints 44 alter table HAND_TEACHER add primary key (TEACHER_NO); 45 46 -- Create table 課程信息表 47 drop table HAND_COURSE; 48 create table HAND_COURSE 49 ( 50 COURSE_NO VARCHAR2(10) not null, 51 COURSE_NAME VARCHAR2(20), 52 TEACHER_NO VARCHAR2(20) not null 53 ); 54 -- Add comments to the table 55 comment on table HAND_COURSE 56 is '課程信息表'; 57 -- Add comments to the columns 58 comment on column HAND_COURSE.COURSE_NO 59 is '課程號'; 60 comment on column HAND_COURSE.COURSE_NAME 61 is '課程名稱'; 62 comment on column HAND_COURSE.TEACHER_NO 63 is '教師編號'; 64 -- Create/Recreate primary, unique and foreign key constraints 65 alter table HAND_COURSE add constraint PK_COURSE primary key (COURSE_NO, TEACHER_NO); 66 67 -- Create table 成績信息表 68 drop table HAND_STUDENT_CORE; 69 create table HAND_STUDENT_CORE 70 ( 71 STUDENT_NO VARCHAR2(10) not null, 72 COURSE_NO VARCHAR2(10) not null, 73 CORE NUMBER(4,2) 74 ); 75 -- Add comments to the table 76 comment on table HAND_STUDENT_CORE 77 is '學生成績表'; 78 -- Add comments to the columns 79 comment on column HAND_STUDENT_CORE.STUDENT_NO 80 is '學號'; 81 comment on column HAND_STUDENT_CORE.COURSE_NO 82 is '課程號'; 83 comment on column HAND_STUDENT_CORE.CORE 84 is '分數'; 85 -- Create/Recreate primary, unique and foreign key constraints 86 alter table HAND_STUDENT_CORE add constraint PK_SC primary key (STUDENT_NO, COURSE_NO); 87 88 -- Create table 學生歷史信息表 89 drop table HAND_STUDENT_HIS; 90 create table HAND_STUDENT_HIS 91 ( 92 STUDENT_NO VARCHAR2(10) not null, 93 STUDENT_NAME VARCHAR2(20), 94 STUDENT_AGE NUMBER(2), 95 STUDENT_GENDER VARCHAR2(5), 96 LAST_UPDATE_DATE DATE, 97 STATUS VARCHAR2(5) 98 ); 99 -- Add comments to the table 100 comment on table HAND_STUDENT_HIS 101 is '學生信息歷史表'; 102 -- Add comments to the columns 103 comment on column HAND_STUDENT_HIS.STUDENT_NO 104 is '學號'; 105 comment on column HAND_STUDENT_HIS.STUDENT_NAME 106 is '姓名'; 107 comment on column HAND_STUDENT_HIS.STUDENT_AGE 108 is '年齡'; 109 comment on column HAND_STUDENT_HIS.STUDENT_GENDER 110 is '性別'; 111 comment on column HAND_STUDENT_HIS.LAST_UPDATE_DATE 112 is '最後更新時間'; 113 comment on column HAND_STUDENT_HIS.STATUS 114 is '狀態'; 115 116 -- Create table 日誌信息表 117 drop table HAND_LOG; 118 create table HAND_LOG 119 ( 120 CODE VARCHAR2(240) not null, 121 MSG VARCHAR2(240) not null, 122 KEY1 VARCHAR2(240), 123 KEY2 VARCHAR2(240), 124 KEY3 VARCHAR2(240), 125 KEY4 VARCHAR2(240), 126 KEY5 VARCHAR2(240) 127 ); 128 -- Add comments to the table 129 comment on table HAND_LOG 130 is '日誌信息表'; 131 -- Add comments to the columns 132 comment on column HAND_LOG.CODE 133 is '編號'; 134 comment on column HAND_LOG.MSG 135 is '消息'; 136 comment on column HAND_LOG.KEY1 137 is '關鍵字1'; 138 comment on column HAND_LOG.KEY2 139 is '關鍵字2'; 140 comment on column HAND_LOG.KEY3 141 is '關鍵字3'; 142 comment on column HAND_LOG.KEY4 143 is '關鍵字4'; 144 comment on column HAND_LOG.KEY5 145 is '關鍵字5'; 146 147 /*******初始化學生表的數據******/ 148 insert into HAND_STUDENT values ('s001','張三',23,'男'); 149 insert into HAND_STUDENT values ('s002','李四',23,'男'); 150 insert into HAND_STUDENT values ('s003','吳鵬',25,'男'); 151 insert into HAND_STUDENT values ('s004','琴沁',20,'女'); 152 insert into HAND_STUDENT values ('s005','王麗',20,'女'); 153 insert into HAND_STUDENT values ('s006','李波',21,'男'); 154 insert into HAND_STUDENT values ('s007','劉玉',21,'男'); 155 insert into HAND_STUDENT values ('s008','蕭蓉',21,'女'); 156 insert into HAND_STUDENT values ('s009','陳蕭曉',23,'女'); 157 insert into HAND_STUDENT values ('s010','陳美',22,'女'); 158 commit; 159 /******************初始化教師表***********************/ 160 insert into HAND_TEACHER values ('t001', '劉陽',''); 161 insert into HAND_TEACHER values ('t002', '諶燕','t001'); 162 insert into HAND_TEACHER values ('t003', '胡明星','t002'); 163 commit; 164 /***************初始化課程表****************************/ 165 insert into HAND_COURSE values ('c001','J2SE','t002'); 166 insert into HAND_COURSE values ('c002','Java Web','t002'); 167 insert into HAND_COURSE values ('c003','SSH','t001'); 168 insert into HAND_COURSE values ('c004','Oracle','t001'); 169 insert into HAND_COURSE values ('c005','SQL SERVER 2005','t003'); 170 insert into HAND_COURSE values ('c006','C#','t003'); 171 insert into HAND_COURSE values ('c007','JavaScript','t002'); 172 insert into HAND_COURSE values ('c008','DIV+CSS','t001'); 173 insert into HAND_COURSE values ('c009','PHP','t003'); 174 insert into HAND_COURSE values ('c010','EJB3.0','t002'); 175 insert into HAND_COURSE values ('c011','PHP','t004'); 176 commit; 177 /***************初始化成績表***********************/ 178 insert into HAND_STUDENT_CORE values ('s001','c001',58.9); 179 insert into HAND_STUDENT_CORE values ('s002','c001',80.9); 180 insert into HAND_STUDENT_CORE values ('s003','c001',81.9); 181 insert into HAND_STUDENT_CORE values ('s004','c001',60.9); 182 insert into HAND_STUDENT_CORE values ('s001','c002',82.9); 183 insert into HAND_STUDENT_CORE values ('s002','c002',72.9); 184 insert into HAND_STUDENT_CORE values ('s003','c002',81.9); 185 insert into HAND_STUDENT_CORE values ('s001','c003','59'); 186 insert into HAND_STUDENT_CORE values ('s003','c011',81.9); 187 insert into HAND_STUDENT_CORE values ('s001','c011','59'); 188 commit;
題解:sql
包頭(1.1~1.6):數據庫
create or replace package cux_exam_xxxx_pkg is -- 1. 定義數據類型 type score_data_type is record( student_no hand_student.student_no%type, student_name hand_student.student_name%type, student_age hand_student.student_age%type, student_gender hand_student.student_gender%type, course_no hand_course.course_no%type, course_name hand_course.course_name%type, teacher_name hand_teacher.teacher_name%type, core hand_student_core.core%type, avg_core hand_student_core.core%type, max_core hand_student_core.core%type, min_core hand_student_core.core%type); -- 2. 定義內存表類型 type_studens_tbl TYPE type_studens_tbl IS TABLE OF studens_rec%ROWTYPE INDEX BY BINARY_INTEGER; -- 3. 得到低於平均分數的學⽣生信息 function get_grounded_info return type_studens_tbl; -- 4. 分數調整 procedure score_adjustment(p_std_score in number, x_return_status out nocopy varchar2, x_msg_data out nocopy varchar2); -- 5. 查詢教師的直接領導 function get_manager(p_teacher_no in varchar2) return varchar2 ; -- 6. 查詢課程的及格率 function get_course_pass_rate(p_course_no in varchar2) return number ; end cux_exam_xxxx_pkg;
包體(1.1~1.6):數組
1 create or replace package body cux_exam_xxxx_pkg is 2 -- 3. 得到低於平均分數的學⽣生信息 3 function get_grounded_info return type_studens_tbl is 4 l_studens_tbl type_studens_tbl; 5 begin 6 -- 計算每⻔門課程的平均分,並取出全部成績低於平均分的學⽣生 7 select * 8 from (select hs.student_no, 9 hs.student_name, 10 hs.student_age, 11 hs.student_gender, 12 hc.course_no, 13 hc.course_name, 14 ht.teacher_name, 15 hsc.core, 16 round(avg(hsc.core) over(partition by 17 hsc.course_no), 2) avg_core, 18 max(hsc.core) over(partition by hsc.course_no) 19 max_core, 20 min(hsc.core) over(partition by hsc.course_no) 21 min_core 22 from hand_course hc, 23 hand_student hs, 24 hand_student_core hsc, 25 hand_teacher ht 26 where hc.course_no = hsc.course_no 27 and hs.student_no = hsc.student_no 28 and hc.teacher_no = ht.teacher_no) 29 BULK COLLECT into l_studens_tbl 30 where core < avg_core; 31 return l_studens_tbl; 32 end get_grounded_info; 33 -- 4. 分數調整 34 procedure score_adjustment(p_std_score in number, 35 x_return_status out nocopy varchar2, 36 x_msg_data out nocopy varchar2) is 37 l_data_cur ref_cursor; 38 l_data_rec score_data_type; 39 l_new_score number; 40 l_savepoint_name varchar2(30) := 'sp_score_adjustment'; 41 begin 42 x_return_status := 'S'; 43 x_msg_data := null; 44 savepoint l_savepoint_name; 45 l_data_cur := get_grounded_info; 46 loop 47 fetch l_data_cur 48 into l_data_rec; 49 exit when l_data_cur%notfound; 50 update hand_student_core hsc 51 set hsc.core = nvl(hsc.core, 0) + 1 52 where hsc.student_no = l_data_rec.student_no 53 and hsc.course_no = l_data_rec.course_no 54 returning hsc.core into l_new_score; 55 if l_new_score < nvl(p_std_score, 60) then 56 dbms_output.put_line('Student No.: ' || 57 l_data_rec.student_no || 58 ', Student Name: ' || 59 l_data_rec.student_name || 60 ', Course Name: ' || 61 l_data_rec.course_name || 62 ', Teacher Name: ' || 63 l_data_rec.teacher_name || 64 ', Score: ' || l_data_rec.core || 65 ', Avg score: ' || l_data_rec.avg_core 66 || 67 ', Max score: ' || l_data_rec.max_core 68 || 69 ', Min score: ' || 70 l_data_rec.min_core); 71 end if; 72 end loop; 73 commit; 74 exception 75 when others then 76 rollback to l_savepoint_name; 77 x_return_status := 'E'; 78 x_msg_data := substr(sqlerrm, 1, 2000); 79 end score_adjustment; 80 -- 5. 查詢教師的直接領導 81 function get_manager(p_teacher_no in varchar2) return varchar2 is 82 l_teacher_no hand_teacher.teacher_no%type; 83 begin 84 select ht.teacher_no 85 into l_teacher_no 86 from hand_teacher ht 87 where level = 2 88 connect by ht.teacher_no = prior ht.manager_no 89 start with ht.teacher_no = p_teacher_no; 90 return l_teacher_no; 91 exception 92 when no_data_found then 93 return '-1'; 94 when too_many_rows then 95 return '-2'; 96 when others then 97 return '-3'; 98 end get_manager; 99 -- 6. 查詢課程及格率 100 function get_course_pass_rate(p_course_no in varchar2) return 101 number is 102 l_passed_count number; 103 l_total_count number; 104 l_course_pass_rate number; 105 begin 106 select sum(case 107 when hsc.core > 60 108 then 1 109 else 110 0 111 end) passed_count, count(1) total_count 112 Into l_passed_count, l_total_count 113 from hand_student_core hsc 114 where hsc.course_no = p_course_no; 115 l_course_pass_rate := round(l_passed_count/l_total_count,2); 116 return l_course_pass_rate; 117 exception 118 when others then 119 return null; 120 end get_course_pass_rate; 121 end cux_exam_XXXX_pkg;
1.7:安全
-- 7.取全部課程及格率⾼高於50%的教師信息,插⼊入到 hand_teacher_temp 表中。 declare l_count number; begin select count(1) into l_count from all_tables t where t.TABLE_NAME = 'HAND_TEACHER_TEMP'; if l_count > 0 then execute immediate 'DROP TABLE HAND_TEACHER_TEMP'; end if; execute immediate 'CREATE TABLE HAND_TEACHER_TEMP AS ' || insert hand_teacher_temp select * from hand_teacher ht where not exists( select 1 from hand_course hc where cux_exam_xxxx_pkg.get_grounded_info(hc.course_no) <0.5 and hc.teacher_no = ht.teacher_no)'; exception when others then dbms_output.put_line(sqlcode || '-' || sqlerrm); end;
1.8: app
-- 8. 寫⼀一個匿匿名塊,更更新學⽣生所選課程的成績。若是存在課程成績在 60 分以 上,則對 原成績降分 2%,輸出學⽣生編號,課程編號以及更更新後的成績(⽤用 returning into )(10 分) Declare TYPE type_student_core_tb IS TABLE OF hand_student_core%ROWTYPE; l_student_core_tb type_student_core_tb; begin Update hand_student_core t set t.core = t.core * 0.98 Where t.core >60 RETURNING student_no ,course_no, core BULK COLLECT INTO l_student_core_tb; FOR i IN l_student_core_tb.FIRST .. l_student_core_tb.LAST LOOP DBMS_OUTPUT.PUT_LINE( l_student_core_tb(i). student_no || ' '|| l_student_core_tb(i). course_no || ' '|| l_student_core_tb(i). core ); END LOOP; commit; exception when others then rollback; dbms_output.put_line(sqlcode || '-' || sqlerrm); end;
小結:ide
注函數和存儲過程的區別:函數有返回值,存儲過程沒有返回值,函數參數只能是INT類型(傳入參數),存儲過程能夠是INT,OUT,IN OUT;函數
大多數SQL函數能在PL/SQL中過程語句中使用,如單行的數值和字符串函數、數據類型轉換函數、日期函數、時間函數、求最大、最小值的 GREATEST, LEAST 函數等,可是有些函數不能再PL/SQL中使用,如Decode函數、分組函數(AVG, MIN, MAX, COUNT, SUM, STDDEV, and VARIANCE)等;oop
PLSQL的塊是能夠嵌套的,變量的做用範圍與其餘語言相似 ,若是同名,想要訪問外層的須要使用outer關鍵字;fetch
PLSQL中經常使用的自定義類型就兩種: 記錄類型、PLSQL內存表類型(根據表中的數據字段的簡單和複雜 程度又可分別實現相似於簡單數組和記錄數組的功能);spa
意外處理等,內置異常,以及raise_application_error()函數等注意。。。
題解:
(1):
-- 2-1. 建立⼀一個 hand_teacher_his 歷史表 create table hand_teacher_his as select ht.*, sysdate last_update_date, 'U' operation from hand_teacher ht where 1=-1;
(2):
-- 2-2. 在 hand_teacher 表上新建⼀一個觸發器器 create or replace trigger hand_teacher_tgr1 after insert or update or delete on hand_teacher for each row declare begin if inserting then insert into hand_teacher_his values(:new.teacher_no, :new.teacher_name, :new.manager_no, sysdate, 'I'); elsif updating then insert into hand_teacher_his values(:old.teacher_no, :old.teacher_name, :old.manager_no, sysdate, 'U'); elsif deleting then insert into hand_teacher_his values(:old.teacher_no, :old.teacher_name, :old.manager_no, sysdate, 'D'); end if; exception when others then raise_application_error(-20005, sqlcode ||'-' ||sqlerrm ); end;
小結:
觸發器注意:時機:Before 或者 After 或 Instead of 事件:Insert 或 Update 或 Delete 對象:表名(或視圖名) 類型:Row 或者 Statement級; 條件:知足特定Where條件才執行; 內容:一般是一段PLSQL塊代碼;
重點注意: Instead of : 用Trigger的內容替換 事件自己的動做 Row級:SQL語句影響到的每一行都會引起Trigger Statement級:一句SQL語句引起一次,無論它影響多少行(甚至0行)。
-- 3. 使⽤用system ⽤用戶新建⼀一個 directory begin execute immediate 'create or replace directory HAND_DIR_TEMP as ''c:\temp'''; execute immediate 'grant read ,write on directory HAND_DIR_TEMP to student1'; end;
小結:
Oracle Directory是爲了便於控制Bfile存儲的安全性;
在Oracle 內部建立的 Directory 默認的全部者是sys, 並有DBA( 或者是另外一個擁有 CREATE ANY DIRECTORY 權限的用戶)建立;Directory 對象能夠像表那樣給其餘用戶賦權。
1 -- 3. 從hand_exam_data.txt⽂文件讀取內容並導⼊入到 hand_teacher 表 2 declare 3 l_line VARCHAR2(1023); 4 fid UTL_FILE.FILE_TYPE; 5 l_data_rec hand_teacher%rowtype; 6 procedure split_columns(p_data_str in varchar2, 7 x_data_rec out hand_teacher%rowtype) is 8 l_substr varchar2(2000); 9 l_instr number; 10 begin 11 if p_data_str is null then 12 return; 13 end if; 14 l_substr := p_data_str; 15 l_instr := instr(l_substr, ','); 16 x_data_rec.teacher_no := trim(replace(substr(l_substr, 1, 17 l_instr - 1),'"','')); 18 -- 提取teacher_name 19 l_substr := substr(l_substr, l_instr + 1); 20 l_instr := instr(l_substr, ','); 21 x_data_rec.teacher_name := trim(replace(substr(l_substr, 1, 22 l_instr - 1),'"','')); 23 -- 提取manager_no 24 l_substr := substr(l_substr, l_instr + 1); 25 l_instr := instr(l_substr, ','); 26 x_data_rec.manager_no := trim(replace(l_substr,'"','')); 27 end; 28 BEGIN 29 BEGIN 30 fid := UTL_FILE.FOPEN('HAND_DIR_TEMP', 'hand_exam_data.txt', 31 'R'); 32 loop 33 UTL_FILE.GET_LINE(fid, l_line); 34 dbms_output.put_line(l_line); 35 split_columns(l_line, l_data_rec); 36 if l_data_rec.teacher_no is not null then 37 insert into hand_teacher values l_data_rec; 38 end if; 39 end loop; 40 utl_file.fclose(fid); 41 EXCEPTION 42 WHEN NO_DATA_FOUND THEN 43 if utl_file.is_open(fid) then 44 utl_file.fclose(fid); 45 end if; 46 END; 47 commit; 48 EXCEPTION 49 WHEN others THEN 50 rollback; 51 dbms_output.put_line(sqlcode || '-' || sqlerrm); 52 END;
小結:
這裏注意打開文件函數 UTL_FILE.FOPEN,讀取內容函數 UTL_FILE.GET_LINE,以及什麼時候不在讀取(爲null),以及異常處理,內容格式處理。