mysql基礎部分-史上最全
MySql資料庫
前言
隨便開啟一個Web網站,比如淘寶:
為什麼學習MySQL資料庫?
MySQL廣佔IT市場,比如淘寶、網易、百度、新浪、facebook等大部分網際網路公司,都在使用mysql軟體,而且在網路遊戲領域,大部分的後臺資料庫都在使用mysql,如勁舞團、魔獸世界,還有更厲害的,中國電網、中國移動中很多專案也在使用我們的mysql。
如果我們把mysql學好學精了,還愁沒工作嗎?我們甚至可以去任何IT行業公司,這不像小眾 的產品,你哪怕學透了,也不一定有多少人要你。
第1章 資料庫概述
1.1 什麼是資料庫
資料庫是持久化資料的一種介質,可以理解成用來儲存和管理
持久化(persistence):把資料儲存到可掉電式儲存裝置中以供之後使用。持久化的大多數時候是將記憶體中的資料儲存在資料庫中,當然也可以儲存在磁碟檔案、XML資料檔案中。
1.2為什麼要用資料庫
儲存資料 的容器:陣列、集合、檔案
儲存到檔案:
- 可將資料持久化到硬碟
- 可儲存大量資料
- 方便檢索
- 保證資料的一致性、完整性
- 安全,可共享
- 通過組合分析,可以產生新資料
1.3常見資料庫產品
u Oracle:甲骨文
u DB2:IBM;
u SQL Server:微軟;
u MySQL:甲骨文;
1.4資料庫相關概念
- DB
資料庫( database ):儲存資料的“倉庫”。它儲存了一系列有組織的資料。
- DBMS
資料庫管理系統( Database Management System )。資料庫是通過 DBMS 創
建和操作的容器
- SQL
結構化查詢語言( Structure Query Language ):專門用來與資料庫通訊的語
言。
三者的關係:
1.5資料庫儲存資料的特點
n 將資料放到表中,表再放到庫中
n 一個數據庫中可以有多個表,每個表都有一個的名字,用來標識自己。表名具有唯一性。
n 表具有一些特性,這些特性定義了資料在表中如何儲存,類似java中 “類”的設計。
n 表由列組成,我們也稱為欄位。所有表都是由一個或多個列組成的,每一列類似java 中的”屬性”
n 表中的資料是按行儲存的,每一行類似於java中的“物件”
² 表——類
² 列,欄位——屬性
² 行——物件
第2章 MySQL資料庫的介紹
2.1 MySQL產品的介紹
MySQL是一種開放原始碼的關係型資料庫管理系統,開發者為瑞典MySQL AB公司。在2008年1月16號被Sun公司收購。而2009年,SUN又被Oracle收購.目前 MySQL被廣泛地應用在Internet上的中小型網站中。由於其體積小、速度快、總體擁有成本低,尤其是開放原始碼這一特點,許多中小型網站為了降低網站總體擁有成本而選擇了MySQL作為網站資料庫(Facebook, Twitter, YouTube)。阿里提出“去IOE”,更多網站也開始選擇MySQL。[I1]
2.2 MySQL產品的優點
- 成本低:開放原始碼,一般可以免費試用
- 效能高:執行很快
- 簡單:很容易安裝和使用
2.2 MySQL服務端的安裝和解除安裝
DBMS分為兩類:
– 基於共享檔案系統的DBMS (Access )
– 基於客戶機——伺服器的DBMS C/S
(MySQL、Oracle、SqlServer)
注:檢視資料庫的安裝和解除安裝文件
1、解除安裝
1)軟體的解除安裝
方式一:通過控制面板
方式二:通過電腦管家等軟體解除安裝
方式三:通過安裝包中提供的解除安裝功能解除安裝
2)清理殘餘檔案
如果再次安裝不成功,可以解除安裝後對殘餘檔案進行清理後再安裝
a)清除安裝殘餘檔案
b)清除資料殘餘檔案
請在解除安裝前做好資料備份
c)清理登錄檔
如果前兩步做了,再次安裝還是失敗,那麼可以清理登錄檔
1:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL服務 目錄刪除
2:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MySQL服務 目錄刪除
3:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL服務 目錄刪除
4:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\MySQL服務 目錄刪除
5:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL服務目錄刪除
6:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL服務刪除
登錄檔中的ControlSet001,ControlSet002,不一定是001和002,可能是ControlSet005、006之類
2、安裝
(1)準備安裝
(2)歡迎安裝
(3)准許協議
(4)選擇安裝模式
Typical:表示一般常用的元件都會被安裝,預設情況下安裝到”C:\Program Files\MySQL\MySQL Server 5.5\”下。
Complete:表示會安裝所有的元件。此套件會佔用比較大的磁碟空間。
Custom:表示使用者可以選擇要安裝的元件,可以更改預設按照的路徑。這種按照型別最靈活,適用於高階使用者。
(5)選擇安裝元件及安裝路徑
這裡可以選擇安裝哪些部分,主要是這裡可以設定兩個路徑:
MySQL Server的應用軟體的安裝路徑,預設在“C:\Program Files\MySQL\MySQL Server 5.5\”
Server data files的資料儲存的目錄路徑,預設在“C:\ProgramData\MySQL\MySQL Server 5.5\”
1、建議目錄非中文、無空格等特殊符號 2、建議把資料儲存的目錄路徑修改一下,以防系統崩潰或重灌系統時資料保留。 |
(6)開始安裝
安裝進度
系統會顯示MySQL Enterprise版(企業版)的一些功能介紹介面,可以單擊“Next”繼續。
(7)安裝完成
單擊“Finish”按鈕完成安裝過程。如果想馬上配置資料庫連線,選擇“Launch the MySQL Instance Configuration Wizard”複選框。如果現在沒有配置,以後想要配置或重新配置都可以在“MySQL Server”的安裝目錄的bin目錄下(例如:D:\ProgramFiles\MySQL5.5\MySQL Server 5.5\bin)找到“MySQLInstanceConfig.exe”開啟“MySQL Instance Configuration Wizard”嚮導。
3、MySQL的配置
(1)準備開始
(2)選擇配置型別
選擇配置方式,“Detailed Configuration(手動精確配置)”、“Standard Configuration(標準配置)”,我們選擇“Detailed Configuration”,方便熟悉配置過程。
(3)選擇MySQL的應用模式
Develop Machine(開發機),使用最小數量的記憶體
Server Machine(伺服器),使用中等大小的記憶體
Dedicated MySQL Server Machine(專用伺服器),使用當前可用的最大記憶體。
(4)選擇資料庫用途選擇介面
選擇mysql資料庫的大致用途:
“Multifunctional Database(通用多功能型,好)”:此選項對事務性儲存引擎(InnoDB)和非事務性(MyISAM)儲存引擎的存取速度都很快。
“Transactional Database Only(伺服器型別,專注於事務處理,一般)”:此選項主要優化了事務性儲存引擎(InnoDB),但是非事務性(MyISAM)儲存引擎也能用。
“Non-Transactional Database Only(非事務處理型,較簡單)主要做一些監控、記數用,對MyISAM資料型別的支援僅限於non-transactional,注意事務性儲存引擎(InnoDB)不能用。
(5)配置InnoDB資料檔案目錄
InnoDB的資料檔案會在資料庫第一次啟動的時候建立,預設會建立在MySQL的安裝目錄下。使用者可以根據實際的空間狀況進行路徑的選擇。
(6)併發連線設定
選擇您的網站的一般mysql 訪問量,同時連線的數目,“Decision Support(DSS)/OLAP(決策支援系統,20個左右)”、“Online Transaction Processing(OLTP)(線上事務系統,500個左右)”、“Manual Setting(手動設定,自己輸一個數)”
(7)網路選項設定
是否啟用TCP/IP連線,設定埠,如果不啟用,就只能在自己的機器上訪問mysql 資料庫了,我這裡啟用,把前面的勾打上,Port Number:3306,還有一個關於防火牆的設定“Add firewall exception ……”需要選中,將MYSQL服務的監聽埠加為windows防火牆例外,避免防火牆阻斷。
在這個頁面上,您還可以選擇“啟用標準模式”(Enable Strict Mode),這樣MySQL就不會允許細小的語法錯誤。儘量使用標準模式,因為它可以降低有害資料進入資料庫的可能性。
(8)選擇字符集
注意:如果要用原來資料庫的資料,最好能確定原來資料庫用的是什麼編碼,如果這裡設定的編碼和原來資料庫資料的編碼不一致,在使用的時候可能會出現亂碼。
這個比較重要,就是對mysql預設資料庫語言編碼進行設定,第一個是西文編碼,第二個是多位元組的通用utf8編碼,第三個,手工選擇字符集。
提示:
如果安裝時選擇了字符集和“utf8”,通過命令列客戶端來操作資料庫時,有時候會出現亂碼,
這是因為“命令列客戶端”預設是GBK字符集,因此客戶端與伺服器端就出現了不一致的情況,會出現亂碼。
可以在客戶端執行:
mysql> set names gbk;
可以通過以下命令檢視:
mysql> show variables like 'character_set_%';
對於客戶端和伺服器的互動操作,MySQL提供了3個不同的引數:character_set_client、character_set_connection、character_set_results,分別代表客戶端、連線和返回結果的字符集。通常情況下,這3個字符集應該是相同的,才能確保使用者寫入的資料可以正確的讀出和寫入。“set names xxx;”命令可以同時修改這3個引數的值,但是需要每次連線都重新設定。
(9)安全選擇
選擇是否將mysql 安裝為windows服務,還可以指定Service Name(服務標識名稱,例如我這裡取名為“MySQL5.5”),是否將mysql的bin目錄加入到Windows PATH環境變數中(加入後,就可以直接使用bin下的命令)”,我這裡全部打上了勾。
(10)設定密碼
這一步詢問是否要修改預設root 使用者(超級管理)的密碼(預設為空),“New root password”如果要修改,就在此填入新密碼,“Confirm(再輸一遍)”內再填一次,防止輸錯。(如果是重灌,並且之前已經設定了密碼,在這裡更改密碼可能會出錯,請留空,並將“Modify Security Settings”前面的勾去掉,安裝配置完成後另行修改密碼)
“Enable root access from remotemachines(是否允許root 使用者在其它的機器或使用IP地址登陸,如果要安全,就不要勾上,如果要方便,就勾上它)”。如果沒有勾選,預設只支援localhost和127.0.0.1連線。
最後“Create An Anonymous Account(新建一個匿名使用者,匿名使用者可以連線資料庫,不能操作資料,包括查詢,如果要有操作資料的許可權需要單獨分配)”,一般就不用勾了
(11)準備執行介面
(12)完成
2.3 MySQL的安裝目錄
u bin目錄中都是可執行檔案;
u my.ini檔案是MySQL的配置檔案;
u MySQL的資料儲存目錄為data
u data目錄通常在C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.1\data位置。
u 在data下的每個目錄都代表一個數據庫。
2.4 MySQL環境變數的配置
將C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin;新增到path中
第3章 MySQL的使用
1、啟動和停止服務
MySQL軟體的伺服器端必須先啟動,客戶端才可以連線和使用使用資料庫。
啟動服務的方式:
方式一:圖形化方式
“我的電腦/計算機”-->右鍵-->“管理”-->“服務”-->啟動和關閉MySQL
“開始選單”-->“控制面板”-->“管理工具”-->“服務”-->啟動和關閉MySQL
“工作管理員”-->“服務”-->啟動和關閉MySQL
方式二:命令列
以管理員身份執行
net start MySQL服務名
net stop MySQL服務名
2、客戶端登入
方式一:MySQL自帶客戶端
“開始選單”-->MySQL-->MySQL Server 5.5 --> MySQL 5.5 Command Line Client
僅限於root使用者
方式二:命令列
mysql -h 主機名 -P 埠號 -u 使用者名稱 -p密碼
例如:mysql -h localhost -P 3306 -u root -proot
注意:
(1)-p與密碼之間不能有空格,其他引數名與引數值之間可以有空格也可以沒有空格
mysql -hlocalhost -P3306 -uroot -proot
(2)密碼建議在一行輸入
mysql -h localhost -P 3306 -u root -p
Enter password:****
(3)如果是連本機:-hlocalhost就可以省略,如果埠號沒有修改:-P3306也可以省略
簡寫成:mysql -u root -p
Enter password:****
連線成功後,有關於MySQL Server服務版本的資訊,還有第幾次連線的id標識。
也可以在命令列通過以下方式獲取MySQL Server服務版本的資訊
或登入後,通過以下方式檢視當前版本資訊:
方式三:視覺化工具
例如:Navicat Preminum,SQLyogEnt等工具
還有其他工具:mysqlfront,phpMyAdmin
(1)Navicat Preminum
(2)SQLyog
3、MySQL的基本命令
啟動和關閉mysql服務
方式一:
l 啟動:net start mysql;
l 關閉:net stop mysql;
方式二:
在啟動mysql服務後,開啟windows工作管理員,會有一個名為mysqld.exe的程序執行,所以mysqld.exe才是MySQL伺服器程式。
客戶端登入退出mysql
在啟動MySQL伺服器後,我們需要使用管理員使用者登入MySQL伺服器,然後來對伺服器進行操作。登入MySQL需要使用MySQL的客戶端程式:mysql.exe
l 登入:mysql -u root -p root -h localhost;
- -u:後面的root是使用者名稱,這裡使用的是超級管理員root;
- -p:後面的root是密碼,這是在安裝MySQL時就已經指定的密碼;
- -h:後面給出的localhost是伺服器主機名,它是可以省略的,例如:mysql -u root -p root;
l 退出:quit或exit;
在登入成功後,開啟windows工作管理員,會有一個名為mysql.exe的程序執行,所以mysql.exe是客戶端程式。
第4章 SQL語句
4.1 SQL概述
1. 什麼是SQL
SQL(Structured Query Language)是“結構化查詢語言”,它是對關係型資料庫的操作語言。它可以應用到所有關係型資料庫中,例如:MySQL、Oracle、SQL Server等。SQL標準有:
l 1986年,ANSI X3.135-1986,ISO/IEC 9075:1986,SQL-86
l 1989年,ANSI X3.135-1989,ISO/IEC 9075:1989,SQL-89
l 1992年,ANSI X3.135-1992,ISO/IEC 9075:1992,SQL-92(SQL2)
l 1999年,ISO/IEC 9075:1999,SQL:1999(SQL3)
l 2003年,ISO/IEC 9075:2003,SQL:2003
l 2008年,ISO/IEC 9075:2008,SQL:2008
l 2011年,ISO/IEC 9075:2011,SQL:2011
l 2016年,ISO/IEC 9075:2016,SQL:2016
這些標準就與JDK的版本一樣,在新的版本中總要有一些語法的變化。不同時期的資料庫對不同標準做了實現。
雖然SQL可以用在所有關係型資料庫中,但很多資料庫還都有標準之後的一些語法,我們可以稱之為“方言”。例如MySQL中的LIMIT語句就是MySQL獨有的方言,其它資料庫都不支援!當然,Oracle或SQL Server都有自己的方言。
2. SQL語法要求
l SQL語句可以單行或多行書寫,以分號結尾;
l 可以用空格和縮排來來增強語句的可讀性;
l 關鍵字不區別大小寫,建議使用大寫;
4.2 分類
l DDL(Data Definition Language):資料定義語言,用來定義資料庫物件:庫、表、列等;
l DML(Data Manipulation Language):資料操作語言,用來定義資料庫記錄(資料);
l DCL(Data Control Language):資料控制語言,用來定義訪問許可權和安全級別;
l DQL(Data Query Language):資料查詢語言,用來查詢記錄(資料)。
4.3 DQL
DQL就是資料查詢語言,資料庫執行DQL語句不會對資料進行改變,而是讓資料庫傳送結果集給客戶端。
語法:
SELECT
selection_list /*要查詢的列名稱*/
FROM
table_list /*要查詢的表名稱*/
WHERE
condition /*行條件*/
GROUP BY
grouping_columns /*對結果分組*/
HAVING
condition /*分組後的行條件*/
ORDER BY
sorting_columns /*對結果分組*/
LIMIT
offset_start, row_count /*結果限定*/
建立名:
l 學生表:stu
欄位名稱 |
欄位型別 |
說明 |
sid |
char(6) |
學生學號 |
sname |
varchar(50) |
學生姓名 |
age |
int |
學生年齡 |
gender |
varchar(50) |
學生性別 |
CREATE TABLE stu ( sid CHAR(6), sname VARCHAR(50), age INT, gender VARCHAR(50) ); |
INSERT INTO stu VALUES('S_1001', 'liuYi', 35, 'male'); INSERT INTO stu VALUES('S_1002', 'chenEr', 15, 'female'); INSERT INTO stu VALUES('S_1003', 'zhangSan', 95, 'male'); INSERT INTO stu VALUES('S_1004', 'liSi', 65, 'female'); INSERT INTO stu VALUES('S_1005', 'wangWu', 55, 'male'); INSERT INTO stu VALUES('S_1006', 'zhaoLiu', 75, 'female'); INSERT INTO stu VALUES('S_1007', 'sunQi', 25, 'male'); INSERT INTO stu VALUES('S_1008', 'zhouBa', 45, 'female'); INSERT INTO stu VALUES('S_1009', 'wuJiu', 85, 'male'); INSERT INTO stu VALUES('S_1010', 'zhengShi', 5, 'female'); INSERT INTO stu VALUES('S_1011', 'xxx', NULL, NULL); |
l 僱員表:emp
欄位名稱 |
欄位型別 |
說明 |
empno |
int |
員工編號 |
ename |
varchar(50) |
員工姓名 |
job |
varchar(50) |
員工工種 |
mgr |
int |
領導編號 |
hiredate |
date |
入職日期 |
sal |
decimal(7,2) |
月薪 |
comm |
decimal(7,2) |
獎金 |
deptno |
int |
部門編號 |
CREATE TABLE emp( empno INT, ename VARCHAR(50), job VARCHAR(50), mgr INT, hiredate DATE, sal DECIMAL(7,2), comm decimal(7,2), deptno INT ) ; |
INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20); INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30); INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30); INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20); INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30); INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30); INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10); INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20); INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10); INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30); INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20); INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30); INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20); INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10); |
l 部分表:dept
欄位名稱 |
欄位型別 |
說明 |
deptno |
int |
部門編號 |
dname |
varchar(50) |
部分名稱 |
loc |
varchar(50) |
部門所在地點 |
CREATE TABLE dept( deptno INT, dname varchar(14), loc varchar(13) ); |
INSERT INTO dept values(10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO dept values(20, 'RESEARCH', 'DALLAS'); INSERT INTO dept values(30, 'SALES', 'CHICAGO'); INSERT INTO dept values(40, 'OPERATIONS', 'BOSTON'); |
1.基礎查詢
1.1 查詢學生表中的所有列
1.2 查詢指定列
2.條件查詢
介紹
條件查詢就是在查詢時給出WHERE子句,在WHERE子句中可以使用如下運算子及關鍵字:
l =、!=、<>、<、<=、>、>=;
l AND、OR、NOT
l BETWEEN…AND、IN(set)、IS NULL
案例
案例1:查詢工資>10000的員工資訊
案例2:查詢 job_id不是'IT_PROG'的員工姓名、job_id、salary
案例3:查詢工資>10000並且小於20000的員工姓名、工資、年薪
案例4:查詢部門編號不在90到120之間的並且 工資>15000的員工資訊
3.模糊查詢
- like
當想查詢姓名中包含a字母的學生時就需要使用模糊查詢了。模糊查詢需要使用關鍵字LIKE。
#案例1:查詢員工資訊表中姓名第一個字元為e的員工資訊
#案例2:查詢員工資訊表中姓名第二個字元為e,第五個字元為a的員工資訊
#案例3:查詢姓名中前面字元為ernst的員工資訊
#案例4:查詢姓名中第二個字元為_的員工資訊
#方式一:直接通過\進行轉義
#方式二:通過escape關鍵字指定轉義字元
- between and
特點:
①用於篩選某個欄位或表示式是否在指定的區間範圍
②等價於 使用邏輯表示式的效果,只是語法上更加簡單
③兩個區間值不能調換順序
- 兩個區間值包含
>=左區間 and <=右區間
#案例1:查詢年薪在100000到200000的員工年薪和姓名
#案例2:查詢年薪不在100740到187200的員工年薪和姓名
- in
#案例1:查詢工種編號是IT_PROT或是ST_CLERK或是AD_VP的員工資訊
- is null
#案例1:查詢哪個員工沒有獎金
#案例2:查詢哪個員工有獎金
4.欄位控制查詢
- 去除重複記錄
去除重複記錄(兩行或兩行以上記錄中系列的上的資料都相同),例如emp表中sal欄位就存在相同的記錄。當只查詢emp表的sal欄位時,那麼會出現重複記錄,那麼想去除重複記錄,需要使用DISTINCT:
- 檢視僱員的月薪與佣金之和(IFNULL函式)
因為sal和comm兩列的型別都是數值型別,所以可以做加運算。如果sal或comm中有一個欄位不是數值型別,那麼會出錯。
comm列有很多記錄的值為NULL,因為任何東西與NULL相加結果還是NULL,所以結算結果可能會出現NULL。下面使用了把NULL轉換成數值0的函式IFNULL:
- 給列名新增別名
方式一:
select 列名 as 別名 from 表名;
方式二:
select 列名 別名 from 表名;
5.排序 order by
1)按單個欄位進行升序 ★
案例1:按工資從低到高排序
案例2:按工資從低到高排序
2).按多個欄位排序
案例1:部門編號>50的按工資從高到低排序,如果一樣,再按frist_name升序
3).按表示式排序
案例:將姓名中包含e字元的年薪和姓名顯示出來,並且按年薪進行降序
4).按別名排序
案例:將姓名中包含e字元的年薪和姓名顯示出來,並且按年薪進行降序
5).按函式排序
案例:顯示所有有獎金的員工姓名、獎金、姓名的長度,按姓名的長度從低到高排序
6.常見函式
MySQL資料庫提供了很多函式包括:
l 數學函式;
l 字串函式;
l 日期和時間函式;
l 條件判斷函式;流程控制函式;
l 系統資訊函式;
l 加密函式;
l 格式化函式;
1)、數學函式
ABS(x) |
返回x的絕對值 |
CEIL(x) |
返回大於x的最小整數值 |
FLOOR(x) |
返回大於x的最大整數值 |
MOD(x,y) |
返回x/y的模 |
RAND(x) |
返回0~1的隨機值 |
ROUND(x,y) |
返回引數x的四捨五入的有y位的小數的值 |
TRUNCATE(x,y) |
返回數字x截斷為y位小數的結果 |
SQRT(x) |
返回x的平方根 |
POW(x,y) |
返回x的y次方 |
2)、字串函式
CONCAT(S1,S2,......,Sn) |
連線S1,S2,......,Sn為一個字串 |
CONCAT(s, S1,S2,......,Sn) |
同CONCAT(s1,s2,...)函式,但是每個字串之間要加上s |
CHAR_LENGTH(s) |
返回字串s的字元數 |
LENGTH(s) |
返回字串s的位元組數,和字符集有關 |
INSERT(str, index , len, instr) |
將字串str從第index位置開始,len個字元長的子串替換為字串instr |
UPPER(s) 或 UCASE(s) |
將字串s的所有字母轉成大寫字母 |
LOWER(s) 或LCASE(s) |
將字串s的所有字母轉成小寫字母 |
LEFT(s,n) |
返回字串s最左邊的n個字元 |
RIGHT(s,n) |
返回字串s最右邊的n個字元 |
LPAD(str, len, pad) |
用字串pad對str最左邊進行填充,直到str的長度為len個字元 |
RPAD(str ,len, pad) |
用字串pad對str最右邊進行填充,直到str的長度為len個字元 |
LTRIM(s) |
去掉字串s左側的空格 |
RTRIM(s) |
去掉字串s右側的空格 |
TRIM(s) |
去掉字串s開始與結尾的空格 |
TRIM(【BOTH 】s1 FROM s) |
去掉字串s開始與結尾的s1 |
TRIM(【LEADING】s1 FROM s) |
去掉字串s開始處的s1 |
TRIM(【TRAILING】s1 FROM s) |
去掉字串s結尾處的s1 |
REPEAT(str, n) |
返回str重複n次的結果 |
REPLACE(str, a, b) |
用字串b替換字串str中所有出現的字串a |
STRCMP(s1,s2) |
比較字串s1,s2 |
SUBSTRING(s,index,len) |
返回從字串s的index位置其len個字元 |
3)、日期時間函式
CURDATE() 或 CURRENT_DATE() |
返回當前日期 |
CURTIME() 或 CURRENT_TIME() |
返回當前時間 |
NOW() SYSDATE() CURRENT_TIMESTAMP() LOCALTIME() LOCALTIMESTAMP() |
返回當前系統日期時間 |
YEAR(date) MONTH(date) DAY(date) HOUR(time) MINUTE(time) SECOND(time) |
返回具體的時間值 |
WEEK(date) WEEKOFYEAR(date) |
返回一年中的第幾周 |
DAYOFWEEK() |
返回周幾,注意:週日是1,週一是2,。。。週六是7 |
WEEKDAY(date) |
返回周幾,注意,周1是0,周2是1,。。。週日是6 |
DAYNAME(date) |
返回星期:MONDAY,TUESDAY.....SUNDAY |
MONTHNAME(date) |
返回月份:January,。。。。。 |
DATEDIFF(date1,date2) TIMEDIFF(time1, time2) |
返回date1 - date2的日期間隔 返回time1 - time2的時間間隔 |
DATE_ADD(datetime, INTERVALE expr type) |
返回與給定日期時間相差INTERVAL時間段的日期時間 |
DATE_FORMAT(datetime ,fmt) |
按照字串fmt格式化日期datetime值 |
STR_TO_DATE(str, fmt) |
按照字串fmt對str進行解析,解析為一個日期 |
l (1)DATE_ADD(datetime,INTERVAL expr type)
SELECT DATE_ADD(NOW(), INTERVAL 1 YEAR); SELECT DATE_ADD(NOW(), INTERVAL -1 YEAR); #可以是負數 SELECT DATE_ADD(NOW(), INTERVAL '1_1' YEAR_MONTH); #需要單引號 |
|
表示式型別 |
YEAR_MONTH |
YEAR |
DAY_HOUR |
MONTH |
DAY_MINUTE |
DAY |
DAY_SECOND |
HOUR |
HOUR_MINUTE |
MINUTE |
HOUR_SECOND |
SECOND |
MINUTE_SECOND |
l (2)DATE_FORMAT(datetime ,fmt)和STR_TO_DATE(str, fmt)
格式符 |
說明 |
格式符 |
說明 |
%Y |
4位數字表示年份 |
%y |
表示兩位數字表示年份 |
%M |
月名錶示月份(January,....) |
%m |
兩位數字表示月份(01,02,03。。。) |
%b |
縮寫的月名(Jan.,Feb.,....) |
%c |
數字表示月份(1,2,3,...) |
%D |
英文字尾表示月中的天數(1st,2nd,3rd,...) |
%d |
兩位數字表示月中的天數(01,02...) |
%e |
數字形式表示月中的天數(1,2,3,4,5.....) |
||
%H |
兩位數字表示小數,24小時制(01,02..) |
%h和%I |
兩位數字表示小時,12小時制(01,02..) |
%k |
數字形式的小時,24小時制(1,2,3) |
%l |
數字形式表示小時,12小時制(1,2,3,4....) |
%i |
兩位數字表示分鐘(00,01,02) |
%S和%s |
兩位數字表示秒(00,01,02...) |
%W |
一週中的星期名稱(Sunday...) |
%a |
一週中的星期縮寫(Sun.,Mon.,Tues.,..) |
%w |
以數字表示週中的天數(0=Sunday,1=Monday....) |
||
%j |
以3位數字表示年中的天數(001,002...) |
%U |
以數字表示年中的第幾周,(1,2,3。。)其中Sunday為週中第一天 |
%u |
以數字表示年中的第幾周,(1,2,3。。)其中Monday為週中第一天 |
||
%T |
24小時制 |
%r |
12小時制 |
%p |
AM或PM |
%% |
表示% |
4)、流程函式
IF(value,t ,f) |
如果value是真,返回t,否則返回f |
IFNULL(value1, value2) |
如果value1不為空,返回value1,否則返回value2 |
CASE WHEN 條件1 THEN result1 WHEN 條件2 THEN result2 .... [ELSE resultn] END |
相當於Java的if...else if... |
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 .... [ELSE 值n] END |
相當於Java的switch |
SELECT ename ,CASE WHEN salary>=15000 THEN '高薪' WHEN salary>=10000 THEN '潛力股' WHEN salary>=8000 THEN '屌絲' ELSE '草根' END FROM t_employee; |
|
SELECT oid,`status`, CASE `status` WHEN 1 THEN '未付款' WHEN 2 THEN '已付款' WHEN 3 THEN '已發貨' WHEN 4 THEN '確認收貨' ELSE '無效訂單' END FROM t_order; |
7.分組(聚合)函式
聚合函式是用來做縱向運算的函式:
l COUNT():統計指定列不為NULL的記錄行數;
l MAX():計算指定列的最大值,如果指定列是字串型別,那麼使用字串排序運算;
l MIN():計算指定列的最小值,如果指定列是字串型別,那麼使用字串排序運算;
l SUM():計算指定列的數值和,如果指定列型別不是數值型別,那麼計算結果為0;
l AVG():計算指定列的平均值,如果指定列型別不是數值型別,那麼計算結果為0;
- COUNT
當需要縱向統計時可以使用COUNT()。
l 查詢emp表中記錄數:
l 查詢emp表中有佣金的人數:
注意,因為count()函式中給出的是comm列,那麼只統計comm列非NULL的行數。
l 查詢emp表中月薪大於2500的人數:
l 統計月薪與佣金之和大於2500元的人數:
l 查詢有佣金的人數,以及有領導的人數:
- SUM和AVG
當需要縱向求和時使用sum()函式。
l 查詢所有僱員月薪和:
l 查詢所有僱員月薪和,以及所有僱員佣金和:
l 查詢所有僱員月薪+佣金和:
l 統計所有員工平均工資:
- MAX和MIN
l 查詢最高工資和最低工資:
8.分組查詢
當需要分組查詢時需要使用GROUP BY子句,例如查詢每個部門的工資和,這說明要使用部分來分組。
案例:
1)簡單的分組
案例1:查詢每個工種的員工平均工資
2)可以實現分組前的篩選
案例1:查詢郵箱中包含a字元的 每個部門的最高工資
案例2:查詢有獎金的每個領導手下員工的平均工資
3)可以實現分組後的篩選
案例1:查詢哪個部門的員工個數>5
案例2:每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
案例3:領導編號>102的每個領導手下的最低工資大於5000的領導編號和最低工資
4)可以實現排序
案例:每個工種有獎金的員工的最高工資>6000的工種編號和最高工資,按最高工資升序
5)按多個欄位分組
案例:查詢每個工種每個部門的最低工資,並按最低工資降序
在SELECT 列表中所有未包含在組函式中的列都應該包含 在 GROUP BY 子句中。 |
9.連線查詢
概念:
笛卡爾集會在下面條件下產生:
– 省略連線條件
– 連線條件無效
– 所有表中的所有行互相連線
為了避免笛卡爾集, 可以在 WHERE 加入有效的連線條件
分析:
那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。
案例分析:
你能想像到emp和dept表連線查詢的結果麼?emp一共14行記錄,dept表一共4行記錄,那麼連線後查詢出的結果是56行記錄。
Sql語句:SELECT * FROM emp,dept;
查詢結果:
也就你只是想在查詢emp表的同時,把每個員工的所在部門資訊顯示出來,那麼就需要使用主外來鍵來去除無用資訊了。
Sql語句:SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno ;
查詢結果:
上面查詢結果會把兩張表的所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。
Sql語句:
SELECT emp.ename,emp.sal,emp.comm,dept.dname
FROM emp,dept
WHERE emp.deptno=dept.deptno;
查詢結果:
給表指定別名的寫法:
SELECT e.ename,e.sal,e.comm,d.dname
FROM emp AS e,dept AS d
WHERE e.deptno=d.deptno;
9.1 內連線
上面的連線語句就是內連線,但它不是SQL標準中的查詢方式,可以理解為方言!SQL標準的內連線為:
SELECT * FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;
注意:inner可以省略、on是連線條件
內連線的特點:查詢結果必須滿足條件。
9.2 外連線(左連線、右連線)
外連線的特點:查詢出的結果存在不滿足條件的可能。
- 左連線:
SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno=d.deptno;
注意:OUTER可以省略
左連線是先查詢出左表(即以左表為主),然後查詢右表,右表中滿足條件的顯示出來,不滿足條件的顯示NULL。
- 右連線
右連線就是先把右表中所有記錄都查詢出來,然後左表滿足條件的顯示,不滿足顯示NULL。例如在dept表中的40部門並不存在員工,但在右連線中,如果dept表為右表,那麼還是會查出40部門,但相應的員工資訊為NULL。
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno=d.deptno;
9.3 自然連線(不常用)
大家也都知道,連線查詢會產生無用笛卡爾積,我們通常使用主外來鍵關係等式來去除它。而自然連線無需你去給出主外來鍵等式,它會自動找到這一等式:
l 兩張連線的表中名稱和型別完成一致的列作為條件,例如emp和dept表都存在deptno列,並且型別一致,所以會被自然連線找到!
當然自然連線還有其他的查詢條件的方式,但其他方式都可能存在問題!
SELECT * FROM emp NATURAL JOIN dept;
SELECT * FROM emp NATURAL LEFT JOIN dept;
SELECT * FROM emp NATURAL RIGHT JOIN dept;
內連線案例
①簡單的兩表連線 案例:查詢員工名和部門名 ②新增篩選條件 案例1:查詢部門編號>100的部門名和所在的城市名 案例2:查詢有獎金的員工名、部門名 案例3:查詢城市名中第二個字元為o的部門名和城市名 ③新增分組+篩選 案例1:查詢每個城市的部門個數 案例2:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資 案例3:查詢部門中員工個數>10的部門名 ④新增分組+篩選+排序 案例1:查詢部門中員工個數>10的部門名,並按部門名降序 案例2:查詢每個工種的員工個數和工種名,並按個數降序 ⑤三表連線 案例:查詢員工名、部門名、城市名
|
外連線案例
#案例1 :查詢哪個部門沒有員工 #案例2:查詢城市名包含a字元的哪個城市沒有部門,並按城市名降序 |
10.子查詢
概念:
出現在其他語句的內部的select語句,稱為子查詢或內查詢
裡面巢狀其他select語句的查詢語句,稱為主查詢或外查詢
子查詢不一定必須出現在select語句內部,只是出現在select語句內部的時候較多!
示例:
select first_name from employees where department_id >(
select department_id from departments
where location_id=1700
)
分類:
單行子查詢
特點:子查詢的結果集只有一行一列
多行子查詢
特點:子查詢的結果集有多行一列
說明:
1、子查詢語句需要放在小括號內,提高程式碼的閱讀性
2、子查詢先於主查詢執行,一般來講,主查詢會用到子查詢的結果
3、如果子查詢放在條件中,一般來講,子查詢需要放在條件的右側
示例:where job_id>(子查詢)
不能寫成:where (子查詢)<job_id
4、單行子查詢對應的使用單行操作符:> < >= <= = <>
多行子查詢對應的使用多行操作符:in 、any 、all 、not in
LIMIT用來限定查詢結果的起始行,以及總行數。
案例:
#案例1:誰的工資比 Abel 高? #案例2:返回job_id與141號員工相同,salary比143號員工多的員工姓名,job_id 和工資 #案例3:返回公司工資最少的員工的last_name,job_id和salary #案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資 #多行子查詢 #題目:返回location_id是1400或1700的部門中的所有員工姓名 題目:返回其它部門中比job_id為‘IT_PROG’部門任一工資低的員工的員工號、姓名、job_id 以及salary 題目:返回其它部門中比job_id為‘IT_PROG’部門所有工資都低的員工 的員工號、姓名、job_id 以及salary |
11.分頁查詢
語法:
select 查詢列表
from 表
【where 條件】
limit 【起始條目索引,】查詢的條目數;
案例:
#案例1:查詢前五條員工資訊 #案例2:查詢第11條——第20條的員工資訊 #案例3:查詢有獎金的工資最高的前三名員工名、工資、獎金、部門編號 |
l
12.SQL的執行順序
手寫的順序:
真正執行的順序:
隨著Mysql版本的更新換代,其優化器也在不斷的升級,優化器會分析不同執行順序產生的效能消耗不同而動態調整執行順序。下面是經常出現的查詢順序:
4.4 DDL
1.基本操作
l 檢視所有資料庫名稱:SHOW DATABASES;
l 切換資料庫:USE mydb1,切換到mydb1資料庫;
2.操作資料庫
l 建立資料庫:CREATE DATABASE [IF NOT EXISTS] mydb1;
建立資料庫,例如:CREATE DATABASE mydb1,建立一個名為mydb1的資料庫。如果這個資料已經存在,那麼會報錯。例如CREATE DATABASE IF NOT EXISTS mydb1,在名為mydb1的資料庫不存在時建立該庫,這樣可以避免報錯。
l 刪除資料庫:DROP DATABASE [IF EXISTS] mydb1;
刪除資料庫,例如:DROP DATABASE mydb1,刪除名為mydb1的資料庫。如果這個資料庫不存在,那麼會報錯。DROP DATABASE IF EXISTS mydb1,就算mydb1不存在,也不會的報錯。
3.資料型別
MySQL與Java一樣,也有資料型別。MySQL中資料型別主要應用在列上。
常用型別:
l int:整型
l double/float:浮點型,例如double(5,2)表示最多5位,其中必須有2位小數,即最大值為999.99;
l decimal:浮點型,在表示錢方面使用該型別,因為不會出現精度缺失問題;
l char:固定長度字串型別;char(4) 範圍是0-255
l varchar:可變長度字串型別;
l text:字串型別;表示儲存較長文字
|
意思 |
格式 |
n的解釋 |
特點 |
效率 |
Char |
固定長度字元 |
Char(n) |
最大的字元個數,可選 預設:1 |
不管實際儲存,開闢的空間都是n個字元 |
高 |
Varchar |
可變長度字元 |
Varchar(n) |
最大的字元個數,必選 |
根據實際儲存決定開闢的空間 |
低 |
l blob:位元組型別;//jpg mp3 avi
l date:日期型別,格式為:yyyy-MM-dd;
l time:時間型別,格式為:hh:mm:ss
l timestamp/datetime:時間戳型別;日期+時間 yyyyMMdd hhmmss
儲存範圍 |
所佔位元組 |
|
Datetime |
1900-1-1~xxxx年 |
8 |
Timestamp |
1970-1-1~2038-12-31 |
4 |
詳見 《MySQL之資料型別.doc》
4.操作表
l 建立表:
CREATE TABLE 表名(
欄位名 欄位型別 【欄位約束】,
欄位名 欄位型別 【欄位約束】,
......
);
例如:
CREATE TABLE stus( sid CHAR(6), sname VARCHAR(20), age INT, gender VARCHAR(10) ); |
再例如:
CREATE TABLE emps( eid CHAR(6), ename VARCHAR(50), age INT, gender VARCHAR(6), birthday DATE, hiredate DATE, salary DECIMAL(7,2), resume VARCHAR(1000) ); |
l 檢視當前資料庫中所有表名稱:SHOW TABLES;
l 檢視指定表的建立語句:SHOW CREATE TABLE emps;
l 查看錶結構:DESC emps;
l 刪除表:DROP TABLE emps
l 修改表結構:
a) 修改之新增列:給stus表新增classname列:
ALTER TABLE stu ADD (classname varchar(100));
b) 修改之修改列型別:修改stu表的gender列型別為CHAR(2):
ALTER TABLE stus MODIFY gender CHAR(2);
c) 修改之修改列名:修改stu表的gender列名為sex:
ALTER TABLE stus change gender sex CHAR(2);
d) 修改之刪除列:刪除stsu表的classname列:
ALTER TABLE stus DROP classname;
e) 修改之修改表名稱:修改stu表名稱為student:
ALTER TABLE stus RENAME TO student;
4.5 DML
1.插入資料
語法:
INSERT INTO 表名(列名1,列名2, …) VALUES(值1, 值2)
INSERT INTO stus(sid, sname,age,gender) VALUES('s_1001', 'zhangSan', 23, 'male'); |
INSERT INTO stus(sid, sname) VALUES('s_1001', 'zhangSan'); |
語法:
INSERT INTO 表名 VALUES(值1,值2,…)
因為沒有指定要插入的列,表示按建立表時列的順序插入所有列的值:
INSERT INTO stus VALUES('s_1002', 'liSi', 32, 'female'); |
注意:所有字串資料必須使用單引號
2.修改資料
單表修改語法:
UPDATE 表名 SET 列名1=值1, … 列名n=值n [WHERE 條件]
UPDATE stus SET sname=’zhangSanSan’, age=’32’, gender=’female’ WHERE sid=’s_1001’; |
UPDATE stus SET sname=’liSi’, age=’20’ WHERE age>50 AND gender=’male’; |
UPDATE stus SET sname=’wangWu’, age=’30’ WHERE age>60 OR gender=’female’; |
UPDATE stus SET gender=’female’ WHERE gender IS NULL UPDATE stus SET age=age+1 WHERE sname=’zhaoLiu’; |
多表修改語法:
UPDATE 表1 【inner】 john 表2 on 表 SET 列名1= 新值1,列名2 =新值2
【where 篩選條件】
3.刪除資料
單表刪除語法:
①DELETE FROM 表名 [WHERE 條件]
DELETE FROM stus WHERE sid=’s_1001’003B |
DELETE FROM stus WHERE sname=’chenQi’ OR age > 30; |
DELETE FROM stus; |
②語法:
TRUNCATE TABLE 表名
TRUNCATE TABLE stus; |
l 雖然TRUNCATE和DELETE都可以刪除表的所有記錄,但有原理不同。DELETE的效率沒有TRUNCATE高!
l TRUNCATE其實屬性DDL語句,因為它是先DROP TABLE,再CREATE TABLE。而且TRUNCATE刪除的記錄是無法回滾的,但DELETE刪除的記錄是可以回滾的.
【面試題】二者的區別:
多表刪除語法:
DELETE FROM 表1 別名1 INNER JOIN 表2 別名2 on 連線條件 【AND 篩選條件】
第5章完整性約束
完整性約束是為了表的資料的正確性!如果資料不正確,那麼一開始就不能新增到表中。
5.1主鍵
當某一列添加了主鍵約束後,那麼這一列的資料就不能重複出現。這樣每行記錄中其主鍵列的值就是這一行的唯一標識。例如學生的學號可以用來做唯一標識,而學生的姓名是不能做唯一標識的,因為學習有可能同名。
主鍵列的值不能為NULL,也不能重複!
指定主鍵約束使用PRIMARY KEY關鍵字
l 建立表:定義列時指定主鍵:
CREATE TABLE stu(
sid CHAR(6) PRIMARY KEY,
sname VARCHAR(20),
age INT,
gender VARCHAR(10)
);
l 建立表:定義列之後獨立指定主鍵:
CREATE TABLE stu(
sid CHAR(6),
sname VARCHAR(20),
age INT,
gender VARCHAR(10),
PRIMARY KEY(sid)
);
l 修改表時指定主鍵:
ALTER TABLE stu ADD PRIMARY KEY(sid);
l 刪除主鍵(只是刪除主鍵約束,而不會刪除主鍵列):
ALTER TABLE stu DROP PRIMARY KEY;
5.2主鍵自增長
MySQL提供了主鍵自動增長的功能!這樣使用者就不用再為是否有主鍵是否重複而煩惱了。當主鍵設定為自動增長後,在沒有給出主鍵值時,主鍵的值會自動生成,而且是最大主鍵值+1,也就不會出現重複主鍵的可能了。
l 建立表時設定主鍵自增長(主鍵必須是整型才可以自增長):
CREATE TABLE stu(
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(20),
age INT,
gender VARCHAR(10)
);
l 修改表時設定主鍵自增長:
ALTER TABLE stu CHANGE sid sid INT AUTO_INCREMENT;
l 修改表時刪除主鍵自增長:
ALTER TABLE stu CHANGE sid sid INT;
5.3非空
指定非空約束的列不能沒有值,也就是說在插入記錄時,對添加了非空約束的列一定要給值;在修改記錄時,不能把非空列的值設定為NULL。
l 指定非空約束:
CREATE TABLE stu(
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(10) NOT NULL,
age INT,
gender VARCHAR(10)
);
當為sname欄位指定為非空後,在向stu表中插入記錄時,必須給sname欄位指定值,否則會報錯:
INSERT INTO stu(sid) VALUES(1);
插入的記錄中sname沒有指定值,所以會報錯!
5.4唯一
還可以為欄位指定唯一約束!當為欄位指定唯一約束後,那麼欄位的值必須是唯一的。這一點與主鍵相似!例如給stu表的sname欄位指定唯一約束:
CREATE TABLE tab_ab(
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(10) UNIQUE
);
INSERT INTO sname(sid, sname) VALUES(1001, 'zs');
INSERT INTO sname(sid, sname) VALUES(1002, 'zs');
當兩次插入相同的名字時,MySQL會報錯!
5.5外來鍵
主外來鍵是構成表與表關聯的唯一途徑!
外來鍵是另一張表的主鍵!例如員工表與部門表之間就存在關聯關係,其中員工表中的部門編號欄位就是外來鍵,是相對部門表的外來鍵。
l 建立dept表,指定deptno為主鍵列:
CREATE TABLE dept(
deptno INT PRIMARY KEY,
dname varchar(14),
loc varchar(13)
);
l 建立t_section表,指定sid為主鍵列,u_id為相對t_user表的uid列的外來鍵:
CREATE TABLE emp(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT,
CONSTRAINT fk_e_d FOREIGN KEY(deptno) REFERENCES dept(deptno)
)
5.6表與表之間的關係
l 一對一:例如t_person表和t_card表,即人和身份證。這種情況需要找出主從關係,即誰是主表,誰是從表。人可以沒有身份證,但身份證必須要有人才行,所以人是主表,而身份證是從表。設計從表可以有兩種方案:
- 在t_card表中新增外來鍵列(相對t_user表),並且給外來鍵新增唯一約束;
- 給t_card表的主鍵新增外來鍵約束(相對t_user表),即t_card表的主鍵也是外來鍵。
l 一對多(多對一):最為常見的就是一對多!一對多和多對一,這是從哪個角度去看得出來的。t_user和t_section的關係,從t_user來看就是一對多,而從t_section的角度來看就是多對一!這種情況都是在多方建立外來鍵!
l 多對多:例如t_stu和t_teacher表,即一個學生可以有多個老師,而一個老師也可以有多個學生。這種情況通常需要建立中間表來處理多對多關係。例如再建立一張表t_stu_tea表,給出兩個外來鍵,一個相對t_stu表的外來鍵,另一個相對t_teacher表的外來鍵。
第6章 事務
事務屬於TCL控制語言(Transaction Control Language)。
6.1事務概述
什麼是事務?為什麼要用事務?
一個事務是由一條或者多條sql語句構成,這一條或者多條sql語句要麼全部執行成功,要麼全部執行失敗!
預設情況下,每條單獨的sql語句就是一個單獨的事務!
舉例:
銀行轉賬!張三轉10000塊到李四的賬戶,這其實需要兩條SQL語句:
l 給張三的賬戶減去10000元;
l 給李四的賬戶加上10000元。
如果在第一條SQL語句執行成功後,在執行第二條SQL語句之前,程式被中斷了(可能是丟擲了某個異常,也可能是其他什麼原因),那麼李四的賬戶沒有加上10000元,而張三卻減去了10000元。這肯定是不行的!
你現在可能已經知道什麼是事務了吧!事務中的多個操作,要麼完全成功,要麼完全失敗!不可能存在成功一半的情況!也就是說給張三的賬戶減去10000元如果成功了,那麼給李四的賬戶加上10000元的操作也必須是成功的;否則給張三減去10000元,以及給李四加上10000元都是失敗的!
6.2事務的四大特性(ACID)
l 原子性(Atomicity):事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗。
l 一致性(Consistency):事務執行後,資料庫狀態與其它業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的。
l 隔離性(Isolation):隔離性是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾。
l 永續性(Durability):一旦事務提交成功,事務中所有的資料操作都必須被持久化到資料庫中,即使提交事務後,資料庫馬上崩潰,在資料庫重啟時,也必須能保證通過某種機制恢復資料。
6.3 MySql中的事務
在預設情況下,MySQL每執行一條SQL語句,都是一個單獨的事務。如果需要在一個事務中包含多條SQL語句,那麼需要開啟事務和結束事務。
l 開啟事務:start transaction;
l 結束事務:commit或rollback。
在執行SQL語句之前,先執行strat transaction,這就開啟了一個事務(事務的起點),然後可以去執行多條SQL語句,最後要結束事務,commit表示提交,即事務中的多條SQL語句所做出的影響會持久化到資料庫中。或者rollback,表示回滾,即回滾到事務的起點,之前做的所有操作都被撤消了!
演示事務
建立事務要用到的表
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
balance NUMERIC(10.2)
);
INSERT INTO account(NAME,balance) VALUES('fanbingbing', 100000);
INSERT INTO account(NAME,balance) VALUES('lichen', 100000);
SELECT * FROM account;
- 演示事務執行失敗
案例一:回滾 事務執行失敗!
START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
UPDATE account SET balance=balance+10000 WHERE id=2;
ROLLBACK;
案例二:退出mysql客戶端 事務執行失敗!
START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
UPDATE account SET balance=balance+10000 WHERE id=2;
- 演示事務執行成功
START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
UPDATE account SET balance=balance+10000 WHERE id=2;
COMMIT;
其本意是,在阿里巴巴的IT架構中,去掉IBM的小型機、Oracle資料庫、EMC儲存裝置,代之以自己在開源軟體基礎上開發的系統。傳統上,一個高階大氣的資料中心,IBM小型機、Oracle資料庫、EMC儲存裝置,可以說缺一不可。