SQL
SQL通用語法:
SQL分類:
DDL:
數據庫操作
查詢:
SHOW DATABASES;
創建:
CREATE DATABASE[IF NOT EXISTS] 數據庫名 [DEFAULT CHARSET字符集] [COLLATE 排序規則];
刪除:
DROP DATABASE [IF EXISTS] 數據庫名;
使用:
USE 數據庫名;
DDL - 表操作 - 查詢:
查詢當前數據庫所有表
SHOW TABLES;
查詢表結構:
DESC 表名
查詢指定表的建表語句:
SHOW CREATE TABLE 表名;
DDL - 表操作 - 創建:
DDL - 表操作 - 數據類型
create table emp(-> id int comment '編號',-> workno varchar(10) comment '員工工號',-> name varchar(10) comment '姓名',-> gender char(1) comment '性別',-> age tinyint unsigned comment '年齡',-> idcard char(18) comment '身份證號',-> entrydate date comment '入職時間'-> ) comment '員工表';
DDL - 表操作 - 修改
添加字段:
ALTER TABLE 表名 ADD 字段名 類型(長度)[COMMENT 注釋][約束];
修改數據類型:
ALTER TABLE MODIFY 字段名 新數據類型(長度)
修改字段名和字段類型
ALTER TABLE 表名 CHANGE 舊字段名 新字段名 類型(長度)[COMMENT 注釋]
刪除字段:
ALTER 表名 DROP 字段名;
修改表名:
ALTER TABLE 表名 RENAME TO 新表名;
DDL - 表操作 - 刪除
刪除表
DROP TABLE [IF EXISTS] 表名
刪除指定表,并重新創建該表
TRUNCATE TABLE 表名;
相當于清空
DML:
DML - 添加數據
給指定字段添加數據
INSERT INTO 表名(字段1,字段2)VALUES(值1,值2);
給全部字段添加數據
INSERT INTO 表名 VALUES(值1,值2);
批量添加數據
INSERT INTO 表名(字段1,字段2) VALUES (值1,值2),(值1,值2),(值1,值2);
INSERT INTO 表名 VALUES(值1,值2),(值1,值2);
注:
- 插入數據時,指定的字段順序需要與值的順序是一一對應的
- 字符串和日期數據應該在包含在引號中
- 插入的數據應該在范圍內
DML - 修改數據
UPDATE 表名 SET 字段名1 = 值1,字段名2 = 值2,[WHERE ...]
注:修改語句的條件可以有,也可以沒有,如果么有條件,則會修改整張表的所有數據。
DML - 刪除數據
DELETE FROM 表名 [WHERE 條件];
DQL:
語法:
DQL - 基本查詢:
查詢多個字段
SELECT 字段1,字段2,字段3 ... FROM 表名;
SELECT * FROM 表名
設置別名
SELECT 字段1 [AS 別名1],字段2 [AS 別名2]... FROM 表名;
去除重復記錄
SELECT DISTINCT 字段列表 FROM 表名;
DQL - 條件查詢:
語法:
SELECT 字段列表 FROM 表名 WHERE 條件列表;
-- --------------------------------------------------- > 查詢需求 <------------------------------------------------ 基本查詢
-- 1. 查詢指定字段 name workno age 返回
select name,workno,age from emp;-- 2. 查詢所有字段返回
select * from emp;-- 3. 查詢所有員工的工作地址,起別名
select workaddress as '工作地址' from emp;-- 4. 查詢公司員工的上班地址(不重復)
select distinct workaddress '工作地址' from emp;-- 條件查詢
-- A. 查詢年齡等于 88 的員工
select * from emp where age = 88;-- B. 查詢年齡小于 20 的員工信息
select * from emp where age <= 20;-- D. 查詢沒有身份證號的員工信息
select * from emp where idcard is null;-- E. 查詢有身份證號的員工信息
select * from emp where idcard is not null;-- F. 查詢年齡不等于 88 的員工信息
select * from emp where age <> 88;-- G. 查詢年齡在15歲(包含) 到 20歲(包含)之間的員工信息
select * from emp where age >=15 && age<=20;
select * from emp where age >=15 AND age<=20;
select * from emp where age between 15 and 20; -- between 跟最小值-- H. 查詢性別為 女 且年齡小于 25歲的員工信息
select * from emp where gender = '女' and age <25;-- I. 查詢年齡等于18 或 20 或 40 的員工信息
select * from emp where age = 18 || age = 20 || age = 40 ;
select * from emp where age in(18,20,40);-- J. 查詢姓名為兩個字的員工信息 _ %
select * from emp where name like '__';-- K. 查詢身份證號最后一位是X的員工信息
select * from emp where idcard like '%X';
聚合函數:
分組查詢:
排序查詢:
分頁查詢:
DQL -聚合函數:
常見聚合函數
語法:
SELECT 聚合函數(字段列表) FROM 表名;
注:null值不參與所有聚合函數的運算
-- ------------------------------------> 聚合函數--
-- A. 統計該企業員工數量
select count(*) from emp;
select count(idcard) from emp;-- B. 統計該企業員工的平均年齡
select avg(age) from emp;-- C. 統計該企業員工的最大年齡
select max(age) from emp;-- D. 統計該企業員工的最小年齡
select min(age) from emp;-- E. 統計西安地區員工的年齡之和
select sum(age) from emp where workaddress = '西安';
DQL -分組函數:
SELECT 字段列表 FROM 表名 [WHERE 條件] GROUP BY 分組字段名 [HAVING 分組后過濾條件];
where 和 having區別
- 執行時機不同:where是分組之前進行過濾,不滿足where條件,不參與分組;而having是分組之后對結果進行過濾。
- 判斷條件不同:where不能對聚合函數進行判斷,而having可以
-- 分組查詢
-- A. 根據性別分組 , 統計男性員工 和 女性員工的數量
select gender,count(*) from emp group by gender ;
-- B. 根據性別分組 , 統計男性員工 和 女性員工的平均年齡
select gender,avg(age) from emp group by gender;
-- C. 查詢年齡小于45的員工 , 并根據工作地址分組 , 獲取員工數量大于等于3的工作地址
select workaddress,count(*) address_count from emp where age <45 group by workaddress having address_count >= 3;
-- D. 統計各個工作地址上班的男性及女性員工的數量
select workaddress,gender,count(*) '數量' from emp group by gender, workaddress;
- 執行順序:where > 聚合函數 > having
- 分組之后,查詢字段一般為聚合函數和分組字段,查詢其他字段無任何意義。
DQL -排序查詢:
語法:
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2;
排序方式:
- ASC :升序
- DESC:降序
-- 排序查詢
-- A.根據年齡對公司的員工進行升序排序
select * from emp order by age asc;
select * from emp order by age desc ;
-- B. 根據入職時間, 對員工進行降序排序
select * from emp order by entrydate desc;
-- C. 根據年齡對公司的員工進行升序排序 , 年齡相同 , 再按照入職時間進行降序排序
select * from emp order by age asc, entrydate desc;
注意:如果是多字段排序,當第一個字段值相同時,才會根據第二個字段進行排序。
DQL -分頁查詢:
語法:
SELECT 字段列表 FROM 表名 LIMIT 起始索引,查詢記錄數;
-- 分頁查詢
-- A. 查詢第1頁員工數據, 每頁展示10條記錄
select * from emp limit 10;
-- B. 查詢第2頁員工數據, 每頁展示10條記錄 --------> (頁碼-1)*頁展示記錄數
select * from emp limit 10,10;
練習:
-- 2.6.8 案例
-- 1). 查詢年齡為20,21,22,23歲的員工信息。
select * from emp where gender = '女' and age in(20,21,22,23);-- 2). 查詢性別為 男 ,并且年齡在 20-40 歲(含)以內的姓名為三個字的員工。
select * from emp where gender = '男' and (age between 20 and 40) and name like '___';-- 3). 統計員工表中, 年齡小于60歲的 , 男性員工和女性員工的人數。
select gender,count(*) from emp where age < 60 group by gender;-- 4). 查詢所有年齡小于等于35歲員工的姓名和年齡,并對查詢結果按年齡升序排序,如果年齡相同按入職時間降序排序。
select name '姓名',age '年齡' from emp where age <= 35 order by age asc,entrydate desc ;-- 5). 查詢性別為男,且年齡在20-40 歲(含)以內的前5個員工信息,對查詢的結果按年齡升序排序,年齡相同按入職時間升序排序。
select * from emp where gender = '男' and (age between 20 and 40) order by age asc,entrydate desc limit 5;
DQL -執行順序:
DCL:
DCL - 管理用戶:
1) 查詢用戶
select * from mysql.user; 1
2). 創建用戶
CREATE USER '用戶名'@'主機名' IDENTIFIED BY '密碼'; 1
3). 修改用戶密碼
ALTER USER '用戶名'@'主機名' IDENTIFIED WITH mysql_native_password BY '新密碼' ; 1
4). 刪除用戶
DROP USER '用戶名'@'主機名' ;
注意事項:
? 在MySQL中需要通過用戶名@主機名的方式,來唯一標識一個用戶。
DCL- 權限控制
函數
字符串函數
-- ---------------------------- 函數 ------------------------------- --
-- conccat
select concat('Hello','Mysql');-- lower
select lower('HEllo');-- upper
select upper('hello');-- Lpad
select lpad('01',5,'-');-- rpad
select rpad('01',5,'-');-- trim
select trim(' Hello MySql ');-- substring
select substring('Hello MySQL',1,5);update emp set workno = lpad(workno,5,'0');
數值函數
常見的數值函數如下:
-- 數值函數
-- ceil
select ceil(1.5);-- floor
select floor(1.1);-- mod
select mod(3,4);-- rand
select rand();-- round
select round(2.345,2);-- 生成六位隨機驗證碼
select lpad(round(rand() * 1000000,0),6,'0') ;
日期函數
-- 日期函數
-- curdate
select curdate();
-- curtime
select curtime();
-- now
select now();-- Year,MONTH,DAY
select YEAR(NOW());
SELECT MONTH(NOW());
SELECT DAY(NOW());-- DATE_ADD
SELECT DATE_ADD(NOW(),INTERVAL 70 DAY );-- DATEDIFF(第一個時間減去第二個時間)
SELECT DATEDIFF('2021-12-01','2021-12-21');select name,datediff(curdate(),entrydate) as 'entrydays' from emp order by entrydays desc ;
流程函數
-- 流程控制函數
-- -- IF
select if(true,'ok','Error');
select if(false,'ok','Error');-- IFNULL
select ifnull('ok','default'); -- ok
select ifnull(null,'default'); -- default-- CASE
SELECTNAME,(CASE workaddress WHEN '北京' then '一線城市' when '上海' then '一線城市' else '二線城市' end) as '工作地址'
FROM emp;
-- 案例
selectid,name,(case when math >=85 then '優秀' when math >=60 then '及格' else '不及格' end) '數學' ,(case when english >=85 then '優秀' when english >=60 then '及格' else '不及格' end) '英語' ,(case when chinese >=85 then '優秀' when chinese >=60 then '及格' else '不及格' end) '語文'from score;
約束
概述:
案例:
根據需求,完成表結構的創建
create table user (id int primary key auto_increment comment '主鍵',name varchar(10) not null unique comment '姓名',age int check ( age> 0 && age <= 120 ) comment '年齡',status char(1) default '1' comment '狀態',gender char(1) comment '性別'
) comment '用戶表';-- 插入數據insert into user (name,age,status,gender) values ('程夢雨',19,'1','女'),('Messi',20,'1','男');
外鍵約束:
外鍵用來讓兩張表的數據之間建立連接,從而保證數據的一致性和完整性。
語法:
添加外鍵:
CREATE TABLE 表名 (字段名 數據類型,...[CONSTRAINT] [外鍵名稱] FOREIGN KEY (外鍵字段名) REFERENCES 主表 (主表列名)
);
ALTER TABLE 表名 ADD CONSTRAINT 外鍵名稱 FOREIGN KEY(外鍵字段名) REFERENCE 主表(主表列名);
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) references dept(id);
刪除外鍵:
ALTER TABLE 表名 DROP FOREIGN KEY 外鍵名稱;
-- 刪除外鍵
ALTER TABLE emp DROP FOREIGN KEY fk_emp_dept_id;
刪除/更新行為:
語法:
ALTER TABLE 表名 ADD CONSTRAINT 外鍵名稱 FOREIGN KEY (外鍵字段名) REFERENCES 主表名 ON UPDATE CASCADE ON DELETE CASCADE;
-- 外鍵的刪除和更新行為
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept(id) ON UPDATE CASCADE ON DELETE CASCADE ;ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES dept(id) ON UPDATE SET NULL ON DELETE SET NULL ;
多表查詢:
概述:指從多張表中查詢數據
笛卡爾積:兩個集合A和集合B的所有組合情況。(在多表查詢時,需要消除無效的笛卡爾積)
-- 多表查詢
select * from emp , dept where emp.dept_id = dept.id;
多表查詢分類:
連接查詢 - 內連接:
-- 內連接
-- 1.查詢每一個員工的姓名及關聯的部門的名稱(隱式內連接實現)
select emp.name,dept.name from emp,dept where emp.dept_id = dept.id;-- 2. 查詢每一個員工的姓名,及關聯的部門的名稱(顯式內連接實現)
select emp.name , dept.name from emp inner join dept on emp.dept_id = dept.id;
連接查詢 - 外連接:
-- 外連接
-- 1. 查詢emp標的所有數據,和對應的部門信息(左外)
select emp.* ,d.name from emp left join dept d on d.id = emp.dept_id;-- 2. 查詢dept表的所有數據,和相對應的員工信息(右外)
select d.* , emp.* from emp right join dept d on d.id = emp.dept_id;
連接查詢 - 子連接:
-- 子鏈接
-- 1. 查詢員工及其領導的名字
select e.name , b.name from emp e , emp b where e.managerid = b.id;-- 2. 查詢員工及其領導的名字 ,如果沒有領導,也要查詢出來
select a.name '員工', b.name '領導' from emp a left join emp b on a.managerid = b.id;
聯合查詢:
-- union all , union
-- 1. 將薪資低于 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;
子查詢:
標量子查詢:(返回單個值)
-- 標量子查詢
-- 1. 查詢“銷售部”的所有員工信息
select * from emp where dept_id = (select id from dept where name = '銷售部');-- 2. 查詢“房東白”入職之后的員工信息
select entrydate from emp where name = '方東白';select * from emp where entrydate > (select entrydate from emp where name = '方東白');
列子查詢:(返回的結果是一列)
-- 列子查詢
-- 1. 查詢銷售部和市場部的所有員工信息
select * from emp where dept_id in (select dept.id from dept where name = '市場部' or name = '銷售部');-- 2. 查詢比財務部所有人員工資都高的員工信息
select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '財務部'));-- 3. 查詢比研發部其中任意一人工資高的員工信息
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 = '研發部'));
行子查詢:
-- 行子查詢
-- 1. 查詢與“張無忌”工資和直屬領導相同的信息
select salary , managerid from emp where name = '張無忌';select * from emp where (salary,managerid) = (select salary , managerid from emp where name = '張無忌');
表子查詢:(返回多行多列)
-- 表子查詢
-- 1. 查詢路杖客,宋遠橋的職位和薪資相同的員工信息
select salary , job from emp where name = '鹿杖客' or name = '宋遠橋';select * from emp where (job,salary) in (select job, salary from emp where name = '鹿杖客' or name = '宋遠橋');-- 2.查詢入職日期是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;
練習:
-- 1. 查詢員工的姓名、年齡、職位、部門信息 (隱式內連接)
select e.name, e.age,e.job,d.name from emp e join dept d on d.id = e.dept_id;-- 2. 查詢年齡小于30歲的員工的姓名、年齡、職位、部門信息(顯式內連接)
select e.name,e.age,e.job,d.name from emp e join dept d on d.id = e.dept_id where e.age < 30;-- 3. 查詢擁有員工的部門ID、部門名稱
select distinct d.id,d.name from emp e,dept d where e.dept_id = d.id;-- 4. 查詢所有年齡大于40歲的員工, 及其歸屬的部門名稱; 如果員工沒有分配部門, 也需要展示出來-- 外連接select e.*,d.name from emp e left join dept d on d.id = e.dept_id where e.age > 40;-- 5. 查詢所有員工的工資等級-- 表:emp salgrade-- 連接條件:emp.salary >= salgrade.losal and emp.salary <= salgrade.hisalselect e.* ,s.grade from emp e ,salgrade s where e.salary >= s.losal and e.salary <= s.hisal;-- 6. 查詢 "研發部" 所有員工的信息及 工資等級
select e.*, s.grade
from emp e,salgrade s
where e.dept_id = (select dept.id from dept where dept.name = '研發部')and (e.salary between s.losal and s.hisal);-- 7. 查詢 "研發部" 員工的平均工資
select avg( e.salary) '平均工資' from emp e, dept d where e.dept_id = d.id and d.name = '研發部';-- 8. 查詢工資比 "滅絕" 高的員工信息
select * from emp where salary > (select salary from emp where name = '滅絕');-- 9. 查詢比平均薪資高的員工信息
select avg(salary) from emp;
select * from emp where salary > (select avg(salary) from emp);-- 10. 查詢低于本部門平均工資的員工信息
select avg(e1.salary) from emp e1 where e1.dept_id = 1;select *,(select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id) '平均工資' from emp e2 where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id);-- 11. 查詢所有的部門信息, 并統計部門的員工人數
select d.id ,d.name, (select count(*) from emp e where e.dept_id = d.id) '人數' from dept d;select count(*) from emp where dept_id = 1;-- 12. 查詢所有學生的選課情況, 展示出學生名稱, 學號, 課程名稱
總結:
事務:
事務簡介:
select @@autocommit;set @@autocommit = 0; -- 設置手動提交
-- 轉賬操作
-- 1. 查詢張三賬戶余額
select * from account where name = '張三';-- 2. 將張三的賬戶余額 -1000
update account set money = money - 1000 where name = '張三';程序執行報錯...-- 3. 將李四賬戶余額+1000
update account set money = money + 1000 where name = '李四';-- 提交事務
commit;-- 回滾事務
rollback;
-- ---------------- 方式二 ----------------
begin ;
-- 轉賬操作
-- 1. 查詢張三賬戶余額
select * from account where name = '張三';-- 2. 將張三的賬戶余額 -1000
update account set money = money - 1000 where name = '張三';程序執行報錯...-- 3. 將李四賬戶余額+1000
update account set money = money + 1000 where name = '李四';-- 提交事務
commit ;-- 回滾事務
rollback ;
事務的四大特性:
并發事務問題:
并發事務的隔離級別:
orcal的默認是 Read committted
事務隔離級別越高,數據效率越低