前言
內容有點長,建議配合右邊的目錄。。。
本篇博客更多是展示SQL語言操作MySQL,和較少的概念。
這裏並不能保證能夠列出所以的操作,只能儘可能的保證寫出博主當前瞭解的。
MySQL支持命令大小寫,應該說大寫更規範,但是沒有小寫容易閱讀,所以下面操作使用小寫。
確保你已經安裝了MySQL。
建議:使用一個文本編輯器編寫SQL代碼,因爲MySQL默認終端回滾使用前面的代碼很不友好。比如,TXT文本編輯器
該篇博客的所有代碼可以在文章最後看到。
1. 登陸MySQL
如果使用MySQL數據庫,第一步就是登陸MySQL:
mysql -uroot -p -P3306 -h127.0.0.1
-u:用戶名
-p:密碼,這裏隱藏密碼,也可以直接在後面跟上密碼
-P:端口,默認3306
-h:登陸的主機
一般來說,使用最簡單的登陸方式,使用默認配置:
2. 常用的關於MySQL的操作
查詢MySQL版本:
查詢當前時間:
查看系統使用的編碼格式:
如果你沒有修改過任何配置,可能會出現gbk,這在以後的操作可能會出現中文亂碼,百度如何修改編碼格式即可。
修改命令提示符:
修改命令結束符:
默認結束符是 ; ,但是在後面操作(函數等)會使用到修改結束符。
查看當前使用的數據庫:
3. 數據庫操作
查看當前已有的數據庫:
創建數據庫 test2:
if not exists:如果不存在則創建
test2 :數據庫名
charset:指定編碼格式 - utf8、gbk
collate:指導字符集編碼格式 - 最簡單的區不區分大小寫
查看創建數據庫語句:
選擇/使用數據庫:
4. 表操作、記錄增刪查改
一定要選擇數據庫:use test2;
查看當前數據庫已有的表:
創建表 table1: 關鍵字 create
int、varchar都是MySQL支持的數據類型。int默認11位,int(1)指定使用1位。varchar(20)動態字符串類型,最長支持20位字符,存儲的字符是多長就動態佔用多少空間,相對應char(20)佔用空間=20。
not null-非空約束(數據不能爲空),default默認約束(數據爲空時,使用默認數據)。
primary key是主鍵約束(主鍵一定不能爲空,代碼中顯式的寫出了not null,可以不寫,默認爲not null),能夠唯一確定一條記錄,一張表只能有一個主鍵。
auto_increment自增長,能夠自動從1、2、3開始增長,必須配合主鍵約束使用。
engine指定數據表的數據引擎,還有如MyISAM、Archive等。
charset指定表的編碼格式。
查詢創建表語句:
查看錶結構:關鍵字 describe
縮寫:desc table1;
插入數據:關鍵字 insert
下面會以幾種格式展示插入數據:
有多少字段就插入多少數據:
字段有默認值,可以使用defalut代替:
指定插入的字段(前提是必須指定所有不能爲空或默認值的字段),如table1中,id有自增長,gender有默認值就可以不用指定:
一次性插入多條數據:
insert into table1(name, gender) values('rose', 1), ('alex', 0), ('david', 0);
查看錶數據:關鍵字 select
*代表所有字段
指定查詢的字段:
修改數據:
比如 jack 一般爲男性,這裏需要修改爲0
這裏使用了where 關鍵字,表示要修改匹配的記錄,如果不加where,會將表中所有的gender修改爲0。
刪除數據:
where表示刪除指定數據,不加則刪除表中所有數據。
如果,這時再添加一條數據,你認爲id =1 還是4呢?
如果學習過MySQL的,會很肯定的知道id=4,但是如果說爲什麼,查看如下:
或許你還記得,剛創建表時執行這條語句是沒有AUTO_INCREMENT這行的。
所以,再插入一條數據,id=4:
清空數據:
前面提到了 delete from table1; 可以清空所有數據,還有一條效率更高的命令:truncate :
刪除表:
刪除數據庫:
5. 字段操作
或許在創建表之後需要更改字段的類型、約束、增加、刪除字段等。
依然使用上一個示例:
當前數據爲空。。。
增加字段,增加一個年齡字段,關鍵字 alter:
可能你發現字段名、字段類型都是錯誤的,如何修改?
修改字段類型 modify:
現在,字段類型已經修改,如果只需要修改類型,已經成功了。但是,還需要修改字段名。modify顯然做不到,只能使用更加強大的change:
可以看到,默認添加是添加在最後,使用* 查詢的是按字段順序橫向排列。另外還可以指定添加字段的位置:
指定位置使用after 字段(還有其他的first等),這裏添加了唯一索引(記錄中不允許出現重複,如學生學號)。
刪除字段:
6. 外鍵
應該說,外鍵是使用頻率很高的一個約束。
簡單描述:
就是先設置表1的字段m 參照表2的字段n,在向表1的字段m 插入數據時,插入的數據只能是表2中字段n 已有的數據,不能憑空而來。
能夠設置外鍵的前提:字段m 的類型必須與字段n 完全相同,數據引擎=InnoDB。
創建表1:
–(空格) 註釋內容
創建表2:constraint key_name foreign key (字段) references 表(字段)
查看創建表語句(constraint 後面+索引名稱,博主嘗試過,但是名稱依然是默認名稱,你可以嘗試一下):
向表2插入數據:
這裏會報錯,大致意思就是上面說到的,表1中的s_id 沒有數據,插入表2的不能憑空而來。
先在表1插入:
再在表2插入:
或許,這裏你會想到,如果現在更新、刪除表1中的’101’會產生生麼結果呢?
試試:
發現刪除不了。。。
這裏就有了外鍵約束模式:
有三種:
district:嚴格模式(默認),父表(表1)不能刪除子表(表2)已經引用了的數據(101).
cascade:級聯模式,父表的操作級聯更新子表,如刪除101後,子表唯一 一條數據也將被刪除。
set null:置空模式,父表操作後,字表相應字段置空(NULL)
測試:
刪除表2,清空表1數據(注意順序):
表2創建語句修改爲:
學習資料中說:一般採用 刪除置空,級聯更新,不過代碼不能通過。
只好使用級聯刪除、更新
測試:
插入數據:
更新:
刪除:
7. 聯合查詢
爲了方便測試後面的語句,這裏創建四張表:
class:班級表-存放班級id
students:學生表-存放學生信息,並且外鍵到班級表
class:課程表-存放課程信息
choose:選課表,存放學生選課信息
可以不用關注表的具體實現,直接複製粘貼到mysql中即可。。。
依然使用前面的test2 數據庫
use test2;
-- 注意順序
drop table if exists choose;
drop table if exists course;
drop table if exists students;
drop table if exists class;
-- 班級表
create table if not exists class(
id int not null primary key auto_increment,
class_id char(3) not null unique key
)engine=InnoDB default charset=utf8;
-- 學生表
create table if not exists students(
id int not null primary key auto_increment,
class_id char(3) not null,
student_id char(3) not null unique key,
student_name varchar(20) not null,
gender int(1) default 0,
age int(2),
key cid_key (class_id),
foreign key (class_id) references class(class_id) on delete cascade on update cascade
)engine=InnoDB default charset=utf8;
-- 課程表
create table if not exists course(
id int not null primary key auto_increment,
course_id char(3) not null unique key,
course_name varchar(20) not null
)engine=InnoDB default charset=utf8;
-- 選課表
create table if not exists choose(
id int not null primary key auto_increment,
student_id char(3) not null,
course_id char(3) not null,
key key1 (student_id),
key key2 (course_id),
foreign key (student_id) references students(student_id) on delete cascade on update cascade,
foreign key (course_id) references course(course_id) on delete cascade on update cascade
)engine=InnoDB default charset=utf8;
-- 測試數據
insert into class values(default, 'c01'),
(default, 'c02'),
(default, 'c03');
insert into students values(default, 'c02', 's01', 'tom', 0, 19),
(default, 'c02', 's02', 'jack', 0, 17),
(default, 'c01', 's03', 'rose', 1, 25),
(default, 'c03', 's04', 'alex', 0, 23),
(default, 'c01', 's05', 'david', 0, 28),
(default, 'c02', 's06', 'tyler', 1, 18),
(default, 'c02', 's07', 'lucy', 1, 18);
insert into course values(default, 'cc1', 'chinese'),
(default, 'cc2', 'math'),
(default, 'cc3', 'english');
insert into choose values(default, 's02', 'cc1'),
(default, 's03', 'cc2'),
(default, 's01', 'cc3'),
(default, 's04', 'cc2'),
(default, 's05', 'cc2'),
(default, 's02', 'cc3'),
(default, 's03', 'cc1'),
(default, 's06', 'cc1'),
(default, 's01', 'cc2'),
(default, 's07', 'cc1');
聯合查詢:
顧名思義,將多個結果聯合起來。。。
關鍵字 union
從上圖中,可以看出和單個查詢沒有什麼區別。。。這裏就要提到聯合查詢的兩個選項:
all:保留所有記錄
distinct:(默認)去重
再試試all 選項:
使用聯合查詢的小例子,將學生按照男女分組,並且男生按年齡升序排序,女生按年齡降序排序:
order by用於排序,asc 升序(默認) ,desc降序
limit 限制查詢的記錄數(你可以試試不加limt 時,結果有什麼不同?)
最重要的一點:使用order by 和union 的同時,需要加上括號。(不加括號報錯)
提到了 order by,就不得不提group by:
group by 用於分組,但是隻能顯示分組的第一條數據:
可以使用count(*) 看出分組數量:
也可以按照多字段分組,根據分組字段的順序:
8. 子查詢
或許你會疑問上面創建的表需要四張表這麼多嗎?完全可以一張表容納所有的數據。。。
因爲,數據庫表的設計需要符合範式(六範式)。。。
按照基本滿足前三層範式,就需要將能單獨劃分爲一張表的就劃分爲一張表。。。(範式具體內容百度)
現在,劃分了多張表肯定沒有一張表好查詢,所以出現了子查詢。
子查詢可以分爲兩類:按位置分類、按結果分類
- 按位置 - 子查詢出現的位置
from + 子查詢
where + 子查詢
exists + 子查詢 - 按結果 - 子查詢得到的數據結果分類
標量子查詢:結果是一行一列
列子查詢:結果是一列多行
行子查詢:結果是一行多列(多行多列)
前三個都是出現在where 之後。。。
表子查詢:結果是多行多列,出現在from 之後
- 標量子查詢
場景:查詢choose 表中第一個學生的信息
- 列子查詢
場景:查詢choose表中選擇了課程’cc2’的學生的信息
需要使用關鍵字 in
- 行子查詢
場景:查詢男生中年齡最大的
返回的結果是一行兩列。。。
因爲字段原因,所以只能使用gender(如果有其他字段,比如年齡最大,身高最高的學生)
- 表子查詢
場景:查詢每個班年齡最大的學生
必須使用別名,as 後面加上別名(也可以省略as )
- exists 子查詢
exists 的返回結果只有0 或1
因爲exists的返回結果只有0或1,所以無法返回某一個特定的記錄,而是要麼返回空,要麼返回全部:
9. 連接查詢
前面子查詢的操作基本上也是隻查詢了一張表的內容,那如何將多張表的內容連接到一起,組成一張表呢?
連接查詢可分爲:
內連接、外連接、自然連接和交叉連接
- 內連接
內鏈接類似集合中的交集:
班級表與學生表的交集:
使用到了別名,和on 關鍵字(後面加條件)
- 外連接
外連接又分爲了左外和右外連接:
區別在於:
左外會列出左表的所有記錄和右表符合條件的記錄
右外會列出右表的所有記錄和左表符合條件的記錄
爲了更加直觀的顯示,這裏添加一條課程記錄:
3. 交叉連接
笛卡兒積 - 表1 的記錄 x 表2 的記錄
4. 自然連接
自然連接是自動匹配相同的字段。
下面的結果博主目前沒有能力解釋。。。詳情請百度。
使用示例:
查詢選課表時,結果是學生id 和 課程id ,如果你知道那個學生選了那門課程,就還需要去對照查詢學生表和課程表。這很麻煩。。。
所以可以使用連接查詢:
第一步,顯示課程名
第二步,顯示學生名
再排下序:
連接上所有表:
10. 視圖
視圖和表的操作有很多相似之處,不同的是視圖不存放數據,只是對sql 語句的封裝,這對數據有很大的安全性保證。
比如,如果直接給了表的權限,可能會對數據造成不可預計的損壞。而視圖則規定了你只能操作什麼。
創建視圖:
查看視圖:
可以從某種意思上說視圖是一張虛擬的表,所以很多操作和表類似
使用視圖:
修改視圖:
刪除視圖:
視圖意義:
節省SQL語句,如需要多次執行的SQL,完全可以寫成一個視圖
數據安全:給出什麼樣的視圖就只能做什麼樣的操作
。。。
還有一個很重要的就是如何使用視圖操作原表的數據?
視圖可以操作數據,但是有很多限制。。。
這裏就不再詳細演示了,有興趣可以百度。
視圖也可以指定視圖算法,簡單來說就是查詢語句的先後執行順序,詳細內容請百度。
結語
這篇博客就先介紹到這裏吧。。。
其他更加深入的MySQL操作:
備份與還原:https://blog.csdn.net/qq_38038143/article/details/90316084
函數、存儲過程、觸發器:https://blog.csdn.net/qq_38038143/article/details/90316749
代碼
# 3. 數據庫操作
create database if not exists test2 charset utf8 collate utf8_general_ci;
show create database test2;
desc test2;
select database();
##########################################################################
# 4. 表操作
use test2;
show tables;
create table if not exists table1(
id int not null primary key auto_increment,
name varchar(20) not null,
gender int(1) default 1
)engine=InnoDB default charset=utf8;
show create table table1;
insert into table1 values(1, 'tom', 0);
insert into table1 values(default, 'jack', default);
insert into table1(name) values('lucy');
select * from table1;
select name, gender from table1;
update table1 set gender=0 where id=2;
delete from table1 where id=1;
show create table table1;
insert into table1(name, gender) values('tom', 0);
select * from table1;
##########################################################################
### 5. 字段操作
alter table table1 add agc varchar(2);
alter table table1 modify agc int(2);
alter table table1 change agc age int(2);
alter table table1 add s_id varchar(11) not null unique key after id;
alter table table1 drop age;
##########################################################################
### 6.外鍵
-- 表1
create table if not exists table1(
id int not null primary key auto_increment,
s_id char(3) not null unique key,
name varchar(20) not null,
gender int(1) default 1
)engine=InnoDB default charset=utf8;
-- 表2
create table if not exists table2(
id int not null primary key auto_increment,
s_id char(3) not null unique key,
class_name varchar(20) not null,
key sid_key (s_id),
foreign key (s_id) references table1(s_id)
)engine=InnoDB default charset=utf8;
show create table table2;
insert into table2 values(default, '101', 'chinese');
insert into table1 values(default, '101', 'tom', 0),
(default, '102', 'rose', 1);
insert into table2 values(default, '101', 'chinese');
-- 級聯刪除-級聯更新
-- 表2
create table if not exists table2(
id int not null primary key auto_increment,
s_id char(3) not null unique key,
class_name varchar(20) not null,
key sid_key (s_id),
foreign key (s_id) references table1(s_id) on delete cascade on update cascade
)engine=InnoDB default charset=utf8;
insert into table1 values(default, '101', 'tom', 0),
(default, '102', 'rose', 1);
insert into table2 values(default, '101', 'chinese');
update table1 set s_id='103' where id=1;
delete from table1 where s_id='103';
##########################################################################
# 7 聯合查詢
use test2;
-- 注意順序
drop table if exists choose;
drop table if exists course;
drop table if exists students;
drop table if exists class;
-- 班級表
create table if not exists class(
id int not null primary key auto_increment,
class_id char(3) not null unique key
)engine=InnoDB default charset=utf8;
-- 學生表
create table if not exists students(
id int not null primary key auto_increment,
class_id char(3) not null,
student_id char(3) not null unique key,
student_name varchar(20) not null,
gender int(1) default 0,
age int(2),
key cid_key (class_id),
foreign key (class_id) references class(class_id) on delete cascade on update cascade
)engine=InnoDB default charset=utf8;
-- 課程表
create table if not exists course(
id int not null primary key auto_increment,
course_id char(3) not null unique key,
course_name varchar(20) not null
)engine=InnoDB default charset=utf8;
-- 選課表
create table if not exists choose(
id int not null primary key auto_increment,
student_id char(3) not null,
course_id char(3) not null,
key key1 (student_id),
key key2 (course_id),
foreign key (student_id) references students(student_id) on delete cascade on update cascade,
foreign key (course_id) references course(course_id) on delete cascade on update cascade
)engine=InnoDB default charset=utf8;
-- 測試數據
insert into class values(default, 'c01'),
(default, 'c02'),
(default, 'c03');
insert into students values(default, 'c02', 's01', 'tom', 0, 19),
(default, 'c02', 's02', 'jack', 0, 17),
(default, 'c01', 's03', 'rose', 1, 25),
(default, 'c03', 's04', 'alex', 0, 23),
(default, 'c01', 's05', 'david', 0, 28),
(default, 'c02', 's06', 'tyler', 1, 18),
(default, 'c02', 's07', 'lucy', 1, 18);
insert into course values(default, 'cc1', 'chinese'),
(default, 'cc2', 'math'),
(default, 'cc3', 'english');
insert into choose values(default, 's02', 'cc1'),
(default, 's03', 'cc2'),
(default, 's01', 'cc3'),
(default, 's04', 'cc2'),
(default, 's05', 'cc2'),
(default, 's02', 'cc3'),
(default, 's03', 'cc1'),
(default, 's06', 'cc1'),
(default, 's01', 'cc2'),
(default, 's07', 'cc1');
-- 聯合查詢
select * from class
union
select * from class;
select * from class
union all
select * from class;
(select * from students where gender=0 order by age asc limit 99999)
union
(select * from students where gender=1 order by age desc limit 99999);
select * from students group by gender;
select *,count(*) from students group by gender;
select *,count(*) from students group by class_id,gender;
select * from students where student_id = (
select student_id from choose where id = 1);
select * from students where student_id in (
select student_id from choose where course_id = 'cc2');
select * from students where (age,gender) = (
select max(age),gender from students where gender = 0);
select * from (select * from students order by age desc) as s1
group by class_id;
select * from students where
exists(select * from choose where course_id = 'cc3');
##########################################################################
# 9. 連接查詢
select * from class c inner join students s on c.class_id=s.class_id;
insert into course values(default, 'cc4', 'physics');
select * from course c left join choose cc on c.course_id=cc.course_id;
select * from class cross join students;
select * from course natural join choose using course_id;
-- 使用示例
select c.id,c.student_id,cc.course_name
from choose c left join course cc
on c.course_id=cc.course_id;
select c.id,s.student_name,cc.course_name
from choose c left join course cc
on c.course_id=cc.course_id
left join students s
on c.student_id=s.student_id;
select c.id,s.student_name,cc.course_name
from choose c left join course cc
on c.course_id=cc.course_id
left join students s
on c.student_id=s.student_id
order by c.id;
select c.id,cs.class_id,s.student_id,s.student_name,cc.course_name
from choose c left join course cc
on c.course_id=cc.course_id
left join students s
on c.student_id=s.student_id
left join class cs
on s.class_id=cs.class_id
order by c.id;
##########################################################################
# 10. 視圖
create view get_class as
select * from class;
show create view get_class;
show create table get_class;
desc get_class;
select * from get_class;
alter view get_class as
select class_id from class;
drop view get_class;