MySQL筆記(一):基礎知識
1、GBK中一個漢字佔2個字節,一個字母佔一個字節;UTF-8中一個漢字佔3個字節,一個字母佔一個字節
在Mysql中進行驗證:
查看Mysql客戶端的編碼方式:
select variables like '%char%';
查看字符串的字節長度,length()方法獲取的是字節的長度:
select length('張三丰hello');
MySQL中字節與字符是有區別的,一個字母和一個漢字都算是一個字符,但是二者所佔的字節數是不一樣的
2、MySQL中和分組函數一同查詢出來的數據要求是group by後的數據
常見的分組函數:sum、avg、count、min、max
例如:查詢各個部門的總人數和平均工資
# SELECT中的department_id必須是GROUP BY的字段,否則會報錯
SELECT
department_id, count(*), AVG(salary)
FROM
employees
GROUP BY department_id
3、DATEDIFF()函數可以求兩個日期之間相差的天數
SELECT DATEDIFF(now(), '1995-5-20');
4、having可以對分組(group by)後的結果進行篩選
例如:查詢員工數大於2的部門
SELECT
department_id AS 部門編號,
count( * ) AS 部門總人數
FROM
employees
GROUP BY
department_id
HAVING
count( * ) > 2
having是對前面的查詢結果再進行篩選,注意:count(*) > 2不能放在where中,where中只能查詢from 表中存在的字段
分組篩選總結:
①分組篩選分爲兩大類:分組前篩選和分組後篩選
數據源 | 位置 | 關鍵字 | |
---|---|---|---|
分組前篩選 | 原始表(from表) | group by子句的前面 | where |
分組後篩選 | 分組後得到的結果集 | group by子句的後面面 | having |
②分組函數做條件肯定是放在having子句中,常見的分組函數:sum、max、min、count、avg
③能使用分組前篩選的,優先考慮使用分組前篩選,可以提高查詢效率
④group by中支持多個字段分組,並且字段之間的先後順序沒有要求
⑤Mysql中,group by和having子句中都支持別名;Oracle中,group by和having子句中都不支持別名;所以,儘量不要在group by和having子句中使用別名
5、如果爲表起了別名,則查詢的字段就不能再使用原來的表名進行限定
例如:
select student.name from student s where student.id=1(錯誤)
select s.name from student s where s.id=1(正確)
6、ifnull函數,判斷某字段或表達式是否爲null,如果爲null 返回指定的值,否則返回原本的值
例如:
select ifnull(commission_pct,0) from employees;
isnull函數,判斷某字段或表達式是否爲null,如果是,則返回1,否則返回0
7、like用於模糊查詢,不僅可以用於字符,也可以用於數字。通配符:%任意多個字符,_任意單個字符
# slary是數字類型
select
salary
from
employees
where
salary like '_2%';
8、連接查詢
①連接分爲內連接和外連接,內連接分爲等值連接、非等值連接、自連接,外連接分爲左連接(left join)、右連接(right join)、全連接(full join)
②inner join的效果與內連接中的等值連接是一樣的,並且inner關鍵字可以省略
一、內連接
特點:
①多表等值連接的查詢結果爲多表的交集部分
②n表連接至少需要n-1個連接條件
③查詢時,多表的順序沒有要求
④儘量爲表起別名
⑤可以搭配排序、分組、篩選等子句一起使用
分類:等值連接、非等值連接、自連接
下面的方式一和方式二的查詢效果完全相同
(1)等值連接
# 方式一
SELECT
last_name,
department_name
FROM
employees e,
departments d
WHERE
e.department_id = d.department_id
# 方式二
SELECT
last_name,
department_name
FROM
employees e
[INNER] JOIN
departments d
ON
e.department_id = d.department_id
(2)非等值連接
# 案例:查詢每個員工的工資級別
#方式一:
SELECT
last_name,
salary,
grade_level
FROM
employees e,
grade g
WHERE
e.salary BETWEEN g.lowest_sal AND g.highest_sal
# 方式二:
SELECT
last_name,
salary,
grade_level
FROM
employees e
[INNER] JOIN
grade g
ON
e.salary BETWEEN g.lowest_sal AND g.highest_sal
(3)自連接
# 案例:查詢員工和員工領導的信息
# 方式一:
SELECT
e.employee_id,
e.last_name,
m.employee_id,
m.last_name
FROM
employees e,
employees m
WHERE
e.manager_id = m.employee_id
# 方式二:
SELECT
e.employee_id,
e.last_name,
m.employee_id,
m.last_name
FROM
employees e
[INNER] JOIN
employees m
ON
e.manager_id = m.employee_id
二、外連接
特點:
1、外連接的查詢結果爲主表中的所有記錄
如果從表中有和它匹配的數據,則查詢匹配的值
如果從表中沒有和它匹配的數據,則顯示null
外連接查詢結果=內連接查詢結果+主表中有而從表中沒有的數據
2、左外連接,left join左邊的是主表;右外連接,right join右邊的是主表
3、左外連接和右外連接交換兩個表的順序,可以實現同樣的效果
分類:左外連接、右外連接
(1)左外連接
# 查詢員工ID、員工名、員工工資和員工所在部門的部門名
SELECT
employee_id, last_name, salary, department_name
FROM
employees e
LEFT JOIN
departments d
ON
e.department_id = d.department_id
(2)右外連接
# 查詢員工ID、員工名、員工工資和員工所在部門的部門名,與上面的左外連接的效果是一樣的
SELECT
employee_id, last_name, salary, department_name
FROM
departments d
RIGHT JOIN
employees e
ON
e.department_id = d.department_id
9、子查詢
一、按結果集的行列數分類
①標量子查詢:結果集只有一行一列
②列子查詢:結果集只有一列多行
③行子查詢:結果集一行多列
④表子查詢:結果集多行多列
二、按子查詢出現的位置分類
(1)出現在select後面
僅僅支持標量子查詢
# 查詢每個部門的員工個數, employees是員工信息表,departments是部門信息表 SELECT d.*, ( SELECT count(*) FROM employees e WHERE e.department_id = d.department_id ) count FROM departments d ORDER BY count DESC # 查詢每個專業的男生總數和女生總數(※) SELECT majorid, ( SELECT count(*) FROM student t1 where sex = '男' AND t1.majorid = t.majorid ) boynum, ( SELECT count(*) FROM student t1 where sex = '女' AND t1.majorid = t.majorid ) FROM student t GROUP BY majorid
(2)出現在from後面
支持表子查詢
# 查詢每個部門的平均工資的工資等級,以及部門id和部門名 SELECT department_id, ( SELECT department_name FROM departments d WHERE new_tab.department_id=d.department_id ) avg_salary, CASE WHEN avg_salary>20000 THEN '高等收入' WHEN avg_salary>10000 THEN '中等收入' ELSE '低等收入' END AS '收入等級' FROM ( SELECT department_id, avg(salary) avg_salary FROM employees WHERE department_id IS NOT NULL GROUP BY department_id ) new_tab
(3)出現在where或having後面
支持標量子查詢、列子查詢,也支持行子查詢
# 查詢工資最高的員工所在的部門的部門名 SELECT department_name FROM departments d WHERE d.department_id in ( SELECT department_id FROM employees e WHERE e.salary in ( SELECT max(salary) FROM employees ) ) # 查詢平均工資高於公司總平均工資的部門信息 SELECT * FROM departments WHERE department_id in ( SELECT department_id FROM employees GROUP BY department_id HAVING AVG(salary) > ( SELECT AVG(salary) FROM employees ) )
(4)出現在exists後面(相關子查詢)
支持表子查詢
語法:exists(完整的查詢語句);
結果:0或1,0表示括號中的查詢結果中沒有記錄,1表示括號中的查詢結果至少有一條記錄
exists可以用in代替
# 是否有員工的工資等於30000 SELECT EXISTS(SELECT * FROM employees WHERE salary = 30000); # 查詢有員工的部門的部門名 SELECT department_name FROM departments d WHERE EXISTS( SELECT * FROM employees e WHERE d.department_id = e.department_id ) # 查詢有員工的部門的部門名,用in代替了exists SELECT department_name FROM departments d WHERE d.department_id in ( SELECT department_id FROM employees e )
(5) 出現在DML語句(insert、update、delete)中(※)
# 複製數據 INSERT INTO beauty(name, sex, borndate, phone, photo, boyfriend_id) SELECT name, sex, borndate, phone, photo, boyfriend_id FROM beauty; # 修改張三的女朋友的電話號碼爲114 UPDATE beauty b1 INNER JOIN boys b2 ON b1.boyfriend_id = b2.id SET b1.phone = '114' WHERE b2.boyName = '張三' # 刪除張三女朋友的信息 DELETE b2 FROM boys b1 INNER JOIN beauty b2 ON b1.id = b2.boyfriend_id WHERE b1.boyName = '張三' # 刪除張三的信息和張三女朋友的信息 DELETE b1, b2 FROM boys b1 INNER JOIN beauty b2 ON b1.id = b2.boyfriend_id WHERE b1.boyName = '張三'
10、SQL語句的執行順序
select 查詢列表 ⑦
from 表 ①
連接類型 join 表 ②
on 連接條件 ③
where 篩選條件 ④
group by 分組列表 ⑤
having 分組後的篩選 ⑥
order by 排序列表 ⑧
limit 偏移, 條目數 ⑨
11、聯合查詢
作用:將多條查詢語句的結果合併成一個結果
語法:
查詢語句1
union
查詢語句2
union
...
查詢語句n
特點:
①要求所有的查詢語句的查詢結果列數一致
②要求所有的查詢語句的查詢結果的每一列的類型和順序最好是一致的
③union默認對聯合查詢之後的結果去重,如果不想對聯合查詢結果去重可以使用union all
應用場景:要查詢的結果來自於多個表,並且表之間沒有直接的連接關係,但是查詢語句的查詢結果一致
案例:
# 查詢學生姓名中包含a字符或郵箱中包含b字符的學生信息
SELECT * FROM student WHERE name LIKE '%a%'
UNION
SELECT * FROM student WHERE email LIKE '%b%'
12、truncate PK delete
①delete可以加where篩選條件,truncate不能加篩選條件,即truncate只能刪除全部的數據不能篩選
②truncate刪除效率高一些
③如果要刪除的表中有自增長列,用delete刪除後再插入數據,自增長列的值從斷點開始;用truncate刪除後再插入數據,自增長列的值從1開始
④delete刪除有返回值,truncate刪除沒有返回值
⑤delete刪除可以進行事務回滾,truncate刪除不能進行事務回滾
# 刪除admin表的所有數據
TRUNCATE TABLE admin
13、字段類型
(1)整型
整數類型 | 字節 | 範圍 |
---|---|---|
Tinyint | 1 | 有符號:-27~27-1 無符號:0~2^8-1 |
Smallint | 2 | 有符號:-215~216-1 無符號:0~2^16-1 |
Mediumint | 3 | 無符號:-223~223-1 無符號:0~2^24-1 |
Int/Integer | 4 | 無符號:-231~231-1 無符號:0~2^32-1 |
Bigint | 8 | 無符號:-263~263-1 無符號:0~2^64-1 |
特點:
- 如果不設置無符號還是有符號,默認是有符號,如果想設置無符號,需要添加unsigned關鍵字
- 如果插入的數值超出了整型的範圍,會報out of range異常,並且插入臨界值
- 如果不設置長度,會有默認的長度。長度代表了顯示的最大寬度,如果不夠會用0在左邊填充,但必須搭配zerofill使用!
(2)小數
- 分類:
- 浮點型:float(M,D)、double(M,D)
- 定點型:dec(M,D)、decimal(M,D)
- 特點:
- M:整數部位+小數部位,D:小數部位,如果超過範圍,則插入臨界值
- M和D都可以省略,如果是decimal,則M默認爲10,D默認爲0;如果是float和double,則會根據插入的數值的精度來決定精度
- 定點型的精確度較高,如果要求插入數值的精度較高如貨幣運算等則考慮使用
(3)字符型
-
較短的文本:char、varchar
-
其他:
- binary和varbinary用於保存較短的二進制
- enum用於保存枚舉
- set用於保存集合
-
較長的文本:text、blob(較大的二進制)
-
特點:
寫法 M的意思 特點 空間的耗費 效率 char char(M) 最大的字符數,可以省略,默認爲1 固定長度的字符 比較耗費 高 varchar varchar(M) 最大的字符數,不可以省略 可變長度的字符 比較節省 低 注意:M的意思是存放的最大字符數(一個字母是一個字符,一個漢字也是一個字符)
(4)日期類型
-
分類:
類型 數據 date 只保存日期 time 只保存時間 year 只保存年 datetime 保存日期+時間 timestamp 保存日期+時間的時間戳 -
特點:
類型 字節 範圍 時區等的影響 datetime 8 1000——9999 不受 timestamp 4 1970-2038 受
14、約束
六大約束:主鍵約束(primary key)、外鍵約束(foreign key)、非空約束(not null)、默認約束(default)、唯一約束(unique)、檢查約束(check)
約束類型:
-
列級約束:可以加在字段的字段類型後面的約束,有主鍵約束、非空約束、默認約束、唯一約束
DROP TABLE IF EXISTS `user`; CREATE TABLE IF NOT EXISTS `user`( `id` INT PRIMARY KEY, `username` VARCHAR(64) NOT NULL, `gender` CHAR(1) DEFAULT '男' CHECK(`gender`='男' OR `gender`='女'), #mysql不支持檢查約束 `code_id` VARCHAR(32) UNIQUE );
-
表級約束:可以加在表的最後面的約束,有主鍵約束、外鍵約束、唯一約束
DROP TABLE IF EXISTS `user`; CREATE TABLE IF NOT EXISTS `user`( `id` INT, `username` VARCHAR(64) NOT NULL, `gender` CHAR(1) DEFAULT '男' CHECK(`gender`='男' OR `gender`='女'), `code_id` VARCHAR(32), `major_id` INT, PRIMARY KEY (`id`), UNIQUE (`code_id`), FOREIGN KEY (`major_id`) REFERENCES major(`id`) );
注意:MySQL不支持檢查約束和列級外鍵約束
特點:
-
主鍵 PK 唯一鍵
保證唯一性 是否允許爲空 是否允許有多個 是否允許組合 主鍵 可以 不允許 不允許 允許 唯一鍵 可以 允許,但至多有一個爲空 允許 允許 注意:
①使用唯一約束的字段,最多只能有一條記錄的該字段爲null
②unique(字段名1),unique(字段名2)與unique(字段名1, 字段名2)是不一樣的,前面是定義了兩個唯一鍵,後面是定義了一個組合唯一鍵
15、事務
①事務的ACID屬性
原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)
②併發問題
- 髒讀:(針對未提交的數據)一個事務在更新一條記錄,未提交前,第二個事務讀到了第一個事務更新後的記錄,那麼第二個事務就讀到了髒數據,會產生對第一個未提交數據的依賴。一旦第一個事務回滾,那麼第二個事務讀到的數據,將是錯誤的髒數據
- 不可重複讀:(讀取數據本身的對比)一個事務在讀取某些數據後的一段時間後,再次讀取這個數據,發現其讀取出來的數據內容已經發生了改變
- 幻讀:(讀取結果集條數的對比)一個事務按相同的查詢條件查詢之前檢索過的數據,確發現檢索出來的結果集條數變多或者減少(由其他事務插入、刪除的)
③事務的隔離級別
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
READ UNCOMMITTED | √ | √ | √ |
READ COMMITTED | × | √ | √ |
REPEATABLE READ | × | × | √ |
SERIALIZABLE | × | × | × |
注意:
- Mysql默認的隔離級別是REPEATABLE READ,Oracle默認的隔離級別是READ COMMITTED,級別越高效率越低
- Mysql使用的比較多的存儲引擎有innodb、myisam、memory等,其中innodb支持事務,myisam、memory不支持事務
- 事務中支持insert、update、delete、select(查詢不需要事務),不支持create、drop、alter
④查看和設置隔離級別的命令
# 查看隔離級別
SELECT @@tx_isolation;
# 設置當前會話的隔離級別
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ(隔離級別);
# 設置全局的隔離級別
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ(隔離級別);
⑤與事務有關的命令
# 關閉自動提交,同時開啓事務
SET autocommit=0;
# 開啓事務(可以省略)
START TRANSACTION;
# 提交事務
COMMIT;
# 事務回滾
ROLLBACK;
# 設置保存點,只能搭配rollback使用
SAVEPOINT P1;
# 回滾到保存點p1
ROLLBACK TO p1;