【MySQL】黑马教程MySQL数据库 MySQL基础(二)
文章目錄
- 【MySQL】黑馬教程MySQL數據庫 MySQL基礎(二)
- 函數
- 字符串函數
- 數值函數
- 日期函數
- 流程函數
- 總結
- 約束
- 概述
- 約束演示
- 外鍵約束
- 添加外鍵
- 刪除外鍵
- 刪除/更新行為
- 多表查詢
- 多表關系
- 多表查詢概念
- 內連接
- 外連接
- 自連接
- 聯合查詢 - union,union all(集合查詢)
- 子查詢
- 標量子查詢
- 列子查詢
- 行子查詢
- 表子查詢
- 多表查詢案例
- 案例
【MySQL】黑馬教程MySQL數據庫 MySQL基礎(二)
本專欄主要是根據B站黑馬程序員網課視頻寫該專欄,網課鏈接如下黑馬程序員 MySQL數據庫入門到精通,從mysql安裝到mysql高級、mysql優化全囊括。
使用的軟件是DataGrip,可以在官網下載,如果需要破解,可以私信聯系,免費破解。(一鍵操作即可,懂得都懂😀😀😀)
寫該專欄的目的,一方面作為個人筆記,純手工敲出來,運行結果均為自己動手敲出,大家盡量敲一遍(沒必要根據我的一樣,參考網課),切勿手高眼低;另一方面,網上的教程層次不齊,有些地方看的難受,比如代碼展示方面,純文字,并且比較啰嗦,抓重點即可。(僅個人觀點,勿噴😸😸😸)
函數
函數是指一段可以直接被另一段程序調用的程序或代碼。
字符串函數
MySQL中內置了很多字符串函數,常用的幾個如下:
| concat(S1, S2, ……Sn) | 字符串拼接,將S1, S2, ……Sn拼接成一個字符串 |
| lower(str) | 將字符串str全部轉為小寫 |
| upper(str) | 將字符串str全部轉為大寫 |
| lpad(str, n, pad) | 左填充,用字符串pad對str的左邊進行填充,達到n個字符串長度 |
| rpad(str, n, pad) | 右填充,將字符串pad對str的右邊進行填充,達到n個字符串長度 |
| trim(str) | 去掉字符串頭部和尾部的空格 |
| substring(str, start, len) | 返回從字符串str從start位置起的len個長度的字符串 |
eg:用于業務需求變更,企業員工的工號,統一為5位數,目前不足5位數的全部在前面補0,比如:1號員工的工號應該為00001.
update emp set workno = lpad(workno, 5, '0');數值函數
常見的數值函數如下:
| ceil(x) | 向上取整 |
| floor(x) | 向下取整 |
| mod(x) | 返回x/y的模 |
| rand() | 返回0~1內的隨機數 |
| round(x, y) | 求參數x的四舍五入的值,保留y位小數 |
eg:# 通過數據庫的數據,生成一個六位數的隨機驗證碼
select lpad(round(rand() * 1000000,0), 6, '0');日期函數
常見的日期函數:
| curdata() | 返回當前日期 |
| curtime() | 返回當前時間 |
| now() | 返回當前日期和時間 |
| year(date) | 獲取指定date的年份 |
| month(date) | 獲取指定date的月份 |
| day(date) | 獲取指定date的日期 |
| data_add(date, interval expr type) | 返回一個日期/時間值上加上一個時間間隔expr后的時間值 |
| datediff(date1, date2) | 返回起始時間date1 和結束時間date2之間的天數 |
eg:查詢所有員工的入職天數,并根據入職天數倒敘排序
select name ,datediff(curdate(), entrydate) as entryday from emp order by entryday desc;流程函數
流程函數也是很常見的一類函數,可以在SQL語句中實現條件篩選,從而提高語句的效率。
| if(value, t, f) | 如果value為true,則返回t,否則返回f |
| ifnull(value1, value2) | 如果value1不為空,返回value1,否則返回value2 |
| case when [val1] then [res1] ……else [default] end | 如果val1為true,返回res1,……否則返回default默認值 |
| case [expr] when [val1] then [res1]…… else [default] end | 如果expr的值等于val1,返回res1,……否則返回default默認值 |
eg:統計班級各個學員的成績,展示的規則如下
- >= 85 展示優秀
- >=60 展示及格
- 否則,展示不及格
總結
-
字符串函數
concat, lower, upper, lpad, rpad, trim, substring -
數值函數
ceil, floor, mod, rand, round -
日期函數
curtime, curdate, now, year, month, day, date_add, datediff -
流程函數
if, ifnull, case[...] when ...then ...else...end
約束
概述
概念:約束是作用于表字段上的規則,用于限制存儲在表中的數據。
目的:保證數據庫中數據的正確、有效性和完整性。
分類:
| 非空約束 | 限制該字段的數據不能為null | not null |
| 唯一約束 | 保證該字段的所有數據都是唯一,不重復的 | unique |
| 主鍵約束 | 主鍵是一行的唯一表示,要求非空且唯一 | primary key |
| 默認約束 | 保存數據時,如果未指定該字段的值,則采用默認值 | default |
| 檢查約束 | 保證字段值滿足某一個條件 | check |
| 外鍵約束 | 用來讓兩張表的數據間之間建立連接,保證數據的一致性和完整性 | foreing key |
注意:約束是作用于表中字段上的,可以在創建表/修改表的時候添加約束。
約束演示
案例:根據需求,完成表結構的創建
| id | ID唯一標識 | int | 主鍵,并且自動增長 | primary key,auto_increment |
| name | 姓名 | varchar(10) | 不為空,并且唯一 | not null, unique |
| age | 年齡 | int | 大于0,并且小于等于120 | check |
| status | 狀態 | char(1) | 如果沒有指定該值,默認為1 | default |
| gender | 性別 | char(1) | 無 |
外鍵約束
外鍵用來讓兩張表的數據之間建立連接,從而保證數據的一致性和完整性。
添加外鍵
alter table 表名 add constraint 外鍵名稱 foreign key(外鍵字段名) references 主表(主表列名);eg:添加外鍵
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);刪除外鍵
alter table 表名 drop foreign key 外鍵名稱;eg:刪除外鍵
alter table emp drop foreign key fk_emp_dept_id;刪除/更新行為
| no action | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則不允許刪除/更新。(與restrict一致) |
| restrict | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則不允許刪除/更新。(與no action一致) |
| cascade | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有,則也刪除/更新外鍵在子表中的記錄。 |
| set null | 當在父表中刪除對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則設置子表中該外鍵值為null(這就要求該外鍵允許取null) |
| set default | 父表有變更時,子表將外鍵列設置成一個默認的值(lnnodb不支持) |
eg:外鍵的刪除和更新行為——級聯更新
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update cascade on delete cascade ;eg2:
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null;多表查詢
多表關系
項目開發中,在進行數據庫表結構設計時,會根據業務需求及業務模塊之間的關系,分析并設計表結構,由于業務之間相互關聯,所以各個表結構之間也存在著各種聯系,基本上分為三種:
-
一對多
案例:部門 與 員工的關系
關系:一個部門對應多個員工,一個員工對應一個部門
實現:在多的一方建立外鍵,指向一的方的主鍵
# 多對多 create table student(id int auto_increment primary key comment '主鍵ID',name varchar(10) comment '姓名',no varchar(10) comment '學號' )comment '學生表';insert into student values (null, '黛綺絲', '2000100101'), (null, '謝遜', '2000100102'), (null, '殷天正', '2000100103'), (null, '韋一笑', '2000100104');create table course(id int auto_increment primary key comment '主鍵ID',name varchar(10) comment '課程名稱' )comment '課程表';insert into course values (null, 'Java'), (null, 'PHP'), (null, 'MySQL'), (null, 'Hadoop');create table student_course(id int auto_increment primary key comment '主鍵',studentid int not null comment '學生ID',courseid int not null comment '課程ID',constraint fk_courseid foreign key (courseid) references course(id),constraint fk_studentid foreign key (studentid) references student(id) )comment '學生課程中間表';insert into student_course values (null, 1, 1), (null, 1, 2), (null, 1, 3), (null, 2, 2), (null, 2, 3), (null, 3, 4); -
多對多
-
一對一
案例:用戶 與 用戶詳情的關系
關系:一對一關系,多用于單表拆分,將一張表的基礎字段放在一張表中,其他詳情字段放在另一張表中,以提升操作效率
實現:在任意一方假如外鍵,關聯另外一方的外鍵,并且設置為唯一的(unique)
create table tb_user(id int auto_increment primary key comment '主鍵ID',name varchar(10) comment '姓名',age int comment '年齡',gender char(1) comment '1:男 , 2:女',phone char(11) comment '手機號' )comment '用戶基本信息表';create table tb_user_edu(id int auto_increment primary key comment '主鍵ID',degree varchar(20) comment '學歷',major varchar(50) comment '專業',primaryschool varchar(50) comment '小學',middleschool varchar(50) comment '中學',university varchar(50) comment '大學',userid int unique comment '用戶ID',constraint fk_userid foreign key (userid) references tb_user(id) )comment '用戶教育信息表';insert into tb_user(id, name, age, gender, phone) VALUES (null, '黃渤', 45, '1', '18800001111'),(null, '冰冰', 35, '2', '18800001111'),(null, '馬云', 55, '1', '18800008888'),(null, '李彥宏', 50, '1', '18800009999');insert into tb_user_edu(id, degree, major, primaryschool, middleschool, university, userid) VALUES (null, '本科', '舞蹈', '靜安區第一小學', '靜安區第一中學', '北京舞蹈學院', 1), (null, '碩士', '表演', '朝陽區第一小學', '朝陽區第一中學', '北京電影學院', 2), (null, '本科', '英語', '杭州市第一小學', '杭州市第一中學', '杭州師范大學', 3), (null, '本科', '應用數學', '陽泉第一小學', '陽泉第一中學', '清華大學', 4);
多表查詢概念
概述:指從多張表中查詢數據
笛卡爾積:笛卡爾乘積是指在數學中,兩個集合A集合 和 B集合的所有組合情況。(在查詢多表時,需要消除無效的笛卡爾積)
數據準備:
# 如果表存在,則先刪除外鍵后再重建 alter table emp drop foreign key fk_emp_dept_id; # 刪除dept表 drop table if exists dept; # 創建dept表 create table dept (id int auto_increment comment 'ID' primary key,name varchar(50) not null comment '部門名稱' ) comment '部門表'; insert into dept (id, name) values (1, '研發部'),(2, '市場部'),(3, '財務部'),(4, '銷售部'),(5, '總經辦'),(6, '人事部');drop table if exists emp; # 創建emp表 create table emp (id int auto_increment comment 'ID' primary key,name varchar(50) not null comment '姓名',age int comment '年齡',job varchar(20) comment '職位',salary int comment '薪資',entrydate date comment '入職時間',managerid int comment '直屬領導ID',dept_id int comment '部門ID',-- 添加外鍵constraint fk_emp_dept_id foreign key (dept_id) references dept (id) ) comment '員工表'; # 向emp中插入數據 insert into emp (id, name, age, job, salary, entrydate, managerid, dept_id) values (1, '金庸', 66, '總裁', 20000, '2000-01-01', null, 5),(2, '張無忌', 20, '項目經理', 12500, '2005-12-05', 1, 1),(3, '楊逍', 33, '開發', 8400, '2000-11-03', 2, 1),(4, '韋一笑', 48, '開發', 11000, '2002-02-05', 2, 1),(5, '常遇春', 43, '開發', 10500, '2004-09-07', 3, 1),(6, '小昭', 19, '程序員鼓勵師', 6600, '2004-10-12', 2, 1),(7, '滅絕', 60, '財務總監', 8500, '2002-09-12', 1, 3),(8, '周芷若', 19, '會計', 48000, '2006-06-02', 7, 3),(9, '丁敏君', 23, '出納', 5250, '2009-05-13', 7, 3),(10, '趙敏', 20, '市場部總監', 12500, '2004-10-12', 1, 2),(11, '鹿杖客', 56, '職員', 3750, '2006-10-03', 10, 2),(12, '鶴筆翁', 19, '職員', 3750, '2007-05-09', 10, 2),(13, '方東白', 19, '職員', 5500, '2009-02-12', 10, 2),(14, '張三豐', 88, '銷售總監', 14000, '2004-10-12', 1, 4),(15, '俞蓮舟', 38, '銷售', 4600, '2004-10-12', 14, 4),(16, '宋遠橋', 40, '銷售', 4600, '2004-10-12', 14, 4),(17, '陳友諒', 42, null, 2000, '2011-10-12', 1, null);結果演示:
select * from emp, dept; # 笛卡爾積 select * from emp, dept where emp.dept_id = dept.id;內連接
內連接查詢語法:
-
隱式內連接
select 字段列表 from 表1,表2 where 條件……; -
顯式內連接
select 字段列表 from 表1 [inner] join 表2 on 連接條件……;
內連接查詢的是兩張表交集的部分
eg:查詢每一個員工姓名,及關聯的部門的名稱
# 查詢每一個員工的姓名,及關聯的部門的名稱(隱式內連接實現) select emp.name, dept.name from emp, dept where emp.dept_id = dept.id;# 查詢每一個員工的姓名,及關聯的部門的名稱(顯式內連接實現) select emp.name, dept.name from emp inner join dept where emp.dept_id = dept.id; # 正常寫法 select emp.name, dept.name from emp join dept where emp.dept_id = dept.id; # 省略inner select e.name, d.name from emp e join dept d where e.dept_id = d.id; # 起別名外連接
外連接查詢語法:
-
左外連接
select 字段列表 from 表1 left [outer] join 表2 on 條件……;相當于查詢字段1(左表)的所有數據包含表1和表2交集部分的數據
-
右外連接
select 字段列表 from 表1 right [outer] join 表2 on 條件……;相當于查詢表2(右表)的所有數據包含表1和表2交集部分數據
eg:查詢emp表的所有數據,和對應的部門信息(左外連接)
select emp.*, dept.name from emp left outer join dept on emp.dept_id = dept.id; select emp.*, dept.name from emp left join dept on emp.dept_id = dept.id;eg:查詢dept表的所有數據,和對應的員工信息(右外連接)
select dept.*, emp.* from emp right outer join dept on emp.dept_id = dept.id; select * from emp e right join dept d on e.dept_id = d.id;自連接
自連接查詢語法:
select 字段列表 from 表A 別名A join 表名A 別名B on 條件……;自連接查詢,可以是內連接,也可以是外連接查詢。一定要起別名
eg:查詢 員工 及其 所屬領導的名字
select a.name '員工', b.name '領導' from emp a join emp b on a.managerid = b.id;eg:查詢所有員工 emp 及其領導的名字 emp, 如果員工沒有領導,也需要查詢出來
select a.name '員工', b.name '領導' from emp a left join emp b on a.managerid = b.id;聯合查詢 - union,union all(集合查詢)
對于union查詢,就是把多次查詢的結果合并起來,形成一個新的查詢結果集。
select 字段列表 from 表A …… union [all] select 字段列表 from 表B ……;eg:將工資低于 5000 的員工, 和 年齡大于50歲的員工全部查詢出來
select * from emp where salary < 5000 union all select * from emp where age > 50; # 結果重復 select * from emp where salary < 5000 union select * from emp where age > 50; # 結果無重復對于聯合查詢的多張表的列數必須保持一致,字段類型也需要保持一致。
union all會將全部的數據直接合并在一起,union會對合并之后的數據去重
子查詢
-
概念:SQL語句中嵌套select語句,稱為嵌套語句,又稱子查詢。
select * from t1 where column1 = (select column1 from t2);子查詢外部的語句可以使insert / update / delete / select 的任何一個。
-
根據子查詢結果不同,分為:
- 標量子查詢(子查詢結果為單個值)
- 列子查詢(子查詢結果為一列)
- 行子查詢(子查詢結果為一列)
- 表子查詢(子查詢結果為多行多列)
-
根據子查詢位置,分為: where之后、from之后、select之后。
標量子查詢
子查詢返回的結果是單個值(數字、字符串、日期等),最簡單地形式,這種子查詢稱為標量子查詢
常用的操作符:= <> > >= < <=
eg:查詢銷售部的所有員工信息
# a. 查詢”銷售部“部門ID select id from dept where name = '銷售部';# b. 根據銷售部門ID,查詢員工信息 select * from emp where dept_id = 4; select * from emp where dept_id = (select id from dept where name = '銷售部');eg:查詢在 方東白 入職之后的員工信息
# 插入 方東白 的入職日期 select entrydate from emp where name = '方東白';# 查詢指定入職日期之后入職的員工信息 select * from emp where entrydate > (select entrydate from emp where name = '方東白');列子查詢
子查詢返回的結果是一列(可以是多行),這種查詢稱為列子查詢
常用的操作符: in、 not in、 any 、some 、all
| in | 在指定集合范圍內,多旋一 |
| not in | 不在指定的集合范圍之內 |
| any | 子查詢返回列表中,有任何一個滿足即可 |
| some | 與any等同,使用some的地方都可以使用any |
| all | 子查詢返回列表的所有值都必須滿足 |
eg;查詢 銷售部 和 市場部的所有員工信息
# 查詢 銷售部 和 市場部 的部門ID select id from dept where name = '銷售部' or name = '市場部'; # 根據部門ID,查詢員工信息 select * from emp where dept_id in (select id from dept where name = '市場部' or name = '銷售部');eg:查詢比 財務部 所有人工資都高的員工信息
# 查詢所有 財務部 人員工資 select id from dept where name = '財務部';select salary from emp where dept_id = (select id from dept where name = '財務部'); # b 比 財務部 所有人工資都高的員工 select * from emp where salary > all(select salary from emp where dept_id = (select id from dept where name = '財務部'));eg :查詢比研發部其中任意一人員工工資高的員工信息
# 查詢研發部門所有人工資 select salary from emp where dept_id = (select id from dept where name = '研發部');# 比研發部其中任意一人工資都高的員工信息 select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name = '研發部'));行子查詢
子查詢返回的結果是一行(可以是多列),這種子查詢稱為行子查詢。
常用的操作符:= 、 <> 、 in、 not in
eg:查詢與 張無忌 的薪資及直屬領導相同的員工信息
# 行子查詢 # 查詢 張無忌 的薪資及直屬領導相同的員工信息 select salary, managerid from emp where name = '張無忌';# 查詢與 張無忌 的薪資及直屬領導相同的員工信息 select * from emp where (salary, managerid) = (select salary, managerid from emp where name = '張無忌');表子查詢
子查詢返回的結果是多行多列,這種子查詢稱為表子查詢。
常用的操作符:in
eg:查詢與 鹿杖客、宋遠橋 的職位和薪資相同的員工信息
# 表子查詢 # 查詢 鹿杖客、宋遠橋 的職位和薪資 select job, salary from emp where name = '鹿杖客' or name = '宋遠橋';# 查詢與 鹿杖客、宋遠橋 的職位和薪資相同的員工信息 select * from emp where (job, salary) in (select job, salary from emp where name = '鹿杖客' or name = '宋遠橋');eg:查詢入職日期是 2006-01-01 之后的員工信息,及其部門信息
# 表子查詢 # 入職日期是 2006-01-01 之后的員工信息 select * from emp where entrydate > '2006-01-01';# 查詢這部分員工,對應的部門信息 select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id;多表查詢案例
數據準備:
# 多表查詢 create table salgrade(grade int,losal int,hisal int )comment '薪資等級表';insert into salgrade values (1, 0, 3000),(2, 3001, 5000),(3, 5001, 8000),(4, 8001, 10000),(5, 10001, 15000),(6, 15001, 20000),(7, 20001, 25000),(8, 25001, 30000);案例
eg:查詢員工的姓名、年齡、職位、部門信息(隱式內連接)
# 連接條件:emp.dept_id = dept.id select emp.name, age, job, dept.name from emp ,dept where emp.dept_id = dept.id;eg:查詢年齡小于30歲的員工的姓名、年齡、職位、部門信息(顯示內連接)
# 連接條件:emp.dept_id = dept.id select e.name, e.age, e.job, d.name from emp e inner join dept d on e.dept_id = d.id where e.age < 30 ;eg:查詢擁有員工的部門ID、部門名稱
# 連接條件:emp.dept_id = dept.id select distinct d.id, d.name from emp e, dept d where e.dept_id = d.id;>
eg:查詢所有年齡大于40歲的員工,及其歸屬的部門名稱;如果員工沒有分配部門,也需要顯示出來
# 連接條件:emp.dept_id = dept.id # 外連接 select e.*, d.name from emp e left join dept d on e.dept_id = d.id where age > 40;eg:查詢所有員工的工資等級
# 連接條件:emp.salary >= salgrade.losal and emp.salary <= salgrade.hisal select e.*, s.grade from emp e, salgrade s where e.salary >= s.losal and e.salary <= s.hisal;eg:查詢研發部所有員工的信息工資等級
-- 查詢 研發部 所有員工的信息及工資等級 -- emp dept salgrade -- 鏈接條件:emp.dept_id = dept.id, emp.salary > losal and emp.salary < hisal select e.*, d.name, s.grade from emp e,dept d,salgrade s where e.dept_id = d.idand e.salary > s.losaland e.salary < s.hisaland d.name = '研發部';eg:查詢研發部員工的平均工資
-- 查詢 研發部 員工的平均工資 -- 鏈接條件: emp.dept_id = dept.id; select avg(e.salary) from emp e, dept d where e.dept_id = d.id and d.name = '研發部';eg:查詢工資比滅絕高的員工信息
-- 查詢工資比 滅絕 高的員工信息 -- 查詢 滅絕 的薪資 select salary from emp where name = '滅絕'; -- 查詢比 滅絕 工資高的員工信息 select * from emp where salary > (select salary from emp where name = '滅絕');eg:查詢比平均薪資高的員工
-- 查詢比平均薪資高的員工信息 -- 查詢平均工資 select avg(salary) from emp; -- 查詢比平均薪資高的員工 select *,(select avg(salary) from emp) '平均工資' from emp where salary > (select avg(salary) from emp);eg:查詢低于本部門平均工資的員工信息
-- 查詢低于本部門平均工資的員工信息 -- 查詢指定部門的平均工資 select avg(salary) from emp e1 where e1.dept_id = 1; select avg(salary) from emp e1 where e1.dept_id = 2; -- 查詢低于本部門的平均工資的員工信息 select e2.*, d.name from emp e2,dept d where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id)and e2.dept_id = d.id;eg:查詢所有的部門信息,并統計部門的員工人數
-- 查詢所有的部門信息,并統計部門的員工人數 -- 鏈接條件:emp.dept_id = dept.id; select *, (select count(*) from emp where emp.dept_id = dept.id) '人數' from dept;eg:查詢所有學生的選課情況,展示出學生名稱,學號,課程名稱
-- 查詢所有學生的選課情況,展示出學生名稱、學號、課程名稱 -- 表 student、course、student_course -- 鏈接條件 : student.id = student_course.studentid , course.id = student_course.courseid select s.*, c.name from student s, course c, student_course sc where s.id = sc.studentid and c.id = sc.courseid;總結
以上是生活随笔為你收集整理的【MySQL】黑马教程MySQL数据库 MySQL基础(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20万奖补|成都两化融合管理贯标项目拟支
- 下一篇: MIPS 架构的 AR9331芯片 编译