由於最近心血來潮,就把SQL重新過了一遍,順便總結了一份小寶典,應該算是挺全面的哈~~
導語:SQL
之路–SQL大全
作者:變優秀的小白
愛好:美式一定加冰!
資料庫按照資料結構來組織、儲存和管理資料
名稱 | 型別 | 說明 |
---|---|---|
INT | 整型 | 4位元組 |
BIGINT | 長整型 | 8位元組 |
REAL | 浮點型 | 4位元組 |
DOUBLE | 浮點型 | 8位元組 |
DECIMAL | 高精度小數 | DECIMAL(20,10)表示一共20位,其中小數10位,通常用於財務計算 |
CHAR | 定長字串 | 儲存指定長度的字串,例如,CHAR(100)總是儲存100個字元的字串 |
VARCHAR | 變長字串 | 儲存可變長度的字串 |
BOOLEAN | 布林型別 | True或者False |
DATE | 日期型別 | 日期 |
TIME | 時間型別 | 時間 |
DATETIME | 日期和時間型別 | 儲存日期+時間 |
若是windows版本,百度上有很多安裝教學,
# 若是使用brew安裝的(系統為macOS)
# 需要通過brew啟動mysql
$ brew services start mysql
$ mysql -u root -p
沒有必要的情況下,我們儘量不使用聯合主鍵,因為它給關係錶帶來了複雜度的上升
增加一個外來鍵約束
ALTER TABLE students
ADD CONSTRAINT fk_class_id
FOREIGN KEY (class_id)
REFERENCES classes (id);
刪除一個外來鍵約束
ALTER TABLE students
DROP FOREIGN KEY fk_class_id;
均為表之間的對應關係
關聯式資料庫中對某一列或多個列的值進行預排序的資料結構
可以讓資料庫系統不必掃描整個表,而是直接定位到符合條件的記錄,這樣就大大加快了查詢速度
id | class_id | name | gender | score |
---|---|---|---|---|
1 | 1 | 小明 | M | 90 |
2 | 1 | 小紅 | F | 95 |
3 | 1 | 小軍 | M | 88 |
場景:要經常根據score列進行查詢
解決:對score列建立索引
ALTER TABLE students
ADD INDEX idx_score (score);
則建立了一個名稱未idx_score的索引
場景:索引名稱是任意的,索引如果有多列
解決:括號內增加列名稱
ALTER TABLE students
ADD INDEX idx_name_score (name, score);
運用場景:
解決:該列新增一個唯一索引
ex例子:
新增一個唯一索引
ALTER TABLE students
ADD UNIQUE INDEX uni_name (name);
新增一個唯一約束而不建立唯一索引(具有唯一性保證)
ALTER TABLE students
ADD CONSTRAINT uni_name UNIQUE (name);
ex. *
SELECT *
FROM students;
ex. where & and & or & ()
SELECT *
FROM students
WHERE (score < 80 OR score > 90)
AND gender = 'M';
ex. 列1、列2…
SELECT id, score, name
FROM students;
ex. ORDER BY & DESC & ASC
SELECT id, name, gender, score
FROM students
WHERE class_id = 1
ORDER BY score DESC;
ex. LIMIT M OFFSET N
-- 查詢第一頁
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 0;
-- 查詢第二頁,需要 "跳過" 前三條記錄
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 3;
-- 查詢第四頁,類似
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 9;
-- 若查詢頁沒有資料,不報錯,得到空結果集
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 20;
注意點:如果聚合查詢的WHERE條件沒有匹配到任何行,COUNT()會返回0,而SUM()、AVG()、MAX()和MIN()會返回NULL
-- 使用聚合查詢
SELECT COUNT(*) FROM students;
-- 使用聚合查詢並設定結果集的列名為num
SELECT COUNT(*) num FROM students;
-- 使用聚合查詢並設定WHERE條件
SELECT COUNT(*) boys FROM students WHERE gender = 'M';
-- 分組聚合
SELECT class_id, COUNT(*) num FROM students GROUP BY class_id;
-- 聚合查詢的列中,只能放入分組的列
SELECT class_id, gender, COUNT(*) num FROM students GROUP BY class_id, gender;
-- 使用聚合查詢計算男生平均成績
-- average為自定義名稱
SELECT AVG(score) average FROM students WHERE gender = 'M';
-- 每頁3條記錄,如何通過聚合查詢獲得總頁數
SELECT CEILING(COUNT(*)/3) FROM student;
-- 兩個表的乘積
SELECT * FROM students, classes;
-- 可設定列的別名區分
SELECT
students.id sid,
students.name,
students.gender,
students.score,
classes.id cid,
classes.name cname
FROM students, classes;
-- sql可給表設定別名,相對於上面會簡潔些
SELECT
s.id sid,
s.name,
s.gender,
s.score,
c.id cid,
c.name cname
FROM students s, classes c;
-- 加上where條件判斷
SELECT
s.id sid,
s.name,
s.gender,
s.score,
c.id cid,
c.name cname
FROM students s, classes c
WHERE s.gender = 'M' AND c.id = 1;
FROM 表1
INNER JOIN 表2
ON 條件
WHERE
Or ORDER BY
等-- 內連線,運用別名,id對應取出
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
INNER JOIN classes c
ON s.class_id = c.id;
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
LEFT OUTER JOIN classes c
ON s.class_id = c.id;
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
RIGHT OUTER JOIN classes c
ON s.class_id = c.id;
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
FULL OUTER JOIN classes c
ON s.class_id = c.id;
INSERT INTO <表名> (欄位1, 欄位2, ...) VALUES (值1, 值2, ...);
INSERT INTO students (class_id, name, gender, score) VALUES
(1, '張三', 'M', 87),
(2, '李四', 'M', 81);
-- 查詢更新結果
SELECT * FROM students;
UPDATE <表名> SET 欄位1=值1, 欄位2=值2, ... WHERE ...;
-- 更新多條記錄
UPDATE students SET name='小牛', score=77 WHERE id>=5 AND id<=7;
-- 使用表示式,將所有80下同學成績加10分
UPDATE students SET score=score+10 WHERE score<80;
-- 查詢並觀察結果:
SELECT * FROM students;
-- 刪除id=1的記錄
DELETE FROM students WHERE id=1;
-- 刪除id=5,6,7的記錄
DELETE FROM students WHERE id>=5 AND id<=7;
-- 查詢並觀察結果:
SELECT * FROM students;
-- 建立一個新的DB
mysql> CREATE DATABASE test
Query OK, 1 row affected (0.01 sec)
-- 刪除一個DB
mysql> DROP DATABASE test
Query OK, 0 rows affected (0.01 sec)
-- 切換DB
mysql> USE test;
Database changed
-- 檢視DB的所有表
mysql> SHOW TABLES;
-- 檢視一個表的結構
mysql> DESC students;
-- 檢視建立表的SQL語句
mysql> SHOW CREATE TABLE students;
-- 刪除表
mysql> DROP TABLE students;
Query OK, 0 rows affected (0.01 sec)
-- 修改表,如新增一列
ALTER TABLE students ADD COLUMN birth VARCHAR(10) NOT NULL;
-- 修改表,列名改為birthday,型別改為VARCHAR(20)
ALTER TABLE students CHANGE COLUMN birth birthday VARCHAR(20) NOT NULL;
-- 修改表,刪除列
ALTER TABLE students DROP COLUMN birthday;
mysql> exit
Bye
-- 若記錄已經存在,刪除原記錄,再插入新記錄
REPLACE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);
-- 語法:INSERT INTO ... ON DUPLICATE KEY UPDATE ...
-- 如果記錄已經存在,就更新該記錄
INSERT INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99) ON DUPLICATE KEY UPDATE name='小明', gender='F', score=99;
-- 如果記錄已經存在,就啥事也不幹直接忽略
INSERT IGNORE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);
-- 對class_id=1的記錄進行快照,並儲存為新表students_of_class1:
CREATE TABLE students_of_class1 SELECT * FROM students WHERE class_id=1;
-- FORCE INDEX
SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;
某些業務要求必須完成一系列的操作,而不是隻執行一部分
可見,資料庫事務有ACID 4個特性
解釋:單條SQL語句,資料庫系統自動將其作為一個事務執行
解釋:多條SQL語句作為一個事務執行,使用BEGIN開啟一個事務,使用COMMIT提交一個事務
-- 顯式事務例子
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
-- 若希望它主動失敗,ROLLBACK回滾事務就很棒
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
ROLLBACK;
目的:對於兩個並行執行的事務,如果涉及到操作同一條記錄的時候,可能會發生問題
解釋:是隔離級別最低的一種事務級別。在這種隔離級別下,一個事務會讀到另一個事務更新後但未提交的資料,如果另一個事務回滾,那麼當前事務讀到的資料就是髒資料,這就是髒讀(Dirty Read)
解釋:不可重複讀是指,在一個事務內,多次讀同一資料,在這個事務還沒有結束時,如果另一個事務恰好修改了這個資料,那麼,在第一個事務中,兩次讀取的資料就可能不一致
解釋:一個事務可能會遇到幻讀(Phantom Read)的問題。
幻讀是指,在一個事務中,第一次查詢某條記錄,發現沒有,但是,當試圖更新這條不存在的記錄時,竟然能成功,並且,再次讀取同一條記錄,它就神奇地出現了。
解釋:在Serializable隔離級別下,所有事務按照次序依次執行,因此,髒讀、不可重複讀、幻讀都不會出現。