mysql資料庫(DQL,DML,DDL)總結
sql
文章目錄
sql_english
show:顯示
database:資料庫
use:使用
tables:表
from:從
create:建立
desc:【describe】描述
select:選擇
where:哪裡
as:作為
VERSION:版本
distinct:不同的
escape:逃跑
between:之間
order by:排序依據
ASC:【ascent】升序
DESC:【desc】降序
concat:使連線
length:【函式】長度
upper:上面的 - 大小寫轉換
lower:下面的 - 大小寫轉換
substr/substring:擷取子串
instr:子字串檢索函式
trim:除去
lpad:【left padding】左填充
rpad:【right padding】右填充
round:四捨五入
ceil:向上取整,返回>=該引數的最小整數
floor:向下取整,返回<=該引數的最大整數
truncate:截斷
now():返回當前系統時間和日期
curdate():返回當前系統日期,不包含時間
group by:分組依據
having:有
last:最後的
first:第一、首先
email:郵箱
employees:員工
salary:薪水、工資
department:部門
commission_pct:獎金百分比
job_id:職位編號
hire_date:入職日期、聘用日期
Year:年
month:月
day:日
hour:時
minute:分
second:秒
location_id:位置代號
sql的常見命令
1.檢視當前所有的資料庫
Show databases;
2.開啟指定的庫
use 庫名;
3.檢視當前庫的所有表
show tables;
4.檢視其它庫的所有表
show tables from 庫名;
5.建立表
create table 表名(列名列型別,列名列型別, ... );
6.查看錶結構
desc 表名;
7.檢視伺服器的版本
i.登入到mysq1服務端 -> select version();
ii.沒有登入到mysq1服務端 -> sql --version | sql --V
sql的語法規範
1.不區分大小寫,但建議關鍵字大寫,表名、列名小寫
2.每條命令最好用分號結尾
3.每條命令根據需要,可以進行縮排或換行
4.註釋
i.【#註釋文字;】 | 【-- 註釋文字】
ii./* 多行註釋 */
DQL
進階一:基礎查詢
select 查詢列表 from 表名;
查詢列表可以是:表中的欄位、常量、表示式、函式;查詢的結果是一個虛擬的表格
1.1查詢表中的單個欄位
select last_name from employees;
1.2查詢表中的多個欄位
select last_name,salary,email from employees;
1.3查詢表中所有欄位
select * from employees;
1.4查詢常量值
select 100; | select ‘john’;
1.5查詢表示式
select 100*2;
1.6查詢函式
select VERSION();
1.7起別名
作用:便於理解; 如果要查詢的欄位有重名的情況,使用別名可以區分開來
-
select 100*2 as 結果; select last_name as 姓,first_name as 名 from employees;
-
select last_name 姓,first_name 名 from employees;
案例:查詢salary,需求的顯示結果為out put
select salary as "out put" from employees;
1.8去重
查詢員工表中涉及到的所有的部門編號
select distinct department_id from employees;
1.9“+”號的作用
查詢員工名和姓連按成-一個欄位,並顯示為姓名
select last_name + first_name as 姓名 from employees; //沒有作用
java中的 + :i.運算子 ii.連線符
sql中的 + :運算子
select 10+10; //20
select '10'+10; //20
select 'abc'+10; //10
select null+10; //null
1.10comcat - 實現連線
select concat(last_name,first_name) from employees;
1.11ifnull - 判斷值是否為null
作用:避免 - 【 select null+10; //null 】
SELECT
CONCAT(`first_name`,",",`last_name`,",",`email`,",",IFNULL(`commission_pct`,0),",",`manager_id`)AS out_put
FROM
employees;
進階二:條件查詢
2.1語法
select 查詢列表 from 表名 where 篩選條件;
2.2分類
2.2.1按條件表示式篩選
條件運算子:> < = =! <> >= <=
1:查詢工資>12000的員工資訊
select * from employees where salary>12000;
2:查詢部門編號不等於90號的員工名和部門編號
select last_name,departement_id from employees where departement_id<>90;
2.2.2按邏輯表示式篩選
邏輯運算子:&& || ! and or not
1.查詢工資z在10000到20000之間的員工名、工資以及獎金
SELECT
last_name,
`salary`,
`commission_pct`
FROM
`employees`
WHERE
`salary`>=10000
AND
`salary`<=20000;
2.查詢部門編號不是在90到110之間,或者工資商於15000的員工資訊
SELECT
*
FROM
employees
WHERE
`department_id`<90 OR `department_id`>110 OR salary>15000;
2.2.3模糊查詢
like between and in is null | is not null
i:萬用字元
%:任意多個字元,包含0個字元
_ :任意單個字元
ii:轉義符
/
關鍵字指定轉義符:’ %' escape ' ’;
like
一般和萬用字元搭配使用
-
1.查詢員工名中包含字元a的員工資訊 SELECT * FROM employees WHERE last_name LIKE '%a%'; 2.查詢員工名中第4個字元為 a,第6個字元為 r的員工名和工資 select last_name, salary from employees where last_name like '___a__r%'; 3.查詢員工名中第二個字元為_的員工名 SELECT * FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';
between and
作用:可提高語句的簡潔度,包含邊界值,不能顛倒。
-
1.查詢員工編號在100到120之間的員工資訊 select * from employees where employee_id between 100 and 120; 【等價於: employee_id >=100 and employee_id <= 120;】
in
含義:判斷某欄位的值是否屬於in列表中的某一項
特點:1.使用 in提高語句簡潔度 2.in列表的值型別必須-致或相容
-
查詢員工的工種編號是IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號 SELECT * FROM employees WHERE job_id IN ('IT_PROG','AD_VP','AD_PRES');
is null | is not null
-
查詢沒有獎金的員工名和獎金率 SELECT last_name, commission_pct FROM employees WHERE commission_pct IS NULL; 安全等於 : <=> SELECT last_name, salary FROM employees WHERE salary <=> 12000;
進階三:排序查詢
3.1語法
select 查詢列表 from 表 【where 篩選條件】 order by 排序列表 asc | desc;
3.2特點
1、asc代表的是升序,desc代表的是降序如果不寫,預設是升序
2、order by子句中可以支援單個欄位、多個欄位、表示式、函式、別名
3、order by子句一般是放在查詢語句的最後面,limit子句除外
3.3案例
案例1.查詢員工資訊,要求工資從高到低排序
SELECT * FROM employees ORDER BY salary DESC; //降序
SELECT * FROM employees ORDER BY salary asc; //升序 | 預設升序
案例2.查詢部門編號>=90的員工資訊,按入職時間的先後進行排序
select *
from employees
where department_id >= 90
order by hiredate;
案例3:按年薪的高低顯示員工的資訊和年薪[按表示式排序]
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY 年薪;
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) desc;
案例4.按姓名的長度顯示員工的姓名和工資[按函式排序]
select length(last_name) as 位元組長度,last_name,salary
from employees
order by 位元組長度 | length(last_name);
案例5.查詢員工資訊,要求先按工資排序,再按員工編號排序[按多個欄位排序]
SELECT employee_id,salary
FROM employees
ORDER BY salary,employee_id ASC;
進階四:常見函式
4.1概念
類似於java的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名
4.2好處
1、隱藏了實現細節 2、提高程式碼的重用性
4.3呼叫
select 函式名(實參列表) 【from 表】;
4.4特點
1.叫什麼(函式名) 2.幹什麼(函式功能)
4.5分類
4.5.1單行函式 - concat,length,ifnull等
a.字元函式
-
//length - 獲取引數值的位元組個數 select length('john'); //concat - 拼接字串 select concat(last_name,first_name) as 姓名 from employees; //upper、lower - 大小寫轉換 select upper('hello'); //HELLO select lower('HTLLO'); //hello 示例:將姓變大寫,名變小寫,然後拼接 select concat(upper(last_name),lower(first_name)) from employees; //substr、substring - 索引從1開始 select substr('我的名字是王家航',6) out_put; //'王家航' <--擷取從指定索引處指定字元長度的字元--> select substr('我的名字是王家航',3,2) as out_put; //'名字' 案例:姓名中首字元大寫,其他字元小寫然後用拼接,顯示出來 select concat(upper(substr(last_name,1,1)),lower(substr(last_name,2))) from employees; //instr - 返回子串第一次出現的素引,如果找不到返回0 select instr('阿珍愛上了阿強','阿強') as out_put; //trim select trim(' 王家航 ') as out_put; //王家航 select trim('a' from 'aaaaaaaaaaaa王家aaaa航aaaaa') as out_put; //王家aaaa航 //lpad - 用指定的字元實現左填充指定長度 select lpad('王家航',10,'*') as out_put; //rpad - 用指定的字元實現右填充指定長度 select rpad('王家航',10,'*') as out_put; //replace - 替換 select replace('my name is 王王王','王','忘') as out_put; //my name is 忘忘忘
b.字元函式
-
//round - 四捨五入 select round(1.65); //2 select round(1.565,2) //1.57 - 小數點後保留兩位 //ceil - 向上取整,返回>=該引數的最小整數 select ceil(1.0003); //2 //floor - 向下取整,返回<=該引數的最大整數 select floor(9.55); //9 //truncate - 截斷:小數點後保留 x 位 select truncate(1.2222225,2); //1.22 //mod - 取餘 select mod(10,3); //1 = 10%3
c.日期函式
-
//now - 返回當前系統時間和日期 select now(); //curdate - 返回當前系統日期,不包含時間 select curdate(); //curtime - 返回當前時間,不包含日期 select curtime(); //可以獲取指定的部分,年、月、日、小時、分鐘、秒 select yrar(now()) as 年; Year:年 month:月 day:日 hour:時 minute:分 second:秒 //str_to_date - 將字元通過指定的格式轉換成日期 STR_TO_DATE('9-13-1999','%m- %d- %Y') 1999-09-13 //date_format;將日期轉換成字元 DATE FORMAT(2018/6/6','%Y年%m月%d日) 2018年06月06日 select date_format(now(),'%y年%m月%d日') as out_put; 查詢有獎金的員工名和入職日期(xx月/xx日 xx年) SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年'),commission_pct FROM employees WHERE commission_pct IS NOT NULL;
d.其他函式
-
SELECT VERSION(); SELECT DATABASE(); SELECT USER();
e.流程控制函式
if函式 - if else 的效果
-
select if(10>5,'大','小'); //大 //查詢是否有獎金 SELECT last_name,commission_pct, IF(commission_pct IS NULL,'沒有獎金奧 垃圾','有獎金,恭喜') AS out_put FROM employees;
case函式_使用一 - switch case 的效果
-
case 要判斷的欄位或表示式 when 常量1 then 要顯示的值1或語句1; when 常量2 then 要顯示的值2或語句2; ... else 要顯示的值n或語句n; end SELECT salary AS 原始工資,department_id, CASE department_id WHEN 30 THEN salary*1.1 WHEN 40 THEN salary*1.2 WHEN 50 THEN salary*1.3 ELSE salary END AS 新工資 FROM employees;
case 函式的使用二 - 類似於多重if
-
case when 條件1 then 要顯示的值1或語句1 when 條件2 then 要顯示的值2或語句2 else 要顯示的值n或語句n end SELECT salary, CASE WHEN salary>20000 THEN 'A' WHEN salary>15000 THEN 'B' WHEN salary>10000 THEN 'C' ELSE 'D' END AS 工資級別 FROM employees ORDER BY salary DESC;
4.5.2分組函式
功能:用作統計使用,又稱為聚合函式或統計函式或組函式
分類:sum求和、avg平均值、max最大值、min最小值、count計算個數
特點:1.sum、avg-般用於處理數值型 ,max、min、count可以處理任何型別
2.以上分組函式都忽略nu11值
3.可以和distinct搭配實現去重的運算
4.count 函式的單獨介紹 - 一般使用count(*)用作統計行數
5.和分組函式一同查詢的欄位要求是group by後的欄位
簡單使用
-
select sum(salary) from employees; select avg(salary) from employees; select max(salary) from employees; select min(salary) from employees; select count(salary) from employees; //和distinct搭配 select sum(distinct salary),sum(salary) from employees; select concat(*) from employees; //查詢行數
進階五:分組查詢
5.1語法
select 分組函式,列(要求出現在group by的後面)
from
【where 篩選條件】
group by 分組的列表
【group by 字句】
#查詢每個工種的最高工資
select job_id,max(salary)
from employees
group by job_id;
#查詢郵箱中包含a字元的,每個部門的平均工資
SELECT email,department_id,ROUND(AVG(salary),2) AS 平均工資
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
#查詢有獎金的每個領導手下員工的最高工資
select max(salary),manager_id
from employees
where commission_pct Is NOT NULL
group by manager_id;
#新增複雜的篩選條件
#查詢哪個部門的員工個數>2
SELECT COUNT(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2;
#查詢每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
select max(salary) as 最高工資,job_id,commission_pct
from employees
where commission_pct is not null
group by job_id
having 最高工資 > 12000;
#查詢領導編號>102的每個領導手下的最低工資>5000的領導編號是哪個,以及其最低工資
SELECT manager_id,MIN(salary) AS 最低工資
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING 最低工資>5000;
5.2總結
1、分組查詢中的篩選條件分為兩類
資料來源 位置 關鍵字 分組前篩選 原始表 group by子句的前面 where 分組後篩選 分組後的結果集 group by子句的後面 having i:分組函式做條件肯定是放在having子句中 ii:能用分組前篩選的,就優先考慮使用分組前篩選
2、group by子句支援單個欄位分組,多個欄位分組(多個欄位之間用逗號隔開沒有順序要求),表示式或函式(用得較少)
3、也可以新增排序(排序放在整個)
#按表示式或函式分組
#案例:按員工姓名的長度分組,查詢每一組的員工個數,篩選員工姓名長度個>5的長度的個數
SELECT COUNT(*),LENGTH(last_name)
FROM employees
GROUP BY LENGTH(last_name)
HAVING COUNT(*) > 5;
#按多個欄位分組
#查詢每個部門每個工種的員工的平均工資
select avg(salary) a,department_id,job_id
from employees
group by department_id,job_id;
#新增排序
#查詢每個部門每個工種的員工的平均工資,並且按平均工資的高低顯示
select avg(salary) a,department_id,job_id
from employees
group by department_id,job_id
order by a;
5.3課後習題
-
#查詢各job_id的員工工資的最大值,最小值,平均值,總和,並按job__id升序 SELECT job_id,MAX(salary) AS 最大值,MIN(salary) AS 最小值,AVG(salary) AS 平均值,SUM(salary) AS 和 FROM employees GROUP BY job_id ORDER BY 和 ASC; #查詢員工最高工資和最低工資的差距(DIFFERENCE) SELECT MAX(salary)-MIN(salary) AS difference FROM employees; #查詢各個管理者手下員工的最低工資,其中最低工資不能低於6000,沒有管理者的員工不計算在內 SELECT MIN(salary),manager_id FROM employees WHERE manager_id IS NOT NULL GROUP BY manager_id HAVING MIN(salary) >= 6000; #查詢所有部門的編號,員工數量和工資平均值,並按平均工資降序 SELECT department_id,COUNT(*),ROUND(AVG(salary),2) AS 平均工資 FROM employees GROUP BY department_id ORDER BY 平均工資 DESC; #選擇具有各個job_id的員工人數 SELECT job_id,COUNT(*) FROM employees GROUP BY job_id;
進階六:連線查詢
6.1含義
又稱多表查詢,當查詢的欄位來自於多個表時,就會用到連線查詢
6.2笛卡爾乘積現象
表現:表1有m行,表2有n行,結果=m*n行
發生原因:沒有有效的連線條件
如何避免:新增有效的連按條件
語法:select name,boyName from beauty,boys;
-
SELECT NAME,boyname FROM beauty,boys WHERE beauty.`boyfriend_id` = boys.id;
6.3分類
6.3.1按年代分類
a.sql92標準
僅僅支援內連線
語法
select 查詢列表
from 表1,表2
where 連線條件
and 篩選條件;
b.sql99標準
支援內連線+外連線(左外和右外)+交叉連線
語法
select 查詢列表
from 表1 別名【連線型別】
join 表2別名
on 連線條件
【where 篩選條件】
【group by 分組】
【having 篩選條件】
【order by 排序列表】
新增排序、分組、篩選
inner可以省略
篩選條件放在where後面,連按條件放在on後面,提高分高性,便於閱讀
/*
連線型別:
內連線:inner
左外:left 【outer】
右外:right 【outer】
全外:full 【outer】
交叉:cross 【outer】
*/
6.3.2按功能分類
a.內連線
等值連線
- sql92寫法
-
#案例: #等值連線 #案例1:查詢女神名和對應的男神名 SELECT name,boyname FROM beauty,boys WHERE beauty.boyfriend_id = boys.id; #案例2:查詢員工名和對應的部門名 SELECT last_name,department_name FROM employees,departments WHERE employees.department_id = departments.department_id; #為表起別名 - 提高語句的簡潔度,區分多個重名的欄位 #注意:如果為表起了別名,則查詢的欄位就不能使用原來的表名去限定 #查詢員工名、工種號、工種名 SELECT last_name,e.job_id,job_title FROM employees AS e,jobs AS j WHERE e.`job_id` = j.`job_id`; #查詢城市名中第二個字元為o的部門名和城市名 select department_name,city from departments d,locations l where d.location_id = l.`location_id` and city like '_o%'; #查詢每個城市的部門個數 SELECT city,COUNT(*) AS 部門個數 FROM departments d,locations l WHERE d.`location_id` = l.`location_id` GROUP BY city; #查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資 SELECT MIN(salary) AS 最低工資,d.manager_id,department_name FROM employees e,departments d WHERE e.`department_id` = d.`department_id` AND commission_pct IS NOT NULL GROUP BY department_name,d.manager_id; #查詢每個工種的工種名和員工的個數,並且按員工個數降序 SELECT COUNT(*) 個數,job_title FROM employees e,jobs j WHERE e.`job_id` = j.`job_id` GROUP BY job_title ORDER BY 個數 DESC; #查詢員工名、部門名和所在的城市 SELECT last_name,department_name,city FROM employees e,departments d,locations l WHERE e.`department_id` = d.`department_id` AND d.`location_id` = l.`location_id` ORDER BY city;
總結:
1.多表等值連線的結果為多表的交集部分
2.n表連線,至少需要n-1個連線條件
3.多表的順序沒有要求
4.一般需要為表起別名
5.可以搭配前面介紹的所有子句
-
sql99寫法
#查詢員工名、部門名 select last_name,department_name from employees e inner join deparments d on e.deparment_id = d.deparment_id; #查詢部門個數>3的城市名和部門個數,(新增分組+篩選) select city,count(*) 個數 from locations l inner join deparments d on l.location_id = d.location_id group by deparment_id having count(*) >3;
非等值連線
-
sql92
#查詢員工的工資和工資級別 select salary,grade_level from employees e,job_grades j where e.`salary` between j.`lowest_sal` and j.`highest_sal` order by j.`grade_level`;
-
sql99
#查詢員工的工資級別 select salary,grade_level from employees e inner join job_grades j on e.salary between j.lowest_sal and j.highest_sal; #查詢每個工資級別的個數,並且按工資級別排序 SELECT grade_level,COUNT(*) FROM employees e INNER JOIN job_grades j ON e.salary BETWEEN j.lowest_sal AND j.highest_sal GROUP BY grade_level HAVING COUNT(*) > 20 ORDER BY grade_level DESC;
自連線
-
sql92
#詢員工名和上級的名稱 SELECT e.`last_name`,e.`manager_id`,m.`last_name`,m.`manager_id` FROM employees e,employees m WHERE m.`manager_id` = e.`employee_id`;
-
sql99
#詢員工名和上級的名稱 SELECT e.`last_name`,e.`manager_id`,m.`last_name`,m.`manager_id`
b.外連線
特點:
1、外連線的查詢結果為主表中的所有記錄
如果從表中有和它匹配的,則顯示匹配的值
如果從表中沒有和它匹配的,則顯示null
外連線查詢結果=內連線結果+主表中有而從表沒有的記錄
2、左外連線,left join左邊的是主表
右外連線,right join右邊的是主表
3、左外和右外交換兩個表的順序,可以實現同樣的效果
4、全外連線=內連線的結果+表1中有但表2沒有的+表2中有但表1沒有的
左外連線
sql99
-
#查詢哪個部門沒有員工 SELECT d.*,e.employee_id FROM departments d LEFT OUTER JOIN employees e ON d.`department_id` = e.`department_id` WHERE employee_id IS NULL;
右外連線
sql99
-
#查詢哪個部門沒有員工 SELECT d.*,e.employee_id FROM employees e right OUTER JOIN departments d ON d.`department_id` = e.`department_id` WHERE employee_id IS NULL;
c.交叉連線
sql99
-
select b.*,bo.* from beauty b cross join boys bo;
6.4.3總結
功能:sq199支援的較多
可讀性:sq199實現連線條件和篩選條件的分離,可讀性較高
進階七:子查詢
7.1含義
出現在其他語句中的select語句,稱為子查詢或內查詢
外部的查詢語句,稱為主查詢或外查詢
7.2分類
7.2.1按子查詢出現的位置
a.select後面:僅僅支援標量子查詢
#查詢每個部門的員工個數
SELECT d.*,(
SELECT COUNT(*) FROM employees e
WHERE d.`department_id` = e.department_id
) 個數
FROM departments d;
#查詢員工號=102的部門名
select (
select department_name
from departments d
inner join employees e
on d.department_id = e.department_id
where e.employee_id = 102
) 部門名;
b.from後面:支援表子查詢
將子查詢結果充當一張表,要求必須起別名
#查詢每個部門的平均工資的工資等級
SELECT a.*,`grade_level`
FROM (
SELECT department_id,AVG(salary) p
FROM employees e
GROUP BY department_id
) a
INNER JOIN job_grades j
ON a.p BETWEEN j.`lowest_sal` AND j.`highest_sal`;
c.where (or) having後面:標量子查詢 列子查詢 行子查詢(少)
特點
子查詢放在小括號內
子查詢一般放在條件的右側
標量子查詢,一般搭配著單行操作符使用 – < > <= >= <> =
列子查詢,一般搭配多行操作符使用 – in、any/some、all
案例
-
標量子查詢(單行子查詢)
#誰的工資比Able高 #1.查詢Able的工資 select salary from employees where salary = 'Able'; #2.查詢員工的資訊,滿足salary的要求 select * from employees where salary > ( select salary from employees where salary = 'Abel' ); #返回job_id與141號員工相同,salary比143號員工多的員工姓名,job_id和工資 SELECT job_id,salary FROM employees WHERE job_id = ( SELECT job_id FROM employees WHERE employee_id = 141 )AND salary > ( SELECT salary FROM employees WHERE employee_id = 143 ); #返回公司工資最少的員工的last__name,job__id和salary SELECT last_name,job_id,salary FROM employees WHERE salary = ( SELECT MIN(salary) FROM employees ); #查詢最低工資大於50號部門最低工資的部門id和其最低工資 #50號部門最低工資 SELECT MIN(salary) FROM employees WHERE department_id = 50 #每個部門最低工資和部門id SELECT MIN(salary),department_id FROM employees GROUP BY department_id SELECT MIN(salary) m,department_id FROM employees GROUP BY department_id HAVING m>( SELECT MIN(salary) FROM employees WHERE department_id = 50 );
-
列子查詢(多行子查詢)
#返回location id是1400或1700的部門中的所有員工姓名 select last_name from employees where department_id IN (=any)( SELECT department_id FROM departments WHERE location_id IN (1400,1700) ); #返回其它工種中比job_id為'IT_PROG'工種任一工資 低的員工的:工號、姓名、job_id以及salary SELECT employee_id,last_name,job_id,salary FROM employees WHERE job_id <> 'IT_PROG' AND salary < ( SELECT MAX(salary) FROM employees WHERE job_id = 'IT_PROG' ); #返回其它工種中比job_id為'IT_PROG'工種所有工資低的員工的:工號、姓名、job_id以及salary SELECT employee_id,last_name,job_id,salary FROM employees WHERE job_id <> 'IT_PROG' AND salary < all( SELECT salary FROM employees WHERE job_id = 'IT_PROG' );
-
行子查詢(結果集)
#查詢員工編號最小並且工資最高的員工資訊 SELECT MIN(employee_id) FROM employees WHERE salary = ( SELECT MAX(salary) FROM employees ); #等於 SELECT * FROM employees WHERE employee_id = ( SELECT MIN(employee_id) FROM employees WHERE salary = ( SELECT MAX(salary) FROM employees ) );
d.exists後面(相關子查詢)
語法
exists(完整的查詢語句)
結果1或0 \ true or false
#查詢有員工的部門名
select department_name
from departments d
where exists(
select *
from employees e
where d.department_id = e.department_id
);
select department_name
from departments d
where in(
select *
from employees e
where d.department_id = e.department_id
);
7.2.2按結果集的行列數不同
標量子查詢(結果集只有一行一列)
列子查詢(結果集只有一列多行)
行子查詢(結果集有一行多列)
表子查詢(結果集一般為多行多列)
進階八:分頁查詢
8.1應用場景
當要顯示的資料,-頁顯示不全,需要分頁提交sq1請求
8.2語法
select 查詢列表
from 表
【join_type join 表2
on 連線條件
where 篩選條件
group by 分組欄位
having 分組後的篩選
order by 排序的欄位】
limit 【 offset】,size;
#offset要顯示條目的起始索引(起始索引從0開始)
#size要顯示的條目個數
8.3案例
#查詢前五條員工資訊
select * from employees limit 5,0;
#查詢第11條一第25條
select * from employees limit 14,10;
#有獎金的員工資訊,並且工資較高的前10名
SELECT *
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY commission_pct DESC
LIMIT 10;
8.4特點
limit語句放在查詢語句的最後
公式:
要顯示的頁數page,每頁的條目數size
select 查詢列表
from 表
limit (page-1)*size,size;
8.5案例
#查詢平均工資最低的部門資訊
SELECT *
FROM departments
WHERE department_id=(
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary)
LIMIT 1
);
#查詢平均工資最低的部門資訊和該部門的平均工資
SELECT d.*,aa.a
FROM departments d
JOIN (
SELECT AVG(salary) a,department_id
FROM employees
GROUP BY department_id
ORDER BY a
LIMIT 1
) aa
ON d.`department_id` = aa.department_id;
#查詢平均工資高於公司平均工資的部門有哪些
SELECT AVG(salary) aa,department_id
FROM employees
GROUP BY department_id
HAVING aa>(
SELECT AVG(salary)
FROM employees
);
#查詢出公司中所有manager 的詳細資訊.
select *
from employees
where employee_id in (
select manager_id
from employees
);
#各個部門中最高工資中最低的那個部門的最低工資是多少
select min(salary) from employees e
where e.department_id =(
SELECT department_id d_id FROM employees
GROUP BY department_id
ORDER BY MAX(salary)
LIMIT 1
);
#查詢平均工資最高的部門的manager的詳細資訊:last_name,department__id,email,salary
SELECT last_name,department_id,email,salary
FROM employees
WHERE employee_id IN (
SELECT e.manager_id
FROM employees e
JOIN(
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MAX(salary) DESC
LIMIT 1
) m
ON e.department_id = m.department_id
);
-----------------------------OR------------------------------------
SELECT last_name,d.department_id,email,salary
FROM employees e
JOIN departments d
ON d.`manager_id` = e.`employee_id`
WHERE d.`department_id` = (
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MAX(salary) DESC
LIMIT 1
);
進階九:聯合查詢
9.1語法
union:聯合 #合併:將多條查詢語句的結果合併成一個結果
查詢語句1
union
查詢語句2
union
查詢語句3
union
...
#應用場景:
#要查詢的結果來自於多個表,且多個表沒有直按的連線關係,但查詢的資訊一致時
要求多條查詢語句的查詢列數是一致的!
要求多條查詢語句的查詢的每一列的型別和順序最好一致
union關鍵字預設去重,如果使用 union all可以包含重複項
#查詢部門編號>90或郵箱包含a的員工資訊
select * from employees where employee_is > 90 or email like '%a%';
------------------------OR-----------------------------
select * from employees where employee_is > 90
union
select * from employees where email like '%a%';
DML
資料操作語言
插入:insert
修改:update
刪除:delete
插入語句
方式一:經典插入
1.1語法
insert into 表名(列名, ... ) value (值1, ... );
1.2案例
#插入的值的型別要與列的型別一致或相容
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'wang家航','女','2000-04-23','18582800945',NULL,2);
#不可以為nul1的列必須插入值
#列的順序可以調換
#列數和值的個數必須一-致
#可以省略列名,預設所有列,而且列的順序和表中列的順序--致
方式二:其他插入
2.1語法
insert into 表名
set 列名=值,列名=值, ...
2.2案例
insert into beauty
set id=1,name='王家航',sex='男',borndate='2000-10-12',phone='18582800945';
對比
1.方式一支援插入多行,方式二不支援
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'wang家航','女','2000-04-23','18582800945',NULL,2),
VALUES(13,'wang家航','女','2000-04-23','18582800945',NULL,2);
2.方式一支援子查詢,方式二不支援
INSERT INTO beauty(id,NAME,phone)
SELECT 26,'宋苦','11809866';
修改語句
方式一.修改單表的記錄
1.1語法
update 表名
set 列 = 新值,列 = 新值,列 = 新值 ...
where 篩選條件
1.1案例
UPDATE beauty SET phone = '16608040945'
WHERE id = 13;
UPDATE boys SET boyName = '王家航',userCP = 1000
WHERE id = 1;
方式二.修改多表的記錄【補充】
2.1語法
sql92:
update 表1 別名,表2 別名
set 列=值, ...
where 連線條件
and 篩選條件;
sql99:
update 表1 別名F
inner | left | right join 表2 別名
on 連線條件
set 列=值, ...
where 篩選條件
2.2案例
#修改張無忌的女朋友的手機號為114
UPDATE beauty be
INNER JOIN boys bo
ON be.`boyfriend_id` = bo.`id`
SET be.phone = 144
WHERE be.boName = '王家航';
刪除語句
方式一:delete
1.1語法
#1.單表的刪除
delete from 表名 where 篩選條件;
#2.多表的刪除【補充】
sql92:
delete 別名(要刪除表的別名)
from 表1 別名,表2 別名
where 連線條件
and 篩選條件;
sql99:
delete 別名(要刪除表的別名)
from 表1 別名
inner | left | right join 表2 別名
on 連線條件
where 篩選條件;
2.2案例
#刪除手機號以9結尾的女神資訊
DELETE FROM beauty WHERE phone LIKE '%9';
#刪除鹿晗的女朋友的資訊
delete be
from boys b
join beauty be
on b.`id` = be.`boyfriend_id`
where b.`boyName` = '鹿晗';
#刪除黃曉明的資訊以及他女朋友的資訊
DELETE b,be
FROM beauty be
INNER JOIN boys b
ON be.`boyfriend_id` = b.`id`
WHERE b.`boyName` = '黃曉明';
方式二:truncate
2.1語法
truncate table 表名;
-----刪除全部表資料--------
對比
delete可以加 where條件, truncate不能加
truncate刪除,效率高一丟丟
假如要刪除的表中有自增長列,如果用 delete刪除後,再插入資料,自增長列的值從斷點開始,
而 truncate刪除後,再插入資料,自增長列的值從1開始
truncate刪除沒有返回值, delete刪除有返回值
truncate刪除不能回滾, delete刪除可以回滾。
DDL
建立:create
修改:alter
刪除:drop
庫的管理
1.1語法
#建立庫
create database 【 if not exists】 庫名;
#修改庫名
rename database 舊庫名 to 新庫名
#更改庫的字符集
alter database 庫名 character set 【gbk】;
#庫的刪除、
drop database 【 if exists】庫名;
1.2案例
#建立庫 books
create database if not exists books;
表的管理
2.1表的建立
#建立表
create table 表名(
列名 列的長度【(長度) 約束】,
列名 列的長度【(長度) 約束】,
列名 列的長度【(長度) 約束】,
...
列名 列的長度【(長度) 約束】
)
#建立圖書表
create table book(
id int,#編號
bName varchar(20),#圖書名
purice double,#價格
authorId int,#作者編號
publishDate datetime#出版日期
);
#建立作者表
CREATE TABLE author(
id INT,
au_name VARCHAR(20),
nation VARCHAR(20)
);
2.2表的修改
2.2.1語法
alter table 表名 add | drop | modify | change column 列名 【列型別 約束】;
-
修改列名
#改變 表 書 更改 列 舊名 新名 修改型別 alter table book change column publishdate pubDate datetime;
-
修改列的型別或約束
#改變 表 書 修改 列 欄位名 時間戳 alter table book modify column pubDate timestamp;
-
新增新列
# 作者 新增 列 年度 型別 alter table author add column annual double; alter table 表名add colunn 列名型別[first | after 欄位名];
-
刪除列
# 作者 刪除 列 年度 alter table author drop column annual;
-
修改表名
# 作者 改名 至 alter table author rename to book_author;
-
表的刪除
drop table if exists book_author; #檢視當前庫下的表 show tables;
2.3通用寫法
drop database if exists 舊庫名;
create database 新庫名;
drop table if exists 舊錶名;
create table 表名(
列名 列的長度【(長度) 約束】,
列名 列的長度【(長度) 約束】,
...
列名 列的長度【(長度) 約束】
);
2.4表的複製
#僅僅複製表的結構
CREATE TABLE copy LIKE author;
#複製表的結構和資料
CREATE TABLE copy2
SELECT * FROM author;
#複製部分資料
CREATE TABLE copy3
SELECT * FROM author
WHERE nation = '中國';
#僅僅複製某些欄位
CREATE TABLE copy4
SELECT id,au_name
FROM aution
WHERE 0;#(1=2)
2.5常見的資料型別
所選擇的型別越簡單越好,能儲存最值的型別越小越好
2.5.1數值型
-
整形
整形型別 tinyint smallint mediumint int/integer bigint 位元組 1 2 3 4 8 特點:
-
如果不設定無符號還是有符號,預設是有符號,如果想設定無符號,需要新增tunsigned關鍵字
-
如果插入的數值超出 了整型的範圍,年報out of range異常,並且插入臨界值
-
如果不設定長度,會有預設的長度
長度代表了顯示的最大寬度,如果不夠會用0在左邊填充,但必須搭配zerofill使用
-
-
小數
定點數 dec(M,D) decimal(M,D) 浮點數 float(M,D) double(M,D)
特點:
- M:整數部位+小數部位
D:小數部位
如果超過範圍,則插入臨界值 - M和D都可以省略
如果是decimal,則M預設為10,D預設為0
如果是float和double,則會根據插入的數值的精度來決定精度 - 定點型的精確度較高,如果要求插入數值的精度較高如貨幣運算等則考慮使用
- M:整數部位+小數部位
2.5.2字元型
- 較短的文字:char、varchar
- 較長的文字:text、blob(較長的二進位制資料)
- binary和varbinary用於儲存較短的二進位制
enum用於儲存列舉
set用於儲存集合
特點:
寫法 | M的意思 | 特點 | 空間的耗費 | 效率 | |
---|---|---|---|---|---|
char | char(M) | 最大的字元數 | 固定長度的字元 | 比較耗費 | 高 |
varchar | varchar(M) | 最大的字元數 | 可變長度的字元 | 比較節省 | 低 |
2.5.3日期型
日期和時間型別 最小值 最大值
日期和時間型別 | 位元組 | 最小值 | 最大值 |
---|---|---|---|
date | 4 | 1000-01-01 | 9999-12-31 |
datetime | 8 | 1000-01-01 00:00:00 | 9999-12-31 23:59:59 |
timestamp | 4 | 19700101080001 | 2038年某個時刻 |
time | 3 | -838:59:59 | 838:59:59 |
year | 1 | 1901 | 2155 |
2.6約束
2.6.1含義
一種限制,用於限制表中的資料,為了最終保證表中的資料的準確性和可靠性
2.6.2分類
not null:非空,用於保證該欄位的值不能為空
default:預設,用於保證該欄位有預設值
PRIMARY KEY:主鍵,用於保證該欄位的值具有唯一性,並且非空
unique:唯一,用於保證該欄位的值具有唯-一性,可以為空
CHECK:檢查約束[sql 中不支特]
FOREIGN KEY:外來鍵,用於限制兩個表的關係,用於保證該欄位的值必須膚自於主表的關聯列的值
show index from 表名;
2.6.3其他
新增約束的時機:
1.建立表時2.修改表時
約束的新增分類:
列級約束:
六大約束語法,上都支援,但外來鍵約束沒有效果
表級約束:
隨了非空、預設,其他的都支援
2.6.4建立表時
-
建立表時新增列級約束
# 1.新增列級約束 create table stuinfo( id int primary key, stuName varchar(20) not null, gender char check(gender in ('男','女')), seat int unique, age int default 18, majorId int REFERENCES major(id) ); create table major( id int primary key, majorName varchar(20) not null unique ); # 直接在欄位名和型別後面追加約束型別即可
-
建立表時新增表級約束
create table stuinfo( id int, stuName varchar(20), gender char, seat int, age int, majorId int constraint pk primary key(id), constraint uq unique(seat), constraint fk_stuinfo_major foreign key(majorId) REFERENCES major(id); ); # 語法:在各個欄位的最下面 【 constraint 約束名】 約束型別(欄位名)
-
通用
create table stuinfo( id int primary key, stuName varchar(20) not null, gender char check(gender in ('男','女')), seat int unique, age int default 18, constraint fk_stuinfo_major foreign key(majorId) REFERENCES major(id); );
-
主鍵和唯一的大對比
保證唯一性 是否允許為空 一個表中可以有幾個 是否允許組合 主鍵 是 否 至多一個 是,不推薦 唯一 是 是 可以有多個 是,不推薦 -
外來鍵
1、要求在從表設定外來鍵關係
2、從表的外來鍵列的型別和主表的關聯列的型別要求一致或相容,名稱無要求
3、主表的關聯列必須是一個key(一般是主鍵或唯一)
4、插入資料時,先插入主表,在插入從表 刪除資料時,先刪陳從表,再刪除主表
2.6.5修改表時新增約束
-
語法
# 新增列級約束 alter table 表名 modify column 欄位名 欄位型別 新約束; # 新增表級約束 alter table 表名 add 【 constraint 約束名】 約束型別(欄位名) 【外來鍵的引用】;
-
案例
#改變 表 stuinfo 修改 列 stuname varchar(20) not null; alter table stuinfo modify column stuname varchar(20) not null; #2.新增預設約束 alter table stuinfo modify column age int default 18; #3.新增主鍵 #列級約束 alter table stuinfo modify column id int primary key; #表級約束 alter table stuinfo add primary key(id); #4.新增唯一 #列級約束 alter table stuinfo modify column seat int unique; #表級約束 alter table stuinfo add unique(seat); #5.新增外來鍵 alter table add foreign key(majorId) REFERENCES major(id);
2.6.6修改表時刪除約束
-
案例
# 刪除非空的束 ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR (20) NULL; # 刪除預設約束 ALTER TABLE stuinfo MODIFY COLUMN age INT; # 刪除主鍵 ALTER TABLE stuinfo DROP PRIMARY KEY; # 刪除唯一 ALTER TABLE stuinfo DROP INDEX seat; # 刪除外來鍵 ALTER TABLE stuinfo DROP FOREIGN KEY majorid:
2.6.7標識列
-
含義
又稱為自增長列
可以不用手動插入值,系統提供預設的序列值
-
關鍵字
AUTO_ INCREMENT - auto_increment
-
特點
- 標識列必須和主鍵搭配嗎?不一定,但要求是一個key
- 一個表可以有幾個標識列?至多一個!
- 標識列的型別只能是數值型
- 標識列可以通過SET auto_increment_increment=值;設定步長
-
修改表時設定標識列
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY AUTO_INCREMENT;
-
修改表時刪除標識列
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY;