主題:MLDN筆記連載(下載)—6、Oracle_04
|
|
|
|
[attach]2331[/attach]
隨堂筆記下載:本帖隱藏的內(nèi)容需要回復(fù)才可以瀏覽
1、課程名稱:Oracle
數(shù)據(jù)庫(kù)的備份與恢復(fù)、介紹PL/SQL編程(根本不用)、介紹嵌套表、可變數(shù)組、數(shù)據(jù)庫(kù)設(shè)計(jì)范式
2、知識(shí)點(diǎn)
2.1、上次課程的主要知識(shí)點(diǎn)
1、 表的創(chuàng)建,表創(chuàng)建之后如果不合適可以增加字段,但是一般情況下不要去修改表的結(jié)構(gòu)。
2、 約束:五種約束:PRIMARY KEY、NOT NULL、UNIQUE、CHECK、FOREIGN KEY
3、 約束本身也是可以進(jìn)行修改的,但是在為一個(gè)表增加約束的時(shí)候,表中的數(shù)據(jù)不能違反約束
4、 視圖:封裝了一個(gè)完整的SQL語句,以后直接查詢視圖就可以完成復(fù)雜的查詢功能。視圖本身最好不要修改。
5、 序列:是完成自動(dòng)增長(zhǎng)的功能。nextVal、currVal
2.2、本次預(yù)計(jì)講解的知識(shí)點(diǎn)
1、 了解數(shù)據(jù)庫(kù)的備份及恢復(fù)操作過程
2、 介紹一下嵌套和可變數(shù)組的特點(diǎn),但是此功能肯定不用
3、 PL/SQL、游標(biāo)、過程:介紹,基本上是不使用了
4、 掌握數(shù)據(jù)庫(kù)的設(shè)計(jì)范式
5、 數(shù)據(jù)庫(kù)的設(shè)計(jì)題目
3、具體內(nèi)容
3.1、數(shù)據(jù)庫(kù)的備份與恢復(fù)(了解)
在一般程序的維護(hù)中,基本上要對(duì)數(shù)據(jù)進(jìn)行及時(shí)的備份操作,在oracle中本身提供了數(shù)據(jù)庫(kù)備份命令,操作步驟如下:
1、 在硬盤上建立一個(gè)文件夾:D:\temp
2、 之后進(jìn)入命令行方式,并且進(jìn)入到d:\temp目錄之中,執(zhí)行exp命令(導(dǎo)出文件名稱:EXPDAT.DMP)
3、 現(xiàn)在可以將數(shù)據(jù)庫(kù)中的全部表刪除掉
4、 之后輸入imp命令將d:\temp目錄中的全部?jī)?nèi)容恢復(fù)回來
3.2、嵌套表及可變數(shù)組(了解)
嵌套表和可變數(shù)組是Oracle中自己的東西,不屬于標(biāo)準(zhǔn)的SQL語法。
3.2.1、嵌套表
嵌套表:在一個(gè)表中還有另外一張表。
例如:現(xiàn)在有如下一種場(chǎng)景:一個(gè)部門可以有多個(gè)項(xiàng)目
· 兩張表:部門表、項(xiàng)目表
· 在項(xiàng)目表中必然保存一個(gè)部門的編號(hào),因?yàn)轫?xiàng)目表是從表,而部門表是主表
· 但是在Oracle中以上的過程卻可以通過一張表完成。那么就相當(dāng)于是把項(xiàng)目表中的全部?jī)?nèi)容做成了一個(gè)單獨(dú)的字段,在部門表中有一列的數(shù)據(jù)類型為此字段。
所以,此時(shí),需要單獨(dú)去創(chuàng)建表示項(xiàng)目的數(shù)據(jù)類型。
CREATE TYPE project_ty AS OBJECT(
pname VARCHAR(30) ,
pnum NUMBER ,
pdate DATE
) ;
/
此類型實(shí)際上是一個(gè)用戶自己定義的復(fù)合類型。
但是,如果現(xiàn)在想使用此類型的話,則必須首先聲明一個(gè)此類型的標(biāo)識(shí)。
CREATE TYPE project_nt AS TABLE OF project_ty ;
/
最終:project_nt,就是真正所需要的在建立表時(shí)的數(shù)據(jù)類型。
建立department表,在部門表中的項(xiàng)目處,就可以使用project_nt進(jìn)行數(shù)據(jù)類型的聲明:
CREATE TABLE department
(
did NUMBER ,
dname VARCHAR(30) ,
projects project_nt
) NESTED TABLE projects STORE AS projects_nt_tab ;
以上的部門表中,一個(gè)部門有多個(gè)項(xiàng)目,項(xiàng)目的所有相關(guān)信息都存儲(chǔ)在projects_nt_tab之中。
例如:向嵌套表中插入記錄
INSERT INTO department VALUES (1,'軟件技術(shù)部',
project_nt(
project_ty('ERP',3,sysdate),project_ty('CRM',5,sysdate),
project_ty('HR',10,sysdate),project_ty('OA',5,sysdate)
)
) ;
對(duì)于部門表來說,數(shù)據(jù)只有一行,但是一行的數(shù)據(jù)中包含了一個(gè)復(fù)合的類型。
對(duì)于一個(gè)部門,項(xiàng)目可以變成很多,沒有限制。如果要想對(duì)嵌套的內(nèi)容有所限制,則就必須使用可變數(shù)組。
3.2.2、可變數(shù)組
實(shí)際上可變數(shù)組與嵌套表類似,只是可以指定出存放的大小。
要想使用可變數(shù)組,首先要跟之前一樣進(jìn)行一種數(shù)據(jù)類型的聲明。
例如:一個(gè)項(xiàng)目要有多個(gè)雇員完成
· 創(chuàng)建工作人員的信息字段(復(fù)合字段)
CREATE TYPE worker_info AS OBJECT(
id NUMBER ,
name VARCHAR(20) ,
sex VARCHAR(2) ,
salary NUMBER(7,2)
) ;
/
· 必須以上面的類型為基礎(chǔ),進(jìn)行數(shù)據(jù)大小的指派,就相當(dāng)于聲明了一個(gè)數(shù)組。
CREATE TYPE work_info_list AS VARRAY(10) OF worker_info ;
/
· 在建立表的時(shí)候必須指定項(xiàng)目中的工作人員的類型為worker_info_list。
CREATE TABLE projects
(
pid NUMBER ,
pname VARCHAR(30) ,
workers work_info_list
) ;
· 向表中增加數(shù)據(jù)
INSERT INTO projects VALUES(1,'統(tǒng)計(jì)局項(xiàng)目',work_info_list(
worker_info(11,'張三','男',30) ,worker_info(12,'李四','男',32) ,
worker_info(13,'王五','男',33) ,worker_info(14,'趙六','男',34) ,
worker_info(11,'孫七','男',35)
)) ;
3.3、PL / SQL編程(了解)
肯定不用,很少有人再去專門編寫過程了。
3.3.1、PL/SQL塊
如果要想使用PL/SQL則需要按照一個(gè)固定的格式編寫:
DECLARE
聲明一些變量、游標(biāo)
BEGIN
程序的開始,有若干條數(shù)據(jù)操作代碼
END ;
/
按照以上的格式開發(fā)一個(gè)簡(jiǎn)單的PL/SQL程序。
DECLARE
i NUMBER ;
BEGIN
-- 為i賦值
i := 30 ;
DBMS_OUTPUT.put_line('i = ' || i) ;
END ;
/
但是,如果直接運(yùn)行以上的程序,并沒有任何的輸出,這是因?yàn)槌绦虻妮敵鲲@示被關(guān)閉了:
SET SERVEROUTPUT on ;
當(dāng)然,在P:L/SQL中也是可以接收用戶自己輸入的數(shù)據(jù)。
DECLARE
i NUMBER ;
BEGIN
-- 為i賦值
DBMS_OUTPUT.put_line('請(qǐng)用戶輸入數(shù)據(jù):') ;
i := &temp ;
DBMS_OUTPUT.put_line('i = ' || i) ;
END ;
/
例如:由用戶輸入一個(gè)雇員編號(hào),之后顯示此編號(hào)的雇員姓名
DECLARE
-- 雇員編號(hào)
eno NUMBER ;
-- 雇員姓名
name VARCHAR(30) ;
BEGIN
DBMS_OUTPUT.put_line('請(qǐng)輸入雇員編號(hào):') ;
eno := &no ;
SELECT ename INTO name FROM emp WHERE empno=eno ;
DBMS_OUTPUT.put_line('雇員姓名為:' || name) ;
END ;
/
但是以上的程序也存在問題,如果雇員編號(hào)不存在呢?則程序出現(xiàn)錯(cuò)誤。所以,此時(shí)可以在PL/SQL塊中增加異常的捕獲,此時(shí)可以使用如下的格式聲明PL/SQL塊:
DECLARE
聲明一些變量、游標(biāo)
BEGIN
程序的開始,有若干條數(shù)據(jù)操作代碼;
EXCEPTION
如果有錯(cuò)誤,則執(zhí)行此段代碼
END ;
/
例如:修改以上的代碼
DECLARE
-- 雇員編號(hào)
eno NUMBER ;
-- 雇員姓名
name VARCHAR(30) ;
BEGIN
DBMS_OUTPUT.put_line('請(qǐng)輸入雇員編號(hào):') ;
eno := &no ;
SELECT ename INTO name FROM emp WHERE empno=eno ;
DBMS_OUTPUT.put_line('雇員姓名為:' || name) ;
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.put_line('沒有發(fā)現(xiàn)此雇員信息') ;
END ;
/
在PL/SQL之中也提供了各種的循環(huán)、判斷功能。
1、 loop循環(huán)
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 1 ;
LOOP
DBMS_OUTPUT.put_line('temp = ' || temp) ;
EXIT WHEN temp>=10 ;
temp := temp + 1 ;
END LOOP ;
END ;
/
2、 while…loop循環(huán)
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 1 ;
WHILE(temp<=10) LOOP
DBMS_OUTPUT.put_line('temp = ' || temp) ;
temp := temp + 1 ;
END LOOP ;
END ;
/
3、 for循環(huán)
要指定循環(huán)的范圍
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 1 ;
FOR temp IN 1..10 LOOP
DBMS_OUTPUT.put_line('temp = ' || temp) ;
END LOOP ;
END ;
/
4、 IF語句
進(jìn)行條件的判斷
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 3 ;
IF temp>=3 THEN
DBMS_OUTPUT.put_line('temp = ' || temp) ;
END IF;
END ;
/
5、 提供多分吱判斷
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 2 ;
IF temp=3 THEN
DBMS_OUTPUT.put_line('3、temp = ' || temp) ;
ELSIF temp=2 THEN
DBMS_OUTPUT.put_line('2、temp = ' || temp) ;
END IF;
END ;
/
6、 IF…ELSE語句
DECLARE
temp NUMBER ;
BEGIN
-- 為temp設(shè)置一個(gè)初始值
temp := 2 ;
IF temp=3 THEN
DBMS_OUTPUT.put_line('3、temp = ' || temp) ;
ELSE
DBMS_OUTPUT.put_line('2、temp = ' || temp) ;
END IF;
END ;
/
在PL/SQL之中,提供了一個(gè)完整的程序的控制操作邏輯。
例如:輸入一個(gè)雇員編號(hào),根據(jù)他所在的部門漲工資,規(guī)則:
· 如果在10部門,增長(zhǎng)10%
· 如果在20部門,增長(zhǎng)20%
· 如果在30部門,增長(zhǎng)30%
· 最高工資不能超過5000 |
|
|
|
|
|
-
1
評(píng)分人數(shù)
-
|
|
|
|
|
|
- 浪曦幣
- 10 枚
- 金幣
- 0 枚
- 最后登錄
- 2009-5-4
|
|
|
|
|
DECLARE
eno NUMBER(4) ;
dno NUMBER(4) ;
sal NUMBER(7,2) ;
BEGIN
-- 接收雇員編號(hào)
DBMS_OUTPUT.put_line('請(qǐng)輸入雇員編號(hào):') ;
eno := &empno ;
-- 根據(jù)此編號(hào)查詢出部門編號(hào)及工資
SELECT deptno,sal INTO dno,sal FROM emp WHERE empno=eno ;
-- 進(jìn)行依次的判斷
IF dno=10 THEN
IF sal*1.1>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=eno ;
ELSE
UPDATE emp SET sal=sal*1.1 WHERE empno=eno ;
END IF ;
ELSIF dno=20 THEN
IF sal*1.2>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=eno ;
ELSE
UPDATE emp SET sal=sal*1.2 WHERE empno=eno ;
END IF ;
ELSIF dno=30 THEN
IF sal*1.3>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=eno ;
ELSE
UPDATE emp SET sal=sal*1.3 WHERE empno=eno ;
END IF ;
ELSE
null ;
END IF ;
END ;
/
3.3.2、游標(biāo)
在DECALE中聲明變量的時(shí)候應(yīng)該指定其類型,但是以上面的程序?yàn)槔?,如果要想聲明eno,dno之類的需要進(jìn)行表的結(jié)構(gòu)查詢才可以知道,但是這樣太麻煩,所以在Oracle中對(duì)于變量的聲明可以直接使用以下的語法,就可以與表中的字段類型一致:表名稱.字段名稱%TYPE,例如:
eno emp.empno%TYPE ;
以上是表示每一個(gè)具體的屬性。
游標(biāo):實(shí)際上指的是在每行數(shù)據(jù)的一個(gè)指向問題。如何去定義一個(gè)變量,此變量表示一行的類型,此時(shí)就可以通過ROWTYPE聲明,例如:聲明一個(gè)變量,此變量表示emp的一行完整記錄:
erow emp%ROWTYPE ;
以上的erow變量就表示emp表中的一行記錄。
例如:使用erow聲明
DECLARE
eno emp.empno%TYPE ;
erow emp%ROWTYPE ;
BEGIN
-- 接收雇員編號(hào)
DBMS_OUTPUT.put_line('請(qǐng)輸入雇員編號(hào):') ;
eno := &empno ;
-- 根據(jù)此編號(hào)查詢出部門編號(hào)及工資
SELECT * INTO erow FROM emp WHERE empno=eno ;
DBMS_OUTPUT.put_line('雇員姓名:' || erow.ename) ;
DBMS_OUTPUT.put_line('雇傭日期:' || erow.hiredate) ;
END ;
/
游標(biāo)的時(shí)候需要在DECALE聲明處進(jìn)行聲明,之后才可以使用,每次操作的時(shí)候游標(biāo)都必須手工向下移動(dòng)。游標(biāo)在移動(dòng)之前必須先打開,之后利用FETCH進(jìn)行游標(biāo)的移動(dòng)。
例如:使用游標(biāo)打印emp表中的數(shù)據(jù)
DECLARE
erow emp%ROWTYPE ;
-- 聲明一個(gè)游標(biāo),里面裝的是全部的emp表內(nèi)容
CURSOR mycur IS SELECT * FROM emp ;
BEGIN
-- 打開游標(biāo)
OPEN mycur ;
-- 游標(biāo)打開之后實(shí)際上是在所有數(shù)據(jù)的第一行之上
-- 游標(biāo)向下移動(dòng),每次移動(dòng)都會(huì)把全部的記錄放到erow之中
FETCH mycur INTO erow ;
WHILE(mycur%FOUND) LOOP
DBMS_OUTPUT.put_line('雇員姓名:' || erow.ename || ',雇傭日期:' || erow.hiredate) ;
-- 再往下移動(dòng)
FETCH mycur INTO erow ;
END LOOP ;
-- 關(guān)閉游標(biāo)
CLOSE mycur ;
END ;
/
但是,如果按以上的方式使用,則每次都需要打開和關(guān)閉游標(biāo),會(huì)很麻煩,所以一般在游標(biāo)的操作中使用FOR循環(huán)是最常見的。
DECLARE
-- 聲明一個(gè)游標(biāo),里面裝的是全部的emp表內(nèi)容
CURSOR mycur IS SELECT * FROM emp ;
BEGIN
FOR erow IN mycur LOOP
DBMS_OUTPUT.put_line('雇員姓名:' || erow.ename || ',雇傭日期:' || erow.hiredate) ;
END LOOP ;
END ;
/
例如:使用游標(biāo)完成以下的操作
一次性上漲所有人員工資,要求如下;
· 如果在10部門,增長(zhǎng)10%
· 如果在20部門,增長(zhǎng)20%
· 如果在30部門,增長(zhǎng)30%
· 最高工資不能超過5000
DECLARE
-- 聲明一個(gè)游標(biāo),里面裝的是全部的emp表內(nèi)容
CURSOR mycur IS SELECT * FROM emp ;
BEGIN
FOR erow IN mycur LOOP
IF erow.deptno=10 THEN
IF erow.sal*1.1>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=erow.empno ;
ELSE
UPDATE emp SET sal=sal*1.1 WHERE empno=erow.empno ;
END IF ;
ELSIF erow.deptno=20 THEN
IF erow.sal*1.2>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=erow.empno ;
ELSE
UPDATE emp SET sal=sal*1.2 WHERE empno=erow.empno ;
END IF ;
ELSIF erow.deptno=30 THEN
IF erow.sal*1.3>5000 THEN
UPDATE emp SET sal=5000 WHERE empno=erow.empno ;
ELSE
UPDATE emp SET sal=sal*1.3 WHERE empno=erow.empno ;
END IF ;
ELSE
null ;
END IF ;
END LOOP ;
END ;
/
注意點(diǎn):
游標(biāo)的操作中,是所有的數(shù)據(jù)行依次向下移動(dòng),之后把每一行的記錄送給rowtype類型的變量,通過rowtype取出一行的具體內(nèi)容。
3.3.3、過程
過程 = 過程聲明 + PL/SQL塊
例如:聲明一個(gè)過程
CREATE OR REPLACE PROCEDURE mypro(eno NUMBER)
AS
esal emp.sal%TYPE ;
BEGIN
SELECT sal INTO esal FROM emp WHERE empno=eno ;
DBMS_OUTPUT.put_line('雇員工資:' || esal) ;
END ;
/
調(diào)用過程:
exec mypro(7369) ;
例如:再建立一個(gè)過程,此過程可以增加部門信息
CREATE OR REPLACE PROCEDURE mypro(dno dept.deptno%TYPE,dn dept.dname%TYPE,dl dept.loc%TYPE)
AS
BEGIN
INSERT INTO dept(deptno,dname,loc) VALUES (dno,dn,dl) ;
END ;
/
exec mypro(50,'技術(shù)部','北京') ;
3.4、數(shù)據(jù)庫(kù)設(shè)計(jì)范式
為數(shù)據(jù)庫(kù)表設(shè)計(jì)提供一個(gè)依據(jù),可以適應(yīng)各種變化。但是數(shù)據(jù)庫(kù)設(shè)計(jì)范式僅僅只是一個(gè)參考,實(shí)際中不能完全應(yīng)用。
3.4.1、第一范式
每一個(gè)字段不可再分。
例如:定義一張用戶表:id、name、bithday
但是,如果此時(shí)使用了以下的設(shè)計(jì),則就不符合于第一范式:
· 將姓名拆分成:姓、名
· 生日拆分成:年、月、日
實(shí)際上,之前的部門表,就滿足與第一范式。
3.4.2、第二范式
數(shù)據(jù)庫(kù)表中不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的部分函數(shù)依賴。
假定選課關(guān)系表為SelectCourse(學(xué)號(hào), 姓名, 年齡, 課程名稱, 成績(jī), 學(xué)分)
如果此時(shí)按照第一范式的設(shè)計(jì)要求,數(shù)據(jù)庫(kù)創(chuàng)建腳本如下:
CREATE TABLE selectcourse
(
stuno NUMBER ,
sname VARCHAR(30) ,
sage NUMBER ,
cname VARCHAR(50) ,
score NUMBER ,
cgrade NUMBER
) ; |
|
|
|
|
|
|
|
|
|
|
|
- 浪曦幣
- 10 枚
- 金幣
- 0 枚
- 最后登錄
- 2009-5-4
|
|
|
|
|
測(cè)試數(shù)據(jù):
INSERT INTO selectcourse (stuno,sname,sage,cname,score,cgrade) VALUES (11,'張三',20,'JAVA',90,3) ;
INSERT INTO selectcourse (stuno,sname,sage,cname,score,cgrade) VALUES (12,'李四',21,'JAVA',89,3) ;
INSERT INTO selectcourse (stuno,sname,sage,cname,score,cgrade) VALUES (11,'張三',20,'C++',80,5) ;
從以上的數(shù)據(jù)庫(kù)創(chuàng)建腳本及測(cè)試數(shù)據(jù)中可以發(fā)現(xiàn),此表的設(shè)計(jì)有如下問題:
· 一個(gè)學(xué)生可以選多門課,學(xué)生的編號(hào)重復(fù)、姓名重復(fù)、年齡重復(fù)
· 一門課程可以有多個(gè)學(xué)生參加,課程重復(fù),學(xué)分重復(fù)
· 一門課程的名稱可以修改,如果現(xiàn)在有200個(gè)學(xué)生參加了此課程,則要修改200行記錄
· 如果一門課程一個(gè)學(xué)生都沒有。不會(huì)有任何課程了
· 課程編號(hào)應(yīng)該唯一,學(xué)生編號(hào)應(yīng)該唯一
實(shí)際上來說,課程和學(xué)生信息應(yīng)該是彼此單獨(dú)存在的,之后才可以建立學(xué)生-課程的關(guān)系。
此時(shí):數(shù)據(jù)庫(kù)創(chuàng)建腳本修改如下
CREATE TABLE student
(
stuno NUMBER PRIMARY KEY NOT NULL ,
sname VARCHAR(30) ,
sage NUMBER
) ;
CREATE TABLE course
(
cid NUMBER PRIMARY KEY NOT NULL ,
cname VARCHAR(50) ,
cgrade NUMBER,
) ;
CREATE TABLE selectcourse
(
stuno NUMBER ,
cid NUMBER ,
score NUMBER ,
FOREIGN KEY(stuno) REFERENCES student(stuno) ON DELETE CASCADE ,
FOREIGN KEY(cid) REFERENCES course(cid) ON DELETE CASCADE
) ;
修改成以上的形式之后,可以發(fā)現(xiàn),課程和學(xué)生信息獨(dú)立。學(xué)生選的課程以及課程對(duì)應(yīng)的學(xué)生都在選課關(guān)系表中進(jìn)行配置。
INSERT INTO student (stuno,sname,sage) VALUES (11,'張三',20) ;
INSERT INTO student (stuno,sname,sage) VALUES (12,'李四',21) ;
INSERT INTO course (cid,cname,cgrade) VALUES (1,'JAVA',3) ;
INSERT INTO course (cid,cname,cgrade) VALUES (2,'C++',5) ;
INSERT INTO selectcourse(stuno,cid,score) VALUES (11,1,90) ;
INSERT INTO selectcourse(stuno,cid,score) VALUES (12,1,89) ;
INSERT INTO selectcourse(stuno,cid,score) VALUES (11,2,100) ;
此時(shí),可以發(fā)現(xiàn),如果更改了學(xué)生信息,則只需要更改一條即可,如果一個(gè)課程沒有學(xué)生參加,那么此課程也會(huì)被保留。
3.4.3、第三范式
在第二范式的基礎(chǔ)上,數(shù)據(jù)表中如果不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的傳遞函數(shù)依賴則符合第三范式。
假定學(xué)生關(guān)系表為Student(學(xué)號(hào), 姓名, 年齡, 所在學(xué)校, 學(xué)校地點(diǎn), 學(xué)校電話)
如果,此時(shí)按照第二范式操作,則數(shù)據(jù)庫(kù)創(chuàng)建腳本如下:
CREATE TABLE student
(
stuno NUMBER PRIMARY KEY NOT NULL ,
sname VARCHAR(30) ,
sage NUMBER
) ;
CREATE TABLE school
(
sid NUMBER PRIMARY KEY NOT NULL ,
sname VARCHAR(50) ,
sloc VARCHAR(200),
stel VARCHAR(50)
) ;
CREATE TABLE studentschool
(
stuno NUMBER ,
cid NUMBER ,
FOREIGN KEY(stuno) REFERENCES student(stuno) ON DELETE CASCADE ,
FOREIGN KEY(cid) REFERENCES school(sid) ON DELETE CASCADE
) ;
按照以上的設(shè)計(jì),那么最終的結(jié)果:一個(gè)學(xué)校可以有多個(gè)學(xué)生,一個(gè)學(xué)生可以在多個(gè)學(xué)校。正常情況下應(yīng)該一個(gè)學(xué)生只在一個(gè)學(xué)校,一個(gè)學(xué)校存在多個(gè)學(xué)生。(一個(gè)部門有多個(gè)雇員)。所以此時(shí),數(shù)據(jù)庫(kù)創(chuàng)建腳本修改如下:
CREATE TABLE school
(
sid NUMBER PRIMARY KEY NOT NULL ,
sname VARCHAR(50) ,
sloc VARCHAR(200),
stel VARCHAR(50)
) ;
CREATE TABLE student
(
stuno NUMBER PRIMARY KEY NOT NULL ,
sname VARCHAR(30) ,
sage NUMBER ,
sid NUMBER ,
FOREIGN KEY(sid) REFERENCES school(sid) ON DELETE CASCADE
) ;
3.4.4、范式說明
數(shù)據(jù)庫(kù)設(shè)計(jì)范式,在大多數(shù)情況下只能作為參考出現(xiàn),在數(shù)據(jù)庫(kù)設(shè)計(jì)范式中,只有唯一的一個(gè)永遠(yuǎn)必須考慮的問題:“數(shù)據(jù)庫(kù)查詢時(shí),表的關(guān)聯(lián)越少越好”、“數(shù)據(jù)庫(kù)修改結(jié)構(gòu)時(shí),越好修改越好”。
以上的全部都只是參考。
3.4.5、數(shù)據(jù)庫(kù)的設(shè)計(jì)工具
在數(shù)據(jù)庫(kù)的設(shè)計(jì)工作中,有許多的設(shè)計(jì)工具經(jīng)常使用,比較常用的是 —— Sybase PowerDesigner。
此時(shí),就可以針對(duì) Oracle數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)庫(kù)的建模了。
建立一張雇員表,Name為在工具中的顯示名稱,沒有任何意義,而Code為以后真正要使用的表名稱。
為表中依次添加各個(gè)要使用的列和列的類型,并在主鍵上打上勾。
以上的表會(huì)形成數(shù)據(jù)庫(kù)創(chuàng)建腳本。
表的關(guān)系出來之后,就可以利用此工具,自動(dòng)生成數(shù)據(jù)庫(kù)創(chuàng)建腳本。
[數(shù)據(jù)庫(kù)] ? [生成數(shù)據(jù)庫(kù)]
4、數(shù)據(jù)庫(kù)設(shè)計(jì)(小組討論)
設(shè)計(jì)要求,要求設(shè)計(jì)一個(gè)網(wǎng)上購(gòu)物程序(使用powerdesigner建立模型并編寫測(cè)試數(shù)據(jù)),有以下的需求
1、 管理員可以在后臺(tái)添加商品,每個(gè)商品屬于一個(gè)商品組
2、 可以對(duì)管理員進(jìn)行分組,對(duì)每一組進(jìn)行分別授權(quán),即一個(gè)管理員組可以有多個(gè)管理員,一個(gè)管理員組有多個(gè)權(quán)限,一個(gè)管理員可以在多個(gè)組
3、 用戶可以自己購(gòu)買商品,購(gòu)買商品時(shí)要在定單表中添加信息,一個(gè)用戶可以同時(shí)購(gòu)買多個(gè)商品,用戶可以選擇自己所在的地區(qū)進(jìn)行商品的派送
4、 用戶可以根據(jù)自己的購(gòu)買積分,對(duì)商品進(jìn)行折扣。
問題:
如果現(xiàn)在一個(gè)用戶要查看一個(gè)定單,那么要查詢多少?gòu)埍恚?br>
定單詳情
定單編號(hào): 100001 用戶姓名: Xxx 用戶電話: Xxxxxx
用戶地區(qū): 北京 用戶地址: Xxxxx
商品總價(jià): Xxxx 定單日期: Xxx年xx月xx日 郵政編碼: Xxxxx
商品信息
No. 商品名稱 商品數(shù)量 商品單價(jià) 商品總價(jià) 折扣價(jià)格
1 Xxxx 3 90 270 200
2 Xxxx 4 78 312 300
3 Xxxx 1 10 10 5
4 Xxxx 2 20 40 8
如果要想完成以上的顯示效果,則要查詢:
· 用戶表
· 定單表
· 定單詳情表
· 商品表
· 地區(qū)表
· 子地區(qū)表
在數(shù)據(jù)庫(kù)設(shè)計(jì)中允許通過增加冗余字段的方式提升數(shù)據(jù)庫(kù)的查詢性能。
數(shù)據(jù)庫(kù)設(shè)計(jì)就必須嚴(yán)格按照要求完成,不可更改要求。
在項(xiàng)目中:一定要減少數(shù)據(jù)庫(kù)的查詢次數(shù),同時(shí)盡可能減少表的關(guān)聯(lián)查詢。 |
| |
|