Handouts
MySQL和Oracle系統學習
一. 開篇立意(必看,有說明)
- 自我系統性學習數據庫知識,包含基本SQL語句學習,MySQL.Oracle的學習,以及區別,後續會增加優化篇,水平有限,錯誤之處請批評.
- 這是我學完之後總結內容,很全,但是邏輯順序不適用新手, 可以參考順序學習:
- Oracle篇
- 基礎概念
- 表數據的操作
- 二維表的創建,維護之流
- 用戶的操作
-
二. Oracle 篇
數據庫存在之意義
我之理解,數據庫的目的就是長期有效的存儲數據,並且對數據在硬盤上進行有序排列.
基礎概念(必須看,後面不會說明!!!)
元組=記錄=行數據
屬性=字段=列數據
域:屬性的取值範圍
主鍵:辨別每行的一個或一組字段,用以區別其他元組.
別名(alias): 對字段和表起一個名字,用來簡化操作.
語法: 字段名 [as ]別名
表名 [as] 別名
其中'[]' 部分可以省略.
Oracle管理系統的介紹
- 下載略之…: [我安裝的之 Oracle 11g ]
- 驗證: 打開sql命令界面:輸入
conn system
.然後提示輸入密碼,即可.顯示已連接,安裝成功,
一些說明:
- 因爲Oracle基於C/S架構,所以基本交互流程是:Oracle client 通過
ip,port,protocol,庫名
尋找Oracle服務器,在連接數據庫. - 第三方管理軟件: 我首選
Navicate premium 15
, 執行Google,後期可能看情況出教程. - 關於連接: 選擇
TNS
模式, 這樣自己學習時候會方便一些,具體原因略之. - OracleXE 自帶賬戶:
system
sys
不帶普通用戶.Oracle11g 默認帶一個普通用戶scott
默認密碼tiger
賬戶操作
- 創建賬戶
--由於Oracle特性,先用system賬戶登錄系統,使用dba(數據庫管理員)身份,在通過system創建普通用戶(mysql非方便許多)
create user 用戶名 idenified by 密碼
eg.
create user scott idenified by xxxxxx;
--給用戶賦予權限
--賦予數據庫登錄權限
grant connect to scott;
--賦予用戶資源操作權限
grant resource to scott;
--賦予用戶dba權限
grant dba to scott;
--更改密碼
alter user scott idenified by newPassword
--撤銷權限
revoke connect, resource from 用戶名;
- 刪除用戶
drop user 用戶名
三. SQL語言
- SQL簡介:
- 非面向過程語言:強調做什麼,而非如何做.
- 作用:
- 數據庫數據的增刪改查
- 數據庫對象的創建,修改,刪除
- 用戶權限/role之授予/撤銷
- 事務控制 - 組成:
--這是overview 概覽,後續有詳細的.
數據定義語言(DDL):
CREATE DATABASE - 創建新數據庫
ALTER DATABASE - 修改數據庫
CREATE TABLE - 創建新表
ALTER TABLE - 變更(改變)數據庫表
DROP TABLE - 刪除表
CREATE INDEX - 創建索引(搜索鍵)
DROP INDEX - 刪除索引
數據操作語言(DML):I
SELECT - 從數據庫表中獲取數據
UPDATE - 更新數據庫表中的數據
DELETE - 從數據庫表中刪除數據
INSERT INTO - 向數據庫表中插入數據
數據查詢語言(DQL):SELECT 語句。
數據控制語言(DCL): GRANT、REVOKE、COMMIT、ROLLBACK 等語句。
二維表的創建
約束
約束: 限制字段屬性的一些條件,譬如字段:年齡: 邏輯上講必須 0<age<120(人類理想壽命).這就是約束.
屬性約束有: 約束命名規則
--主鍵約束 PK_表名_列名
--非空約束 NN-表名_列名
--檢查約束 CK_表名_列名
--唯一約束 UK_表名_列名
--外鍵約束 FK_表名_列名
約束的添加方法:
1. 聲明字段之後
2. 聲明表的末尾
3. 聲明表後修改/增加約束.
插嘴一句: Oracle中註釋是--xxxx, 兩個短槓後面加文字.
example
CREATE TABLE student (
sno number(10) primary key,
sname VARCHAR2(100) NOT NULL,
sage NUMBER(3) CHECK(sage>0 AND sage<120),
ssex CHAR(4) CHECK(ssex='male'OR ssex='female'),
sWeChat VARCHAR2(30) unique
--第二種方式
--添加主鍵
--constraints pk_表名_字段名 primary key(字段名)
--添加非空約束(其實就是檢查約束)
--constraints ck_student_sname check(sname is not null)
--添加檢查約束
--constraints ck_student_sage check(sage<120 and sage>0)
--添加唯一約束
--constraints un_student_sqq unique(sWeChat)
);
--備註: 最後一句一定不要有逗號',' , Oracle語法要求嚴格,不許出錯.
--第三種方法: 創建表之後
alter table 表名 add constraints 約束名 pk_表名_字段名 primary key(字段名);
alter table 表名 add constraints 約束名 ck_表名_字段名 check(字段名 is not null);
alter table 表名 add constraints 約束名 un_表名_字段名 unique(字段名);
外鍵約束
--這裏外鍵約束單獨出來講解
--概念: 子表,父表
--現有一學生表, 裏面有一字段`cid` 班級號, 另有一表`class`,班級表,包含所有班級信息.裏面有字段`cid` (可以不同名,但值必須同).此時`student` 裏面有字段依賴於`class` 表,就說=tudent是子表,class是父表.
--1. 聲明字段後:
references clazz(字段名)
--2. 聲明表,最後
constraints fk_表名_字段名 foreign key(字段名) references clazz(字段名)
--3. 聲明表後,修改/增加約束
alter table 表名 add constraints 約束名 fk_子表名_字段名 foreign key(字段名) references 父表名(字段名) on ;
######外鍵的缺點以及改善
--無法直接刪除父表數據,除非級聯刪除
--級聯刪除:
--在添加外鍵約束時,使用關鍵字 on delete cascade, 當刪除父表數據時,自動刪除子表相關所有數據。
alter table 表名 add constraints 約束名 fk_子表名_字段名 foreign key(字段名) references 父表名(字段名) on delete cascade ;
--使用關鍵字 on delete set null, 刪除父表數據時,將子表中的依賴字段的值設置爲null。注意:子表依賴字段不能添加非空約束。
刪除約束
alter table 表名 drop constraints 約束名;
alter table 表名 add constraints 約束名 fk_子表名_字段名 foreign key(字段名) references 父表名(字段名);
--備註: 如果沒有設置約束名,系統會自動分配,使用語句:
SELECT * FROM USER_CONS_COLUMNS;
--查詢對應表對應字段分配的約束名.
序列
- 意義: 方式主鍵衝突.
- 序列是Oracle專有對象,產生一個自動遞增的數列.
--創建序列
create sequence 序列名
--特點1:默認開始是沒有值的,也就是指針指在了沒有值的位置。
--特點2:序列名.nextval每次執行都會自增一次,默認步長爲1
--特點3:序列名.currval查看當前序列的值。開始是沒有的。
--作用:作爲主鍵使用,動態的獲取之間的值,這樣新增數據的時候極大的避免了主鍵衝突.
--例子
create sequence xran
insert into STUDENT values(cc.nextval,'張三',30,'male','xran656510385');
insert into STUDENT values(cc.nextval,'張三',30,'male','xran656510385');
insert into STUDENT values(cc.nextval,'張三',30,'male','xran656510385');
select * from student
--會發現sno自增1
--如何設置指定的初始值和步長?
create sequence xran--創建序列
start with 3 --設置開始位置
increment by 2 --設置步長
--這次從3開始,每次增加2.
索引
- 目的: 提升查詢效率
--索引在用戶查詢時自動起作用,通過使用快速路徑訪問方法快速定位數據,減少磁盤的I/O.
--創建: 兩種方式
--1. 聲明表時,定義primary key or unique 約束時會自動創建索引,
--2. 手動創建
create index 索引名 on 表名(字段名1,字段名2,..);
--刪除索引
drop index 索引名;
--oracle會自動給表的主鍵創建索引。默認索引字段是主鍵.
--注意: 索引適用於數據量大,數據量小範圍效率低,因爲要按目錄去比對.簡而言之:索引類似一個目錄`content`, 按照需求快速的檢索數據.避免遍歷數據的巨大耗時.
視圖 VIEW
- 我之理解:就是一個或多個表或從其他視圖中將不重要數據映射成一個表,供程序員查詢,修改,自動會同步到原表中,這樣避免重要數據的篡改.也就是說,只向外提供映射部分數據的表.
--創建視圖
create view 視圖名 as select 對外提供的內容 from 真實表名 [with read only]
--其中:[with read only] 表示對視圖設置只讀模式.
--刪除視圖
drop view 視圖名
--查詢視圖
select * from 視圖名
--特點1:保護真實表,隱藏重要字段的數據。保護數據。
--特點2:在視圖中的操作會映射執行到真實表中
--特點3:可以手動開啓只讀模式 使用關鍵字 with read only
--注意:視圖的創建必須擁有dba權限--->詳見上述用戶管理部分.
分頁
- 何爲分頁? 答曰: 將數據量很大的表分頁顯示,提供更加友好的界面.
--rownum關鍵字:oracle對外提供的自動給查詢結果編號的關鍵字,與每行的數據沒有關係
--注意:rownum關鍵字只能做< <=的判斷,不能進行> >=的判斷
--查詢學生表前五條信息,顯示咋在第一頁
select rownum, s.* from student s; where rownum<=5;
--查詢學生表第6-10條數據,顯示在第二頁
select stu.* from (select rownum r ,s.* from student s where rownum <=10) stu where r>7;
--解釋: 因爲rownum只能操作<=,故,stepone: 將<=10的數據顯示出來, 因爲這也是一張表,所以可以賦予別名, 然後根據這樣表查詢 r>=6的部分. (此時 r 是stu表中的一個字段).
--規律總結: 每頁顯示m條數據,查詢第n頁數據
select * from (select rownum r,e. * from 要分頁的表 e where rownum<=m*n) t where r>m*(n-1);
--感覺沒必要記憶,理解原理即可.
備份表
--這裏提供另外一種,有已知表創建新表,以可用作備份.
--1.
create table 新表名 as select * from 表名 ;
二維表的維護
添加新字段
alter table 表名 add 字段名 類型;
修改原有字段
--1. 修改字段類型
alter table tableName modify fieldName type;
--eg.
alter table student modify sWhChat varchar2(11);
--2. 修改字段名
alter table tableName rename column fieldName to newFieldName ;
--3. delete field
alter table tableName drop column fieldNanme;
刪除表
drop table tableName
修改表名
rename 原表名 to 新表名
表數據的操作(關鍵時刻)
- 表的執行順序:
1). from
2). where
3). group by
4). select
5). having
6). order by
--優先級遞減,order by 最後執行.顯示結果表.
null
- 先講解null, 按我的邏輯來.
--1. 任何數據類型+null = null,
--2. 一些字段篩選條件:
is null
is not null
select
SELECT [distinct] 列名稱 FROM 表名稱 ;
SELECT * FROM 表名稱
提示:星號(*)是選取所有列的快捷方式--通配符,詳見regular expression。
--關鍵字: distinct 取出結果表中重複的行;
--作用範圍: 後面所有字段
order by
--ORDER BY 語句用於根據指定的列對結果集進行排序。
--ORDER BY 語句默認按照升序對記錄進行排序。
--如果您希望按照降序對記錄進行排序,可以使用 DESC 關鍵字
SELECT field1, field2 FROM table ORDER BY field1 DESC, field2 ASC
--在第一列中有相同的值時,第二列是以升序排列的。如果第一列中有些值爲 nulls 時,情況也是這樣的.
where
- 條件查詢子句
select * from 表名 where 條件
--其中條件: 包括一些運算符
between A and B(包含邊界值)
in(vlaue1,value2,value3,...) --返回指定的字段匹配()中的值的結果.
like 模糊查詢
is [not] null 爲空值
運算符
like 模糊查詢中一些通配符:
% :表示一個或多個字符
_ :表示一個字符
escape :對於特殊符號可使用ESCAPE 標識符來查找
--eg.
select * from emp where sal between 1600 and 2900;
select * from emp where ename in('SMITH','CLARK','KING');
SELECT * FROM EMP WHERE ENAME LIKE '_/%%' escape '/'; --從emp表中查詢ename, 要求名字第二位帶有'%'的所有信息.
--escape後面指定的字符,表示like中第一次出現時,其後面的一位字符,原樣輸出.
Oracle中SQL函數
- 分爲;兩類:
-1. 單行函數
-2. 多行函數
--單行函數: 具體有哪些自己查Google,不再贅述.
--只需知道單行函數中有:字符函數,數值函數,日期函數,轉換函數,通用函數
--多行函數;
sum(), avg() 只適用於數值型
count(),max(),min() :適用於任何數據類型.
單行函數
- 這裏只講解常用的:
轉換函數: 常用:
to_char() , to_data() , to_number()
--其中數值類型與字符類型可以`影式`互轉,無需顯示強調.類似Java中的自動類型轉化.
1. number-->char
--指定顯示格式:
--9表示位置佔位,例如999,999,999會將數字按照三個一組使用逗號隔開。
--L表示人民幣符號,$表示美元符號
--0可以進行佔位分組,但是如果真實數據位數不足,會使用0進行補位。
--eg.select to_char(12345,'$999,999,999') from dual;
--其中dual是 Oracle存在的僞表,是爲了方便進行數據的驗證而臨時存在的表.
2. char-->date
--使用to_date('要轉換的字符',日期格式)函數將字符轉換爲日期
--字符必須符合日期格式,常用格式:
--yyyy-mm-dd
-- yyyy/mm/dd
3. date-->char
--使用to_char('要轉換的日期',轉換格式)
--如果不指名轉換格式,則使用默認格式,
========================================================================
其他函數
1. nvl(字段名,新的值):如果字段值不爲null,則返回該字段的值。如果爲null則返回新的值.
2. nvl2(字段名,處理1,處理2):如果字段值不爲null,則執行處理1,爲null執行處理2
3. decode(字段名,值1,處理1,值2,處理2,值3,處理3,...,公共處理)
--如果字段的值和decode中的條件值相同則執行對象的處理。如果都沒有則執行公共處理
多行函數
--除count(*)外,其餘函數都是跳過null,處理非空值.
--可以使用nvl()多函數強制限制處理空值.
select count(nvl(field,0)) form table....;
count():
--count(*) 返回表的記錄數
--count(字段名) 返回非空值的數量
--count(distinct 字段名) 去除重複後的字段值的數量
--小結:
- 多行函數(max,min,avg,sum,count)很重要
- 多行函數:不能與其他字段混用,.因爲多行函數的值只有一個(從多行中選取最合適的值)而字段這是所有行, 不能一一對應.除非分組.
- 多行函數不能和單行函數,普通字段混用,除非分組.
- 多行函數和與多行函數混用.
group by
--使用`group by` ,`select`後的字段只能是`分組的字段`和`多行函數`
--關鍵字:group by 分組字段名,分組字段名....
--注意1:使用了分組後,在select語句中只允許出現分組字段和多行函數
--注意2:如果是多字段分組,則先按照第一字段分組,然後每個小組繼續按照二個字段繼續分組,以此類推。
--注意3:在where子句中不允許出現多行函數。因爲不符合邏輯.
having
--分組篩選
--關鍵字:having
--作用:針對分組進行分組後的數據篩選,允許使用多行函數。
--注意:having關鍵必須和分組結合使用。不允許單獨使用。
--where和having的比較:
--where子句不允許出現多行函數,having允許出現多行函數
--where子句和having都可以使用普通字段直接進行篩選,但是where的效率高於having
--where執行順序: from--->where--->group by-->select-->order by
--having執行順序:from--->group by-->select--->having--->order by
--結論:在分組語句中,使用where進行字段級別的篩選,使用having進行多行函數的篩選
--執行過程:
from--where--group by--select--having--order by
eg. SELECT JOB,COUNT(*) FROM EMP GROUP BY JOB;
--分析: 先從from開始,選擇表emp,然後執行where(沒有), 然後執行group by 按照job分組: 然後統計每組中個數.即執行select中的語句.最後進行排序 orderby (沒有) .
--我覺得講的可以了吧,覺得還行的扣111.
insert into
insert into 表名(字段名,字段名,...)values(值1,值2,值3....);
--注意1:主鍵必須給值,允許爲空的字段可以不給值。
--注意2:插入語句表名後跟的字段名爲要賦值的字段,值和字段數量和順序必須是一一對應的。
--注意3:如果是全字段插入,可以省略字段名部分 insert into 表名 values(值1,值2,.....)
delete from
delete from 表名 刪除表中的所有記錄
delete from 表名 where 條件 刪除指定的數據,只要符合條件就會刪除
truncate table 表名 刪除表中的所有記錄,但是效率高於deletetruncate table 表名 刪除表中的所有記錄,但是效率高於delete
update
--update 表名 set 字段名=新的值,字段名=新的值...(會將字段的值全部改爲新的值)
--update 表名 set 字段名=新的值,字段名=新的值... where 條件(將符合條件的數據的字段改爲新的值)
多表聯合查詢(最後的榮光,堅持吧! 勇士)
- 簡介: SQL92 和 SQL99
- 都可以用, 具體用哪個,隨你.
- SQL92方式(92年標準)---不帶全外連接
- SQL99方式(99年標準)
連接方式:`笛卡爾積`,`等值鏈接`, `不等值連接`,` 自連接`. , `外連接`
SQL92
--笛卡爾積:將多個表的數據進行一一對應,所得到結果爲多表的笛卡爾積。
--結果的數量爲所有表的數量的乘積
--等值連接篩選
--概念:先做表的笛卡爾積,然後篩選,篩選條件爲等值篩選。
--注意:條件爲字段的值相同來進行篩選,字段的名字可以不同
--等值連接,是要一個字段沒有值`null` ,會被篩選掉,但想要的話必須用外連接
--不等值連接 : 將等值連接的'=' 轉化爲非等號.
--自連接:
--查詢員工姓名,工作,薪資,及上級領導姓名
select e1.ename,e1.job,e1.sal,e2.ename from emp e1,emp e2 where e1.mgr=e2.empno
--注意: 自連接特徵: 一般有兩個字段值相同, 名字無所謂.
--其實,總的來說,上述所見,都可以歸結於等值連接的變種.具體情況具體分析即可.
========================================================================
外連接: 何爲外連接?
--由來: 因爲上述連接,查詢的都是非空字段,null字段自動過濾,但是成年人不要選擇,我全都要,這樣的話如何爲之?
--解決: 採用外連接: 即可
分類: 左外連接,右外連接
首先強調:
SELECT *FROM EMP e,DEPT d WHERE e.DEPTNO=d.DEPTNO;
--這個statement中結果集的字段順序是,先e表中的所有字段,然後是d中的所有字段.所以左表是e,右表是d.
左外連接: 左表爲基準,就是左表的屬性全部顯示,然後顯示右表符合條件的字段.包含null.
右外連接: 類似上面,以右表爲基準,全部顯示, 左表只顯示與條件相符合的字段.
符號'+': 根據語義,左外連接,就是將'+' 放在左表之外的右表上.
右外連接: 就是將'+' 放在右表之外,左表上.
--猜一猜下面的statement是什麼連接? 請回答!!!
SELECT *FROM EMP e,DEPT d WHERE e.DEPTNO(+)=d.DEPTNO;
SQL99
--笛卡爾積:使用cross join 關鍵字
---select 內容 from 表名 cross join 表名2
--自然連接:使用關鍵字 natural join
--使用:select 內容 from 表名 natural join 表名
--特點1:底層先笛卡爾積,然後按照''所有的同名同值''字段自動進行等值篩選
--問題1:如果只想按照部分字段結果篩選怎麼辦?--using
--問題2:如果想按照字段名不同,但是值相同進行等值篩選怎麼辦?--on
--解決1:使用using關鍵字
--作用1:指明使用指定的字段對聯合查詢的結果進行等值篩選
--注意:指明的字段必須是兩表的同名同值字段
--使用:select 內容 from 表名 inner join 表名 using(字段名,字段名,....);
--解決2:使用on關鍵字進行自定義連接條件篩選(等值篩選,不等值篩選)
--注意:普通篩選條件使用where進行篩選,不要使用on進行。好處:SQL語句的閱讀性變強。
--使用:select 內容 from 表名 inner join 表名 on 連接條件 where 普通篩選條件
--自連接:
select .. inner join .. on..where...
==========================================================
外連接:
--左外連接:select 內容 from 表名 left outer join 表名 on 連接條件 ;
--右外連接:select 內容 from 表名 right outer join 表名 on 連接條件;
--全外連接:select 內容 from 表名 full outer join 表名 on 連接條件 ;
--提示: 一般可以省略 inner 和 outer ,但是官方建議寫出具體語義會好些.
這裏不再贅述.與SQL92一樣,使用差不多,公式給出,就用.
子查詢(Oracle最後的關卡,收官之戰)
--單行子查詢:
--使用時機:篩選條件不明確需要執行一次查詢,並且查詢結果一個字段並值只有一個
--注意:where子句中允許出現查詢語句,該查詢語句稱爲子查詢
--使用:select 內容 from 表名 where 字段名 比較運算符 子查詢語句
--多行子查詢
--使用:子查詢的結果只有一個字段但是字段有n個值,考慮使用多行子查詢,其實就是使用關鍵字
--關鍵字1:any 任意
--select 內容 from 表名 where 字段名 比較運算符 any 子查詢語句
--關鍵字2:all 所有
--select 內容 from 表名 where 字段名 比較運算符 all 子查詢語句
--關鍵字3:(not)in 表示任意存在,相當於 = any
--select 內容 from 表名 where 字段名 in 子查詢語句
--select 內容 from 表名 where 字段名 not in 子查詢語句
Oracle篇暫時完結. MySQL會更新.莫得急~~~
四. MySQL 篇
)