MySQL資料庫入門筆記
一、資料庫概述
1.資料庫簡介
資料庫(DataBase,DB):指長期儲存在計算機的儲存裝置上,按照一定規則組織起來,可以被各種使用者或應用共享的資料集合。
資料庫管理系統(DataBase Management System,DBMS):指一種操作和管理資料庫的大型軟體,用於建立、使用和維護資料庫,對資料庫進行統一管理和控制,以保證資料庫的安全性和完整性。使用者通過資料庫管理系統訪問資料庫中的資料。
注意:通常情況下,經常會用資料庫來表示他們使用的資料庫軟體,這經常會引起混淆,確切的說,資料庫軟體應該為資料庫管理系統,資料庫是通過資料庫管理系統建立和操作的。
2.常見資料庫管理系統
1)Oracle:
2)DB2:IBM的產品。
3)SQL Server:Microsoft的產品。軟體介面友好、易學易用,在操作性和互動性方面獨樹一幟。
4)PostgreSQL:加州大學伯克利分校以教學目的開發的資料庫系統,支援關係和麵向物件的資料庫,屬於自由資料庫管理系統。
5)MySQL:免費的資料庫系統。被廣泛用於中小型應用系統。體積小、速度快、總體擁有成本低,開放原始碼。2008年被SUN收購,2009年SUN被Oracle收購。
3.資料庫的安裝和解除安裝
解除安裝:
停止MySQL
net stop mysql
1新增刪除程式中解除安裝MySQL
2到安裝目錄刪除MySQL
3刪除:C:\Documents and Settings\All Users\Application Data\MySQL
C:\ProgramData\MySQL
4檢視登錄檔:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services
搜尋mysql,找到一律幹掉!
============================
安裝:
4.資料庫服務的啟動和關閉
啟動資料庫服務:net start mysql
關閉資料庫服務:net stop mysql
5.資料庫的連線
登入MySQL:mysql -uroot -proot
退出MySQL:exit | quit
檢視資料庫:
show databases;
6.命令指令碼操作
使用DOS視窗進行登入:
遠端連線
一般在公司開發中,可能會將資料庫統一搭建在一臺伺服器上,所有開發人員共用一個數據庫,而不是在自己的電腦中配置一個數據庫
執行命令:
mysql -hip地址 -uroot -p
-h後面寫要連線的主機ip地址
-u後面寫連線的使用者名稱
-p回車後寫密碼
資料庫操作:
建立資料庫:
create database 資料庫名 charset=utf8;
刪除資料庫:
drop database 資料庫名;
切換資料庫:
use 資料庫名;
檢視當前選擇的資料庫:
select database();
表操作:
檢視當前資料庫中所有表:
show tables;
建立表:
auto_increment表示自動增長
create table 表名(列及型別);
如:
create table students(
id int auto_increment primary key,
sname varchar(10) not null
);
修改表:
alter table 表名 add|change|drop 列名 型別;
如:
alter table students add birthday datetime;
刪除表:
drop table 表名;
查看錶結構:
desc 表名;
更改表名稱:
rename table 原表名 to 新表名;
查看錶的建立語句:
show create table '表名';
資料操作:
查詢:
select * from 表名;
增加:
全列插入:
insert into 表名 values(...);
預設插入:
insert into 表名(列1,...) values(值1,...);
同時插入多條資料:
insert into 表名 values(...),(...)...;
或
insert into 表名(列1,...) values(值1,...),(值1,...)...;
主鍵:
主鍵列是自動增長,但是在全列插入時需要佔位,通常使用0,插入成功後以實際資料為準。
修改:
update 表名 set 列1=值1,... where 條件
刪除:
delete from 表名 where 條件
邏輯刪除,本質就是修改操作update
alter table students add isdelete bit default 0;
如果需要刪除則:
update students isdelete=1 where ...;
備份與恢復:
資料備份:
進入DOS管理員介面
進入mysql庫目錄(配置環境變量了就需要)
cd /mysql
執行mysqldump命令:
mysqldump –uroot –p 資料庫名 > ~/Desktop/備份檔案.sql;
按提示輸入mysql的密碼
資料恢復:
連線mysql,建立資料庫
退出連線,執行如下命令:
mysql -uroot –p 資料庫名 < ~/Desktop/備份檔案.sql
根據提示輸入mysql密碼
7.圖形視窗操作
使用SQLyog或者navicat
8.資料庫伺服器、資料庫和表的關係
所謂安裝資料庫伺服器,只是在機器上裝了一個數據庫管理程式,這個管理程式可以管理多個數據庫,一般開發人員會針對每一個應用建立一個數據庫。
為儲存應用中實體的資料,一般會在資料庫建立多個表,以儲存程式中實體的資料。
資料庫伺服器、資料庫和表的關係如圖所示:
9.資料在資料庫中的儲存方式
二、SQL概述
1.什麼是SQL?
SQL:Structure Query Language。
SQL被美國國家標準局(ANSI)確定為關係型資料庫語言的美國標準,後來被國際化標準組織(ISO)採納為關係資料庫語言的國際標準。
SQL優點:
- 不是某個特定資料庫供應商專有的語言。幾乎所有重要的資料庫管理系統都支援SQL。
- 簡單易學,該語言的語句都是由描述性很強的英語單片語成,且這些單詞的數目不多。
- 高度非過程化,即用SQL操作資料庫,只需指出“做什麼”,無須指明“怎麼做”,存取路徑的選擇和操作的執行由DBMS自動完成。
2.SQL的分類
它所支援的SQL提供以下功能:
- DDL(Data Definition Language):資料定義語言,用來定義資料庫物件:庫、表、列等;
- DML(Data Manipulation Language):資料操作語言,用來操作資料庫表中的記錄(資料);
- DQL(Data Query Language):資料查詢語言,用來查詢記錄(資料)。
- DCL(Data Control Language):資料控制語言,用來定義訪問許可權和安全級別;
三、建立資料庫和資料表
DDL:Data Definition Language
作用:用於描述資料庫中要儲存的現實世界實體的語言。即建立資料庫和表的結構。
常用關鍵字:
CREATE ALTER DROP
建立資料庫:
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification [, create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name //指定字符集
| [DEFAULT] COLLATE collation_name //指定資料庫字符集的比較方式
檢視、刪除資料庫:
顯示資料庫語句:
SHOW DATABASES;
顯示資料庫建立語句:
SHOW CREATE DATABASE db_name;
資料庫刪除語句:
DROP DATABASE [IF EXISTS] db_name;
修改、備份、恢復資料庫:
ALTER DATABASE [IF NOT EXISTS] db_name
[alter_specification [, alter_specification] ...]
alter_specification: [DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name
建立資料表:
注意:建立表前,要先使用use db語句使用庫。
CREATE TABLE table_name (
field1 datatype,
field2 datatype,
field3 datatype
)character set 字符集 collate 校對規則;
field:指定列名 datatype:指定列型別
注意:建立表時,要根據需儲存的資料建立相應的列,並根據資料的型別定義相應的列型別。例:user物件
id int
name string
password string
birthday date
MySQL常用資料型別:
分類 |
資料型別 |
說明 |
數值型別 |
BIT(M) TINYINT [UNSIGNED] [ZEROFILL] BOOL,BOOLEAN SMALLINT [UNSIGNED] [ZEROFILL] INT [UNSIGNED] [ZEROFILL] BIGINT [UNSIGNED] [ZEROFILL] FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] |
位型別。M指定位數,預設值1,範圍1-64 帶符號的範圍是-128到127。無符號0到255。 使用0或1表示真或假 2的16次方 2的32次方 2的64次方 M指定顯示長度,d指定小數位數 表示比float精度更大的小數 |
文字、二進位制型別 |
CHAR(size) char(20) VARCHAR(size) varchar(20) BLOB LONGBLOB TEXT(clob) LONGTEXT(longclob) |
固定長度字串 可變長度字串 二進位制資料 大文字 |
時間日期 |
DATE/DATETIME/TimeStamp |
日期型別(YYYY-MM-DD) (YYYY-MM-DD HH:MM:SS),TimeStamp表示時間戳,它可用於自動記錄insert、update操作的時間 |
VARCHAR、BLOB和TEXT類是變長型別。每個型別的儲存需求取決於列值的實際長度。
CLOB(Character Large Object)
用於儲存大量的文字資料
大欄位有些特殊,不同資料庫處理的方式不一樣,大欄位的操作常常是以流的方式來處理的。而非一般的欄位,一次即可讀出資料。
pst.setClob(2, new FileReader("d:\a.txt"););
pst.setClob(2, new BufferedReader(new InputStreamReader(new ByteArrayInputStream("".getBytes()))));
TEXT:
- TINYTEXT:最大長度255(28-1)字元的TEXT列
- TEXT:最大長度65535(216-1)字元的TEXT列
- MEDIUMTEXT:最大長度16,777,215(224-1)字元的TEXT列
- LONGTEXT:最大長度4,294,967,295或4G(232-1)字元的TEXT列
BLOB(Binary Large Object)
用於儲存大量的二進位制資料
大欄位有些特殊,不同資料庫處理的方式不一樣,大欄位的操作常常是以流的方式來處理的。而非一般的欄位,一次即可讀出資料。
pst.setClob(2, new FileInputStream("d:\a.txt"));
BLOB:
- TINYBLOB:最大長度255(28-1)位元組的BLOB列
- BLOB[(M)]:最大長度65535(216-1)位元組的BLOB列
- MEDIUMBLOB:最大長度16,777,215(224-1)位元組的BLOB列
- LONGBLOB:最大長度4,294,967,295或4G(232-1)位元組的BLOB列
修改表:
使用ALTER TABLE 語句追加, 修改, 或刪除列的語法.
ALTER TABLE table_name
ADD (column datatype [DEFAULT expr]
[, column datatype]...);
ALTER TABLE table_name
MODIFY column datatype [DEFAULT expr]
[, column datatype]...;
ALTER TABLE table_name
DROP (column);
修改表的名稱:
Rename table 表名 to 新表名;
修改表的字符集:
alter table student character set utf8;
四、資料操作
DML:Data Manipulation Language
作用:用於向資料庫表中插入、刪除、修改資料。
常用關鍵字:
INSERT UPDATE DELETE
1.insert插入語句
使用INSERT 語句向表中插入資料。
INSERT INTO table [(column [, column...])] VALUES (value [, value...]);
- 插入的資料應與欄位的資料型別相同。
- 資料的大小應在列的規定範圍內,例如:不能將一個長度為80的字串加入到長度為40的列中。
- 在values中列出的資料位置必須與被加入的列的排列位置相對應。
- 字元和日期型資料應包含在單引號中。
- 插入空值,不指定或insert into table value(null)
mysql中文亂碼:
mysql有六處使用了字符集,分別為:client 、connection、database、results、server 、system。
- client是客戶端使用的字符集。
- connection是連線資料庫的字符集設定型別,如果程式沒有指明連線資料庫使用的字符集型別就按照伺服器端預設的字符集設定。
- database是資料庫伺服器中某個庫使用的字符集設定,如果建庫時沒有指明,將使用伺服器安裝時指定的字符集設定。
- results是資料庫給客戶端返回時使用的字符集設定,如果沒有指明,使用伺服器預設的字符集。
- server是伺服器安裝時指定的預設字符集設定。
- system是資料庫系統使用的字符集設定。
2.update修改語句
使用update語句修改表中資料。
UPDATE tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition];
- UPDATE語法可以用新值更新原有錶行中的各列。
- SET子句指示要修改哪些列和要給予哪些值。
- WHERE子句指定應更新哪些行。如沒有WHERE子句,則更新所有的行。
3.delete刪除語句
使用delete語句刪除表中資料。
delete from name [WHERE where_definition];
- 如果不使用where子句,將刪除表中所有資料。
- Delete語句不能刪除某一列的值(可使用update)
- 使用delete語句僅刪除記錄,不刪除表本身。如要刪除表,使用drop table語句。
- 同insert和update一樣,從一個表中刪除記錄將引起其它表的參照完整性問題,在修改資料庫資料時,頭腦中應該始終不要忘記這個潛在的問題。
- 刪除表中資料也可使用TRUNCATE TABLE 語句,它和delete有所不同,參看mysql文件。
delete和truncate的區別:
- delete刪除表中的資料,表結構還在;刪除後的資料可以找回
- truncate刪除是把表直接drop掉,然後再建立一個同樣的新表。刪除的資料不能找回。執行速度比delete快。
五、資料型別
常用資料型別:
- int:整型
- double:浮點型,例如double(5,2)表示最多5位,其中必須有2位小數,即最大值為999.99;
- char:固定長度字串型別; char(10) 'abc '
- varchar:可變長度字串型別;varchar(10) 'abc'
- text:字串型別;
- blob:位元組型別;
- date:日期型別,格式為:yyyy-MM-dd;
- time:時間型別,格式為:hh:mm:ss
- timestamp:時間戳型別 yyyy-MM-dd hh:mm:ss 會自動賦值
- datetime:日期時間型別 yyyy-MM-dd hh:mm:ss
六、查詢
DQL資料查詢語言 (重要)
資料庫執行DQL語句不會對資料進行改變,而是讓資料庫傳送結果集給客戶端。
查詢返回的結果集是一張虛擬表。
查詢關鍵字:SELECT
語法:
SELECT 列名 FROM表名
【WHERE --> GROUP BY -->HAVING--> ORDER BY】;
語法:
SELECT selection_list /*要查詢的列名稱*/
FROM table_list /*要查詢的表名稱*/
WHERE condition /*行條件*/
GROUP BY grouping_columns /*對結果分組*/
HAVING condition /*分組後的行條件*/
ORDER BY sorting_columns /*對結果分組*/
LIMIT offset_start, row_count /*結果限定*/
1.基礎查詢
1.1 查詢所有列
SELECT * FROM stu;
1.2 查詢指定列
SELECT sid, sname, age FROM stu;
2.條件查詢
2.1 條件查詢介紹
條件查詢就是在查詢時給出WHERE子句,在WHERE子句中可以使用如下運算子及關鍵字:
- =、!=、<>、<、<=、>、>=;
- BETWEEN…AND;
- IN(set);
- IS NULL; IS NOT NULL
- AND;
- OR;
- NOT;
2.2 查詢性別為女,並且年齡50的記錄
SELECT * FROM stu WHERE gender='female' AND ge<50;
2.3 查詢學號為S_1001,或者姓名為liSi的記錄
SELECT * FROM stu WHERE sid ='S_1001' OR sname='liSi';
2.4 查詢學號為S_1001,S_1002,S_1003的記錄
SELECT * FROM stu WHERE sid IN ('S_1001','S_1002','S_1003');
2.5 查詢學號不是S_1001,S_1002,S_1003的記錄
SELECT * FROM tab_student WHERE s_number NOT IN ('S_1001','S_1002','S_1003');
2.6 查詢年齡為null的記錄
SELECT * FROM stu WHERE age IS NULL;
2.7 查詢年齡在20到40之間的學生記錄
SELECT * FROM stu WHERE age>=20 AND age<=40;
或者
SELECT * FROM stu WHERE age BETWEEN 20 AND 40;
2.8 查詢性別非男的學生記錄
SELECT * FROM stu WHERE gender!='male';
或者
SELECT * FROM stu WHERE gender<>'male';
或者
SELECT * FROM stu WHERE NOT gender='male';
2.9 查詢姓名不為null的學生記錄
SELECT * FROM stu WHERE sname IS NOT NULL;
或者
SELECT * FROM stu WHERE NOT sname IS NULL;
3.模糊查詢
當想查詢姓名中包含a字母的學生時就需要使用模糊查詢了。模糊查詢需要使用關鍵字LIKE。
萬用字元:
- _ 任意一個字元
- %:任意0~n個字元
3.1 查詢姓名由5個字母構成的學生記錄
SELECT * FROM stu WHERE sname LIKE '_____';
模糊查詢必須使用LIKE關鍵字。其中 “_”匹配任意一個字母,5個“_”表示5個任意字母。
3.2 查詢姓名由5個字母構成,並且第5個字母為“i”的學生記錄
SELECT * FROM stu WHERE sname LIKE '____i';
3.3 查詢姓名以“z”開頭的學生記錄
SELECT * FROM stu WHERE sname LIKE 'z%';
其中“%”匹配0~n個任何字母。
3.4 查詢姓名中第2個字母為“i”的學生記錄
SELECT * FROM stu WHERE sname LIKE '_i%';
3.5 查詢姓名中包含“a”字母的學生記錄
SELECT * FROM stu WHERE sname LIKE '%a%';
4.欄位控制查詢
4.1 去除重複記錄
去除重複記錄(兩行或兩行以上記錄中系列的上的資料都相同),例如emp表中sal欄位就存在相同的記錄。當只查詢emp表的sal欄位時,那麼會出現重複記錄,那麼想去除重複記錄,需要使用DISTINCT:
SELECT DISTINCT sal FROM emp;
4.2 檢視僱員的月薪與佣金之和
因為sal和comm兩列的型別都是數值型別,所以可以做加運算。如果sal或comm中有一個欄位不是數值型別,那麼會出錯。
SELECT *,sal+comm FROM emp;
comm列有很多記錄的值為NULL,因為任何東西與NULL相加結果還是NULL,所以結算結果可能會出現NULL。下面使用了把NULL轉換成數值0的函式IFNULL:
SELECT *,sal+IFNULL(comm,0) FROM emp;
4.3 給列名新增別名
在上面查詢中出現列名為sal+IFNULL(comm,0),這很不美觀,現在我們給這一列給出一個別名,為total:
SELECT *, sal+IFNULL(comm,0) AS total FROM emp;
給列起別名時,是可以省略AS關鍵字的:
SELECT *,sal+IFNULL(comm,0) total FROM emp;
5.排序
5.1 查詢所有學生記錄,按年齡升序排序
SELECT * FROM stu ORDER BY sage ASC;
或者
SELECT * FROM stu ORDER BY sage;
5.2 查詢所有學生記錄,按年齡降序排序
SELECT * FROM stu ORDER BY age DESC;
5.3 查詢所有僱員,按月薪降序排序,如果月薪相同時,按編號升序排序
SELECT * FROM emp ORDER BY sal DESC,empno ASC;
6.聚合函式
聚合函式是用來做縱向運算的函式:
- COUNT():統計指定列不為NULL的記錄行數;
- MAX():計算指定列的最大值,如果指定列是字串型別,那麼使用字串排序運算;
- MIN():計算指定列的最小值,如果指定列是字串型別,那麼使用字串排序運算;
- SUM():計算指定列的數值和,如果指定列型別不是數值型別,那麼計算結果為0;
- AVG():計算指定列的平均值,如果指定列型別不是數值型別,那麼計算結果為0;
6.1 COUNT
當需要縱向統計時可以使用COUNT()。
- 查詢emp表中記錄數:
SELECT COUNT(*) AS cnt FROM emp;
- 查詢emp表中有佣金的人數:
SELECT COUNT(comm) cnt FROM emp;
注意,因為count()函式中給出的是comm列,那麼只統計comm列非NULL的行數。
- 查詢emp表中月薪大於2500的人數:
SELECT COUNT(*) FROM emp WHERE sal > 2500;
- 統計月薪與佣金之和大於2500元的人數:
SELECT COUNT(*) AS cnt FROM emp WHERE sal+IFNULL(comm,0) > 2500;
- 查詢有佣金的人數,有領導的人數:
SELECT COUNT(comm), COUNT(mgr) FROM emp;
6.2 SUM和AVG
當需要縱向求和時使用sum()函式。
- 查詢所有僱員月薪和:
SELECT SUM(sal) FROM emp;
- 查詢所有僱員月薪和,以及所有僱員佣金和:
SELECT SUM(sal), SUM(comm) FROM emp;
- 查詢所有僱員月薪+佣金和:
SELECT SUM(sal+IFNULL(comm,0)) FROM emp;
- 統計所有員工平均工資:
SELECT AVG(sal) FROM emp;
6.3 MAX和MIN
- 查詢最高工資和最低工資:
SELECT MAX(sal), MIN(sal) FROM emp;
7.分組查詢
當需要分組查詢時需要使用GROUP BY子句,例如查詢每個部門的工資和,這說明要使用部門來分組。
注:凡和聚合函式同時出現的列名,一定要寫在group by 之後
7.1 分組查詢
- 查詢每個部門的部門編號和每個部門的工資和:
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno;
- 查詢每個部門的部門編號以及每個部門的人數:
SELECT deptno,COUNT(*) FROM emp GROUP BY deptno;
- 查詢每個部門的部門編號以及每個部門工資大於1500的人數:
SELECT deptno,COUNT(*) FROM emp WHERE sal>1500 GROUP BY deptno;
7.2 HAVING子句
- 查詢工資總和大於9000的部門編號以及工資和:
SELECT deptno, SUM(sal) FROM emp GROUP BY deptno HAVING SUM(sal) > 9000;
注:having與where的區別:
1.having是在分組後對資料進行過濾,where是在分組前對資料進行過濾。
2.having後面可以使用聚合函式(統計函式),where後面不可以使用聚合函式。
3.WHERE是對分組前記錄的條件,如果某行記錄沒有滿足WHERE子句的條件,那麼這行記錄不會參加分組;而HAVING是對分組後資料的約束。
8.limit方言
LIMIT用來限定查詢結果的起始行,以及總行數。
8.1 查詢5行記錄,起始行從0開始
SELECT * FROM emp LIMIT 0, 5;
注意,起始行從0開始,即第一行開始!
8.2 查詢10行記錄,起始行從3開始
SELECT * FROM emp LIMIT 3, 10;
8.3 分頁查詢
如果一頁記錄為10條,希望檢視第3頁記錄應該怎麼查呢?
- 第一頁記錄起始行為0,一共查詢10行;
- 第二頁記錄起始行為10,一共查詢10行;
- 第三頁記錄起始行為20,一共查詢10行;
8.3 查詢程式碼的書寫順序和執行順序
- 查詢語句書寫順序:
select – from- where- group by- having- order by-limit
- 查詢語句執行順序:
from - where -group by - having - select - order by-limit
七、資料完整性
作用:保證使用者輸入的資料儲存到資料庫中是正確的。
確保資料的完整性 = 在建立表時給表中新增約束
完整性分類
- 實體完整性
- 域完整性
- 引用完整性
1.實體完整性
實體:即表中的一行(一條記錄)代表一個實體(entity)
實體完整性的作用:標識每一行資料不重複。
約束型別:主鍵約束(primary key) 唯一約束(unique) 自動增長列(auto_increment)
1.1主鍵約束(primary key)
特點:資料唯一,且不能為null
例:
第一種新增方式:
CREATE TABLE student(
id int primary key,
name varchar(50)
);
第一種新增方式:此種方式優勢在於,可以建立聯合主鍵
CREATE TABLE student(
id int,
name varchar(50),
primary key(id)
);
CREATE TABLE student(
id int,
name varchar(50),
primary key(id,name)
);
第三種新增方式:
CREATE TABLE student(
id int,
name varchar(50)
);
ALTER TABLE student ADD PRIMARY KEY (id);
1.2唯一約束(unique):
CREATE TABLE student(
id int primary key,
name varchar(50) unique
);
1.3自動增長列(auto_increment)
給主鍵新增自動增長的數值,列只能是整數型別,但是如果刪除之前增長的序號,後面再新增的時候序號不會重新開始,而是會接著被刪除的那一列的序號
CREATE TABLE student(
id int primary key auto_increment,
name varchar(50)
);
INSERT INTO student(name) values(‘tom’);
2.域完整性
域完整性的作用:限制此單元格的資料正確,不對照此列的其它單元格比較
域代表當前單元格
域完整性約束:資料型別 非空約束(not null) 預設值約束(default)
Check約束(mysql不支援) check();
1.1 資料型別:(數值型別、日期型別、字串型別)
1.2 非空約束:not null
CREATE TABLE student(
id int pirmary key,
name varchar(50) not null,
sex varchar(10)
);
INSERT INTO student values(1,’tom’,null);
1.3 預設值約束 default
CREATE TABLE student(
id int pirmary key,
name varchar(50) not null,
sex varchar(10) default ‘男’
);
insert into student1 values(1,'tom','女');
insert into student1 values(2,'jerry',default);
3.引用完整性
外來鍵約束:FOREIGN KEY
例:
CREATE TABLE student(
sid int pirmary key,
name varchar(50) not null,
sex varchar(10) default ‘男’
);
create table score(
id int,
score int,
sid int , -- 外來鍵列的資料型別一定要與主鍵的型別一致
CONSTRAINT fk_score_sid foreign key (sid) references student(id)
);
第二種新增外來鍵方式。
ALTER TABLE score1 ADD CONSTRAINT fk_stu_score FOREIGN KEY(sid) REFERENCES stu(id);
八、表與表之間的關係
- 一對一:例如t_person表和t_card表,即人和身份證。這種情況需要找出主從關係,即誰是主表,誰是從表。人可以沒有身份證,但身份證必須要有人才行,所以人是主表,而身份證是從表。設計從表可以有兩種方案:一對多(多對一):最為常見的就是一對多!一對多和多對一,這是從哪個角度去看得出來的。t_user和t_section的關係,從t_user來看就是一對多,而從t_section的角度來看就是多對一!這種情況都是在多方建立外來鍵!
- 在t_card表中新增外來鍵列(相對t_user表),並且給外來鍵新增唯一約束;
- 給t_card表的主鍵新增外來鍵約束(相對t_user表),即t_card表的主鍵也是外來鍵。
- 多對多:例如t_stu和t_teacher表,即一個學生可以有多個老師,而一個老師也可以有多個學生。這種情況通常需要建立中間表來處理多對多關係。例如再建立一張表t_stu_tea表,給出兩個外來鍵,一個相對t_stu表的外來鍵,另一個相對t_teacher表的外來鍵。
多表查詢有如下幾種:
- 合併結果集;UNION 、 UNION ALL
- 連線查詢子查詢
- 內連線 [INNER] JOIN ON
- 外連線 OUTER JOIN ON
- 左外連線 LEFT [OUTER] JOIN
- 右外連線 RIGHT [OUTER] JOIN
- 全外連線(MySQL不支援)FULL JOIN
- 自然連線 NATURAL JOIN
1.合併結果集
- 作用:合併結果集就是把兩個select語句的查詢結果合併到一起!
- 合併結果集有兩種方式:
- UNION:去除重複記錄,例如:
SELECT * FROM t1 UNION SELECT * FROM t2;
- UNION ALL:不去除重複記錄,例如:
SELECT * FROM t1 UNION ALL SELECT * FROM t2。
被合併的兩個結果:列數、列型別必須相同。
2.連線查詢(非常重要)
連線查詢就是求出多個表的乘積,例如t1連線t2,那麼查詢出的結果就是t1*t2。
連線查詢會產生笛卡爾積,假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴充套件到多個集合的情況。
那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。
你能想像到emp和dept表連線查詢的結果麼?emp一共14行記錄,dept表一共4行記錄,那麼連線後查詢出的結果是56行記錄。
也就你只是想在查詢emp表的同時,把每個員工的所在部門資訊顯示出來,那麼就需要使用主外來鍵來去除無用資訊了。
使用主外來鍵關係做為條件來去除無用資訊
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
上面查詢結果會把兩張表的所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。
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;
2.1 內連線
上面的連線語句就是內連線,但它不是SQL標準中的查詢方式,可以理解為方言!SQL標準的內連線為:
SELECT *
FROM emp e
INNER JOIN dept d
ON e.deptno=d.deptno;
內連線的特點:查詢結果必須滿足條件。例如我們向emp表中插入一條記錄:
其中deptno為50,而在dept表中只有10、20、30、40部門,那麼上面的查詢結果中就不會出現“張三”這條記錄,因為它不能滿足e.deptno=d.deptno這個條件。
2.2 外連線(左連線、右連線)
外連線的特點:查詢出的結果存在不滿足條件的可能。
左連線:
SELECT * FROM emp e
LEFT OUTER JOIN dept d
ON e.deptno=d.deptno;
左連線是先查詢出左表(即以左表為主),然後查詢右表,右表中滿足條件的顯示出來,不滿足條件的顯示NULL。
這麼說你可能不太明白,我們還是用上面的例子來說明。其中emp表中“張三”這條記錄中,部門編號為50,而dept表中不存在部門編號為50的記錄,所以“張三”這條記錄,不能滿足e.deptno=d.deptno這條件。但在左連線中,因為emp表是左表,所以左表中的記錄都會查詢出來,即“張三”這條記錄也會查出,但相應的右表部分顯示NULL。
2.3 右連線
右連線就是先把右表中所有記錄都查詢出來,然後左表滿足條件的顯示,不滿足顯示NULL。例如在dept表中的40部門並不存在員工,但在右連線中,如果dept表為右表,那麼還是會查出40部門,但相應的員工資訊為NULL。
SELECT * FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno=d.deptno;
連線查詢總結:
連線不限與兩張表,連線查詢也可以是三張、四張,甚至N張表的連線查詢。通常連線查詢不可能需要整個笛卡爾積,而只是需要其中一部分,那麼這時就需要使用條件來去除不需要的記錄。這個條件大多數情況下都是使用主外來鍵關係去除。
兩張表的連線查詢一定有一個主外來鍵關係,三張表的連線查詢就一定有兩個主外來鍵關係,所以在大家不是很熟悉連線查詢時,首先要學會去除無用笛卡爾積,那麼就是用主外來鍵關係作為條件來處理。如果兩張表的查詢,那麼至少有一個主外來鍵條件,三張表連線至少有兩個主外來鍵條件。
3.自然連線
大家也都知道,連線查詢會產生無用笛卡爾積,我們通常使用主外來鍵關係等式來去除它。而自然連線無需你去給出主外來鍵等式,它會自動找到這一等式:
- 兩張連線的表中名稱和型別完全一致的列作為條件,例如emp和dept表都存在deptno列,並且型別一致,所以會被自然連線找到!
當然自然連線還有其他的查詢條件的方式,但其他方式都可能存在問題!
SELECT * FROM emp NATURAL JOIN dept;
SELECT * FROM emp NATURAL LEFT JOIN dept;
SELECT * FROM emp NATURAL RIGHT JOIN dept;
4.子查詢
一個select語句中包含另一個完整的select語句。
子查詢就是巢狀查詢,即SELECT中包含SELECT,如果一條語句中存在兩個,或兩個以上SELECT,那麼就是子查詢語句了。
- 子查詢出現的位置:
- where後,作為條為被查詢的一條件的一部分;
- from後,作表;
- 當子查詢出現在where後作為條件時,還可以使用如下關鍵字:
- any
- all
- 子查詢結果集的形式:
- 單行單列(用於條件)
- 單行多列(用於條件)
- 多行單列(用於條件)
- 多行多列(用於表)
練習:
1、工資高於JONES的員工。
分析:
查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。
第一步:查詢JONES的工資
SELECT sal FROM emp WHERE ename='JONES'
第二步:查詢高於甘寧工資的員工
SELECT * FROM emp WHERE sal > (${第一步})
結果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES');
2、查詢與SCOTT同一個部門的員工。
- 子查詢作為條件
- 子查詢形式為單行單列
3、工資高於30號部門所有人的員工資訊
分析:
SELECT * FROM emp WHERE sal>(
SELECT MAX(sal) FROM emp WHERE deptno=30);
查詢條件:工資高於30部門所有人工資,其中30部門所有人工資是子查詢。高於所有需要使用all關鍵字。
第一步:查詢30部門所有人工資
SELECT sal FROM emp WHERE deptno=30;
第二步:查詢高於30部門所有人工資的員工資訊
SELECT * FROM emp WHERE sal > ALL (${第一步});
結果:
SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30);
- 子查詢作為條件
- 子查詢形式為多行單列(當子查詢結果集形式為多行單列時可以使用ALL或ANY關鍵字)
4、查詢工作和工資與MARTIN(馬丁)完全相同的員工資訊
分析:
查詢條件:工作和工資與MARTIN完全相同,這是子查詢
第一步:查詢出MARTIN的工作和工資
SELECT job,sal FROM emp WHERE ename='MARTIN';
第二步:查詢出與MARTIN工作和工資相同的人
SELECT * FROM emp WHERE (job,sal) IN (${第一步});
結果:
SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='MARTIN');
5、有2個以上直接下屬的員工資訊
SELECT * FROM emp WHERE empno IN(
SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>=2);
- 子查詢作為條件
- 子查詢形式為單行多列
6、查詢員工編號為7788的員工名稱、員工工資、部門名稱、部門地址
分析:(無需子查詢)
查詢列:員工名稱、員工工資、部門名稱、部門地址
查詢表:emp和dept,分析得出,不需要外連線(外連線的特性:某一行(或某些行)記錄上會出現一半有值,一半為NULL值)
條件:員工編號為7788
第一步:去除多表,只查一張表,這裡去除部門表,只查員工表
SELECT ename, sal FROM emp e WHERE empno=7788;
第二步:讓第一步與dept做內連線查詢,新增主外來鍵條件去除無用笛卡爾積
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, dept d
WHERE e.deptno=d.deptno AND empno=7788;
第二步中的dept表表示所有行所有列的一張完整的表,這裡可以把dept替換成所有行,但只有dname和loc列的表,這需要子查詢。
第三步:查詢dept表中dname和loc兩列,因為deptno會被作為條件,用來去除無用笛卡爾積,所以需要查詢它。
SELECT dname,loc,deptno FROM dept;
第四步:替換第二步中的dept
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, (SELECT dname,loc,deptno FROM dept) d
WHERE e.deptno=d.deptno AND e.empno=7788;
- 子查詢作為表
- 子查詢形式為多行多列
5.自連線
求7369員工編號、姓名、經理編號和經理姓名
SELECT e1.empno , e1.ename,e2.mgr,e2.ename
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno AND e1.empno = 7369;
練習:
求各個部門薪水最高的員工所有資訊
select e.* from emp e,
--部門最高工資
(select max(sal) maxsal,deptno from emp
group by deptno) a
where e.deptno = a.deptno
and e.sal =a.maxsal;
九、函式
1.字串函式
1 CHARSET(str) -- 返回字串字符集
2 CONCAT(string2 [,... ]) -- 連線字串
3 INSTR(string, substring) -- 返回substring在string中出現的位置,沒有返回0
4 UCASE(string2) -- 轉換成大寫
5 LCASE(string2) -- 轉換成小寫
6 LEFT(string2,length) -- 從string2中的左邊起取length個字元
7 LENGTH(string) -- string長度
8 REPLACE(str ,search_str ,replace_str) -- 在str中用replace_str替換search_str
9 STRCMP(string1, string2) -- 逐字元比較兩字串大小
10 SUBSTRING(str, position[, length]) -- 從str的position開始,取length個字元
11 LTRIM(string2) RTRIM(string2) trim -- 去除前端空格或後端空格
檢視字元的ascii碼值ascii(str),str是空串時返回0
select ascii('a');
檢視ascii碼值對應的字元char(數字)
select char(97);
拼接字串concat(str1,str2...)
select concat(12,34,'ab');
包含字元個數length(str)
select length('abc');
擷取字串
left(str,len)返回字串str的左端len個字元
right(str,len)返回字串str的右端len個字元
substring(str,pos,len)返回字串str的位置pos起len個字元
select substring('abc123',2,3);
去除空格
ltrim(str)返回刪除了左空格的字串str
rtrim(str)返回刪除了右空格的字串str
trim([方向 remstr from str)返回從某側刪除remstr後的字串str,方向詞包括both、leading、trailing,表示兩側、左、右
select trim(' bar ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');
返回由n個空格字元組成的一個字串space(n)
select space(10);
替換字串replace(str,from_str,to_str)
select replace('abc123','123','def');
大小寫轉換,函式如下
lower(str);
upper(str);
select lower('aBcD');
2.數學函式
ABS(number2) -- 絕對值
BIN(decimal_number) -- 十進位制轉二進位制
CEILING(number2) -- 向上取整
CONV(number2, from_base, to_base) -- 進位制轉換
FLOOR(number2) -- 向下取整
FORMAT(number,decimal_places) -- 保留小數位數
HEX(DecimalNumber) -- 轉十六進位制
LEAST(number, number2[ ,..]) -- 求最小值
MOD(numerator,denominator) -- 求餘
RAND([seed]) -- RAND([seed])
求絕對值abs(n)
select abs(-32);
求m除以n的餘數mod(m,n),同運算子%
select mod(10,3);
select 10%3;
地板floor(n),表示不大於n的最大整數
select floor(2.3);
天花板ceiling(n),表示不小於n的最大整數
select ceiling(2.3);
求四捨五入值round(n,d),n表示原數,d表示小數位置,預設為0
select round(1.6);
求x的y次冪pow(x,y)
select pow(2,3);
獲取圓周率PI()
select PI();
隨機數rand(),值為0-1.0的浮點數
select rand();
還有其它很多三角函式,使用時可以查詢文件
3.日期時間函式
ADDTIME(date2, time_interval) -- 將time_interval加到date2
CURRENT_DATE() -- 當前日期
CURRENT_TIME() -- 當前時間
CURRENT_TIMESTAMP() -- 當前時間戳
DATE(datetime) -- 返回datetime的日期部分
DATE_ADD(date2, INTERVAL d_value d_type) -- 在date2中加上日期或時間
DATE_SUB(date2, INTERVAL d_value d_type) -- 在date2上減去一個時間
DATEDIFF(date1, date2) -- 兩個日期差
NOW() -- 當前時間
YEAR|Month|DATE(datetime) -- 年月日
獲取子值,語法如下
year(date)返回date的年份(範圍在1000到9999)
month(date)返回date中的月份數值
day(date)返回date中的日期數值
hour(time)返回time的小時數(範圍是0到23)
minute(time)返回time的分鐘數(範圍是0到59)
second(time)返回time的秒數(範圍是0到59)
select year('2016-12-21');
日期計算,使用+-運算子,數字後面的關鍵字為year、month、day、hour、minute、second
select '2016-12-21'+interval 1 day;
日期格式化date_format(date,format),format引數可用的值如下
- 獲取年%Y,返回4位的整數
- 獲取年%y,返回2位的整數
- 獲取月%m,值為1-12的整數
- 獲取日%d,返回整數
- 獲取時%H,值為0-23的整數
- 獲取時%h,值為1-12的整數
- 獲取分%i,值為0-59的整數
- 獲取秒%s,值為0-59的整數
select date_format('2016-12-21','%Y %m %d');
當前日期current_date()
select current_date();
當前時間current_time()
select current_time();
當前日期時間now()
select now();
十、檢視
對於複雜的查詢,在多次使用後,維護是一件非常麻煩的事情
解決:定義檢視
檢視本質就是對查詢的一個封裝
定義檢視
create view stuscore as
select students.*,scores.score from scores
inner join students on scores.stuid=students.id;
檢視的用途就是查詢
select * from stuscore;
十一、事務
當一個業務邏輯需要多個sql完成時,如果其中某條sql語句出錯,則希望整個操作都退回
使用事務可以完成退回的功能,保證業務邏輯的正確性
事務四大特性(簡稱ACID)
- 原子性(Atomicity):事務中的全部操作在資料庫中是不可分割的,要麼全部完成,要麼均不執行
- 一致性(Consistency):幾個並行執行的事務,其執行結果必須與按某一順序序列執行的結果相一致
- 隔離性(Isolation):事務的執行不受其他事務的干擾,事務執行的中間結果對其他事務必須是透明的
- 永續性(Durability):對於任意已提交事務,系統必須保證該事務對資料庫的改變不被丟失,即使資料庫出現故障
要求:表的型別必須是innodb或bdb型別,才可以對此表使用事務
查看錶的建立語句
show create table students;
修改表的型別
alter table '表名' engine=innodb;
事務語句
- 開啟begin;
- 提交commit;
- 回滾rollback;
示例1
步驟1:開啟兩個終端,連線mysql,使用同一個資料庫,操作同一張表
【終端1】
select * from students;
【終端2】
begin;
insert into students(sname) values('張飛');
步驟2:
【終端1】
select * from students;
步驟3:
【終端2】
commit;
【終端1】
select * from students;
示例2
步驟1:開啟兩個終端,連線mysql,使用同一個資料庫,操作同一張表
【終端1】
select * from students;
【終端2】
begin;
insert into students(sname) values('張飛');
步驟2:
【終端1】
select * from students;
步驟3:
【終端2】
rollback;
【終端1】
select * from students;
有志者事竟成,破釜沉舟,百二秦關終屬楚;
苦心人天不負,臥薪嚐膽,三千越甲可吞吳。