數據庫的好處
實現數據持久化
使用完整的管理系統統一管理,易於查詢
存儲大量數據,便於實現共享
安全
DB:數據庫(dataBase),存儲數據的倉庫
DBMS:數據庫管理系統(DataBase Management System),數據庫是通過DBMS創建和操作的容器
SQL:結構化查詢語言(Structure Query Language),專門用來與DBMS通信的語言
SQL的優點:
1、不是某個特定數據庫供應商專有的語言,幾乎所有DBMS都支持SQL
2、簡單易學
3、雖然簡單,但實際上是一種強有力的語言,靈活使用其語言元素,可以進行非常複雜和高級的數據庫操作
SQL語言分類:
1、DML(Data Manipulation Language):數據操縱語句,用於添加、刪除、修改、查詢數據庫記錄,並檢查數據完整性
INSERT:添加數據到數據庫中
UPDATE:修改數據庫中的數據
DELETE:刪除數據庫中的數據
2、DDL(Data Definition Language):數據定義語句,用於庫和表的創建、修改、刪除。
CREATETABLE:創建數據庫表
ALTER TABLE:更改表結構、添加、刪除、修改列長度
DROP TABLE:刪除表
CREATE INDEX:在表上建立索引
DROP INDEX:刪除索引
3、DCL(Data Control Language):數據控制語句,用於定義用戶的訪問權限和安全級別。
GRANT:授予訪問權限
REVOKE:撤銷訪問權限
COMMIT:提交事務處理
ROLLBACK:事務處理回退
SAVEPOINT:設置保存點
LOCK:對數據庫的特定部分進行鎖定
4、DQL(Data Query Language):數據查詢語言,用來查詢記錄(數據)
SELECT:選擇(查詢)數據
DBMS分爲兩類:
–基於共享文件系統的DBMS (Access)
–基於客戶機——服務器的DBMS(MySQL、Oracle、SqlServer)
啓動&&停止
第一:右擊計算機-管理-服務
第二:通過管理員命令行
net start 服務名
net stop 服務名
登錄&&退出
第一:通過自帶的客戶端,輸入賬號密碼,退出時,exit或者ctrl+c一起按
第二:通過命令行,輸入指令:mysql -h localhost(地址) -P+(端口號) -u+賬號 -p+密碼或者回車隱藏密碼
若提示'mysql' 不是內部或外部命令,也不是可運行的程序或批處理文件。則需要重新配置環境變量
mysql常見命令
show databases; 查看數據庫中的所有數據庫
show tables; 查看數據庫中的所有表
create database 數據庫名; 創建一個數據庫
desc 表名; 查看錶的結構
select version; 查看版本
數據庫存儲數據的特點
1、數據先放在表中,表再放在庫中
2、一個庫可以有多張表,每張表都有自己的唯一標識名
3、一張表的設計,類似於java中”類"的設計
表中的字段的設計,類似於屬性的設計
表中的單條記錄,類似於一個對象
表中的所有的記錄,類似於對象的集合
orm :object relation mapping 對象關係映射
SQL語法規範:
不區分大小寫
每句話用;或\g結尾
各子句一般分行寫
關鍵字不能縮寫也不能分行
用縮進提高語句的可讀性
註釋
單行註釋:#註釋文字或者--註釋文字
多行註釋:/*註釋文字*/
DQL
查詢
進階一:
1.查詢表中的單個字段
SELECT last_name FROM employees;
2.查詢表中的多個字段
SELECT last_name,salary,email FROM employees;
3.查詢表中的所有字段
方式一:
SELECT 所有屬性名 FROM employees ;
方式二:
SELECT * FROM employees;
4.查詢常量值
SELECT 100;
SELECT 'john';
5.查詢表達式
SELECT 100%98;
6.查詢函數
SELECT VERSION();
7.起別名
/*
①便於理解
②如果要查詢的字段有重名的情況,使用別名可以區分開來
*/
方式一:使用as
SELECT 100%98 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;
8.去重
#案例:查詢員工表中涉及到的所有的部門編號
SELECT DISTINCT department_id FROM employees;
9.+號的作用
/*
java中的+號:
①運算符,兩個操作數都爲數值型
②連接符,只要有一個操作數爲字符串
mysql中的+號:
僅僅只有一個功能:運算符
select 100+90; 兩個操作數都爲數值型,則做加法運算
select '123'+90;只要其中一方爲字符型,試圖將字符型數值轉換成數值型
如果轉換成功,則繼續做加法運算
select 'john'+90; 如果轉換失敗,則將字符型數值轉換成0
select null+10; 只要其中一方爲null,則結果肯定爲null
*/
#案例:查詢員工名和姓連接成一個字段,並顯示爲 姓名
SELECT CONCAT('a','b','c') AS 結果;
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
10.拼接
CONCAT關鍵字
SELECT CONCAT(字符1,字符2,...) AS "顯示結果" FROM 表名;
其中的屬性不能爲NULL,
藉助IFNULL解決
SELECT CONCAT(屬性) AS "顯示結果" IFNULL(屬性,‘空’) FROM 表名
IFNULL(表達式一,表達式二)
表達式一:可能爲NULL的字段或者表達式
表達式二:如果一爲NULL,則顯示錶達式二,否則顯示錶達式一
進階查詢二:
/*
語法:
select
查詢列表
from
表名
where
篩選條件;
執行順序:
FROM子句
WHERE子句
SELECT子句
分類:
一、按條件表達式篩選
簡單條件運算符:> < = <> >= <=,也可以使用!=,但是不建議
二、按邏輯表達式篩選
邏輯運算符:
作用:用於連接條件表達式
and or not(也可以使用&& || !,但是不建議)
&&和and:兩個條件都爲true,結果爲true,反之爲false
||或or: 只要有一個條件爲true,結果爲true,反之爲false
!或not: 如果連接的條件本身爲false,結果爲true,反之爲false
三、模糊查詢
like
between and(前後包含)
in(用於判斷某字段是否在指定的列表中)
is null
*/
一、按條件表達式篩選
#案例1:查詢工資>12000的員工信息
SELECT * FROM employees WHERE salary>12000;
#案例2:查詢部門編號不等於90號的員工名和部門編號
SELECT last_name,department_id FROM employees WHERE department_id<>90;
二、按邏輯表達式篩選(加小括號可以提升優先級)
#案例1:查詢工資在10000到20000之間的員工名、工資以及獎金
SELECT last_name,salary,commission_pct FROM employees WHERE salary>=10000 AND salary<=20000;
#案例2:查詢部門編號不是在90到110之間,或者工資高於15000的員工信息
SELECT * FROM employees WHERE NOT(department_id>=90 AND department_id<=110) OR salary>15000;
三、模糊查詢
1.like
/*
not like 與like相反
特點:
①一般和通配符搭配使用
通配符:
% 任意多個字符,包含0個字符
_ 任意單個字符
*/
#案例1:查詢員工名中包含字符a的員工信息
select * from employees where last_name like '%a%';#abc
#案例2:查詢員工名中第三個字符爲e,第五個字符爲a的員工名和工資
select last_name,salary FROM employees WHERE last_name LIKE '__n_l%';
#案例3:查詢員工名中第二個字符爲_的員工名
SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';(ESCAPE轉義字符)
SELECT last_name FROM employees WHERE last_name LIKE '_\_%' ;
2.between and
/*
①使用between and 可以提高語句的簡潔度
②包含臨界值
③兩個臨界值不要調換順序
*/
#案例1:查詢員工編號在100到120之間的員工信息
SELECT * FROM employees WHERE employee_id >= 120 AND employee_id<=100;
SELECT * FROM employees WHERE employee_id BETWEEN 120 AND 100;
#案例2:查詢年薪在100000-200000之間的員工信息
SELECT * FROM employees WHERE salary*12*(1+IFNULL(commission_pct,0)) NOT BETWEEN 100000 AND 200000;
3.in
/*
含義:判斷某字段的值是否屬於in列表中的某一項
not in恰好相反
特點:
①使用in提高語句簡潔度
②in列表的值類型必須一致或兼容
③in列表中不支持通配符
*/
#案例:查詢員工的工種編號是 IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號
SELECT
last_name,
job_id
FROM
employees
WHERE
job_id = 'IT_PROT' OR job_id = 'AD_VP' OR JOB_ID ='AD_PRES';
#------------------
SELECT
last_name,
job_id
FROM
employees
WHERE
job_id IN( 'IT_PROT' ,'AD_VP','AD_PRES');
4、is null
/*
=或<>不能用於判斷null值
is null或is not null 可以判斷null值
*/
#案例1:查詢沒有獎金的員工名和獎金率
SELECT
last_name,
commission_pct
FROM
employees
WHERE
commission_pct IS NULL;
#案例2:查詢有獎金的員工名和獎金率
SELECT
last_name,
commission_pct
FROM
employees
WHERE
commission_pct IS NOT NULL;
#----------以下爲×
SELECT
last_name,
commission_pct
FROM
employees
WHERE
salary IS 12000;
#安全等於 <=>
#案例1:查詢沒有獎金的員工名和獎金率
SELECT
last_name,
commission_pct
FROM
employees
WHERE
commission_pct <=>NULL;
#案例2:查詢工資爲12000的員工信息
SELECT
last_name,
salary
FROM
employees
WHERE
salary <=> 12000;
#is null , <=> , =
= :只能判斷普通內容
IS NULL:僅僅可以判斷NULL值,可讀性較高,建議使用
<=> :既可以判斷NULL值,又可以判斷普通的數值,可讀性較低
進階查詢三:
/*
語法:
select
查詢列表
from
表名
where
篩選條件;
order by
排序列表
執行順序:
from 子句
where 子句
select 子句
order by子句
特點
排序列表可以是單個字段,多個字段,表達式,函數,列數,以及以上的組合
降序desc,升序是asc,默認是升序
*/
#案例1:將員工編號>120的員工信息進行工資的升序
SELECT
*
FROM
employees
WHERE
employee_id>120
ORDER BY
salary DESC;
#案例2:隊友獎金的員工,按年薪降序(表達式)
SELECT
*,salary*12*(1+IFNULL(commission_pct,0))
FROM
employees
WHERE
commission_pct IS NOT NULL
ORDER BY
salary*12*(1+IFNULL(commission_pct,0)) DESC;
#案例3:隊友獎金的員工,按年薪降序(別名)
SELECT
*,salary*12*(1+IFNULL(commission_pct,0))
FROM
employees
WHERE
commission_pct IS NOT NULL
ORDER BY
年薪 DESC;
(因爲執行順序的原因,WHERE不能使用別名)
#案例4:按姓名的字數長度進行升序排列
SELECT
last_name
FROM
employees
ORDER BY
LENGTH(last_name);
#案例5:查詢員工的姓名,工資,部門編號,先按工資升序,再按部門編號降序
SELECT
last_name,
salary,
department_id
FROM
employees
ORDER BY
salary ASC,
department_id DESC;
#案例6:按列數排序
SELECT
*
FROM
employees
ORDER BY
2;
#--------------
SELECT
*
FROM
employees
ORDER BY
列名;
常見函數
/*
函數:類似Java中學過的"方法"
爲了解決某個問題,將編寫的一系列的命令集合封裝在一起,對外僅僅暴露方法名,供外部調用
好處:提高重用性和隱藏實現細節
調用函數
叫什麼:函數名
幹什麼:函數功能
分類:
字符函數
數學函數
日期函數
流程控制函數
*/
一、字符函數
CONCAT 拼接字符
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
REPLACE 替換函數
REPLACE(object,search,replace)把object中出現search的全部替換爲replace
LENGTH 獲取字節長度
SELECT LENGTH('hello,World');
CHAR_LENGTH 獲取字符個數
SELECT LENGTH('hello,World');
SUBSTR 截取子串(開始索引是1,不是0,截取長度不寫則默認截取後續全部)
SELECT SUBSTR('hello,World',開始索引,截取的長度);
INSTR 獲取字符第一次出現的索引
SELECT INSTR('三打白骨精qaaaa白骨精bbbb白骨','白骨精');
TRIM去前後指定的字符,默認是去空格
SELECT TRIM('x' FROM 'xxxxxxxxxxxx啦啦啦xxxxx啦啦啦xxxxxxx') AS a;
顯示結果是:啦啦啦xxxxx啦啦啦
LPAD/RPAD 左填充/右填充
SELECT LPAD('木頭',10,'a');
顯示效果:aaaaaaaa木頭
UPPER/LOWER 大寫/小寫
#案例:查詢員工表的姓名,要求格式:姓首字符大寫,其他的小寫,名所有字符大寫,姓與名之間用_分隔,最後起別名OUTPUT
SELECT UPPER(SUBSTR(first_name,1,1)) ,first_name FROM employees;
SELECT LOWER(SUBSTR(first_name,2)) ,first_name FROM employees;
SELECT UPPER(last_name) FROM employees;
SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),LOWER(SUBSTR(first_name,2)),'_',UPPER(last_name)) "OUTPUT" FROM employees;
STRCMP 比較倆個字符串的大小(如果這兩個字符串相等返回0,如果第一個參數是根據當前的排序小於第二個參數順序返回-1,否則返回1。)
SELECT STRCMP('aec','abc');
LEFT/RIGHT 從左/右截取子串
SELECT LEFT('你好',1);
二、數學函數
ABS 絕對值
SELECT ABS(-2.4);
CEIL 向上取整(返回>=該參數的最小整數)
SELECT CEIL(-1.09);
FLOOR 向下取整(返回<=該參數的最小整數)
SELECT FLOOR(-1.09);
ROUND 四捨五入
SELECT ROUND(1.8712345);
顯示結果:2
SELECT ROUND(1.8712345,2);
顯示結果:1.87
TRUNCATE 截斷
SELECT TRUNCATE(1.8712345,1);
顯示結果:1.8
MOD 取餘
SELECT MOD(-10,3);
三、日期函數
NOW 獲取日期和時間
SELECT NOW();
CURDATE 只獲取日期
SELECT CURDATE();
CURTIME 只獲取時間
SELECT CURTIME();
DATEDIFF 獲取日期差
SELECT DATEDIFF('1998-1-16','2019-7-13');
DATE_FORMAT 按字符串fmt格式化日期datetime值
SELECT DATE_FORMAT('1998-7-16','%Y年%M月%d日 %H小時%i分鐘%s秒') 出生日期;
顯示效果:1998年July月16日 00小時00分鐘00秒
STR_TO_DATE 按指定格式解析字符串爲日期類型
SELECT * FROM employees WHERE hiredate < STR_TO_DATE('3/15 1998'.'%m/%d %Y');
四、流程控制函數
IF函數(類似於三目運算符)
SELECT IF(100>9,'好','壞');
#案例1:如果有獎金,則顯示最終獎金,如果沒有,則顯示0
SELECT IF(commission_pct IS NULL,0,salary*12*commission_pct) 獎金,commission_pct FROM employees;
CASE函數
情況一:
CASE 表達式
WHEN 值1 THEN 結果1
WHEN 值2 THEN 結果2
...
ELSE 結果n
END
案例1:部門編號爲30,工資爲2倍;
部門編號爲60,工資爲4倍;
部門編號爲50,工資爲3倍;
顯示部門編號,新工資,舊工資
SELECT department_id,salary,
CASE department_id
WHEN 30 THEN salary*2;
WHEN 50 THEN salary*3;
WHEN 60 THEN salary*4;
ELSE salary
END newsalary
FROM employees;
情況二:
類似於多重IF語句,實現區間判斷
案例1:如果工資>20000,顯示級別A
如果工資>15000,顯示級別B
如果工資>10000,顯示級別C
否則,顯示D
SELECT salary
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END
AS grade
FROM employees;
五、分組函數
用於實現將一組數據進行統計計算,最終得到一個值,又稱爲聚合函數或統計函數
(均忽略NULL值,都可以和DISTINCT搭配)
sum 求和
avg 求平均數
max 求最大值
min 求最小值
count 計算非空字段值的個數
distinct 去重
#案例1:查詢員工信息表中,所有員工的工資和、工資平均值、最低工資、最高工資、有工資的個數。
SELECT SUM(salary),AVG(salary),MIN(salary),MAX(salary),COUNT(salary) FROM employees;
COUNT補充
COUNT(*):用於查詢結果集中的總行數
COUNT(常量):在結果集中新加一個常量列
MyISAM存儲引擎,count(*)最高
InnoDB存儲引擎,count(*)和count(1)效率>count("字段")
六、其他函數
md5(字符):返回MD5加密
PASSWORD(字符):返回加密
分組查詢
/*
語法:
SELECT 分組函數,分組後的字段
FROM 表名
WHERE 篩選條件
GROUP BY 分組的字段
HAVING 篩選條件
ORDER BY 排序
執行順序:
①from子句
②where子句
③group by 子句
④having子句
⑤select子句
⑥order by子句
*/
GROUP BY
#案例1;顯示每個部門的工資之和
SELECT SUM(salary), department_id
FROM employees
GROUP BY department_id;
#案例2:查詢每個工種的員工平均工資
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
#案例3:查詢每個領導手下的人數
SELECT COUNT(*),manage_id
FROM employees
WHERE manage_id IS NOT NULL
GROUP BY manage_id;
分組查詢中的篩選分爲兩類
篩選的基表 使用的關鍵詞 位置
分組前篩選 原始表 where group by 的前面
分組後篩選 分組後的結果集 having group by 的後面
#案例4:查詢郵箱中包含a字符的每個部門的最高工資
SELECT MAX(salary) 最高工資,department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;
#案例5:查詢那個部門的員工個數>5(WHERE不支持分組函數做條件)
SELECT COUNT(*) 員工個數,department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>5
#案例6;每個工種有獎金的員工的最高工資>12000的工種編號和最高工資
SELECT job_id,MAX(salary)
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>12000;
#案例7:查詢有獎金的員工的最高工資>6000的工種編號和最高工資,按最高工資升序
SELECT MAX(salary) 最高工資,job_id
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING MAX(salary)>6000
ORDER BY MAX(salary) ASC;
#案例8:查詢每個工種每個部門的最低工資,並按最低工資降序
SELECT MIN(salary) 最低工資,department_id,job_id
FROM employees
GROUP BY job_id,department_id
ORDER BY MIN(salary) desc;
補充:查詢條件能在WHERE中的就不要放在HAVING後面
連接查詢(笛卡爾乘積)
/*
含義:多表查詢,當查詢的時候涉及多個表的時候,就會用到連接查詢
笛卡爾乘積現象:表一 有M行,表二有N行,結果是M*N行
發生的原因;沒有有效的連接條件
如何避免;添加有效的連接條件
分類:
按年代分類:
SQL 92標準
僅支持內連接
SQL 99標準【推薦】
支持內連接+外連接(左外和右外)+交叉連接
按功能分類
內連接
等值連接
非等值連接
自連接
外連接
左外連接
右外連接
全外連接
交叉連接
*/
一、SQL92標準
等值連接
/*
① 多表等值連接的結果爲多表的交集部分
②n表連接,至少需要n-1個連接條件
③ 多表的順序沒有要求
④一般需要爲表起別名
⑤可以搭配前面介紹的所有子句使用,比如排序、分組、篩選
*/
#案例1:查詢女生名對應的男朋友的名字
SELECT
NAME,boyName
FROM
boys,beauty
WHERE
beauty.`boyfriend_id`=boys.`id`;
起別名可以提高語句的簡潔度,區分多個重名的字段
但是查詢的字段就不能用原來的表名去限定了
#案例2;查詢員工名、工種號、工種名
SELECT
employees.last_name,employees.job_id,job_title
FROM
employees e,jobs j
WHERE
e.job_id=j.job_id;
#案例3:查詢有獎金的員工名、部門名
SELECT
last_name,department_name
FROM
employees e,departments d
WHERE
e.department_id=d.department_id
AND
e.commission_pct IS NOT NULL;
加分組
案例4:查詢每個城市的部門個數
SELECT
COUNT(*) 個數,city
FROM
departments d,locations l
WHERE
d.`location_id`=l.`location_id`
GROUP BY
city;
#案例5:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資
SELECT
department_name,d.`manager_id`,MIN(salary)
FROM
departments d,employees e
WHERE
d.`department_id`=e.`department_id`
AND
commission_pct IS NOT NULL
GROUP BY
department_name,d.`manager_id`;
加排序
#案例6:查詢每個工種的工種名和員工的個數,並且按照員工的個數降序
SELECT
job_title,COUNT(*)
FROM
employees e,jobs j
WHERE
e.`job_id`=j.`job_id`
GROUP BY
job_title
ORDER BY
COUNT(*) DESC;
三表連接
#案例7:查詢員工名、部門名和所在的城市
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`;
非等值連接
#案例1:查詢員工的工資和工資級別
SELECT
salary,job_grades
FROM
employees e,job_grade jg
WHERE
salary BETWEEN jg.`lowest_sal` AND jg.`highest_sal`;
自連接
#案例2:查詢員工名和上級的名稱
SELECT
last_name,employee_id
FROM
employees e,employees m
WHERE
e.`manager_id`=m.`employee_id`;
二、SQL99語法
/*
語法:
SELECT
查詢列表
FROM
表1 別名【連接類型】
JOIN
表2 別名
ON
連接條件
【WHERE 篩選條件】
【GROUP BY 分組】
【HAVING 篩選條件】
【ORDER BY 排序列表】
分類:
內連接:inner
外連接;
左外 left【outer】
右外 right【outer】
全外 full【outer】
交叉連接: cross
*/
內連接
/*
語法:
select 查詢列表
from 表1 別名
【inner】 join 表2 別名 on 連接條件
where 篩選條件
group by 分組列表
having 分組後的篩選
order by 排序列表
limit 子句;
特點:
①表的順序可以調換
②內連接的結果=多表的交集
③n表連接至少需要n-1個連接條件
*/
等值連接:
/*
特點:
①添加排序、分組、篩選
②inner可以省略
③ 篩選條件放在where後面,連接條件放在on後面,提高分離性,便於閱讀
④inner join連接和sql92語法中的等值連接效果是一樣的,都是查詢多表的交集
*/
#案例1:查詢員工名和部門名
SELECT
last_name,department_name
FROM
departments d
INNER JOIN
employees e
ON
e.department_id=d.department_id;
#案例2:查詢名字中包含e的員工名和工種名(添加篩選)
SELECT
last_name,job_title
FROM
employees e
INNER JOIN
jobs j
ON
e.`job_id`=j.`job_id`
WHERE
e.`last_name` LIKE '%e%';
#案例3:查詢部門個數>3的城市名稱和部門個數(添加篩選和分組)
SELECT
city,COUNT(*) 部門個數
FROM
departments d
INNER JOIN
locations l
ON
d.`location_id`=l.`location_id`
GROUP BY
city
HAVING COUNT(*)>3;
#案例4:查詢員工名、部門名、工種名,並按部門名降序(添加三表連接)
SELECT
last_name,department_name,job_title
FROM
employees e
INNER JOIN
departments d
ON
e.`department_id`=d.`department_id`
INNER JOIN
jobs j
ON
e.`job_id` = j.`job_id`
ORDER BY department_name DESC;
非等值連接
#案例1:查詢員工的工資級別
SELECT
salary,grade_level
FROM
employees e
JOIN
job_grades g
ON
e.`salary`
BETWEEN
g.`lowest_sal` AND g.`highest_sal`;
自連接
#案例1:查詢員工的名字、上級的名字
SELECT
e.last_name,m.last_name
FROM
employees e
JOIN
employees m
ON
e.`manager_id`=m.`employee_id`;
外連接
/*
語法:
select 查詢列表
from 表1 別名
left|right|full【outer】 join 表2 別名 on 連接條件
where 篩選條件
group by 分組列表
having 分組後的篩選
order by 排序列表
limit 子句;
特點:
1、外連接的查詢結果爲主表中的所有記錄
如果從表中有和它匹配的,則顯示匹配的值
如果從表中沒有和它匹配的,則顯示null
外連接查詢結果=內連接結果+主表中有而從表沒有的記錄
2、左外連接,left join左邊的是主表
右外連接,right join右邊的是主表
3、左外和右外交換兩個表的順序,可以實現同樣的效果
4、全外連接=內連接的結果+表1中有但表2沒有的+表2中有但表1沒有的(MYSQL不支持)
*/
#案例1:查詢男朋友不在boy表中的女神名(左外連接)
SELECT
b.name,bs.*
FROM
beauty b
LEFT OUTER JOIN
boys bs
ON
b.boyfriend_id =bs.id
WHERE
bs.`id` IS NULL ;
#案例2:查詢沒有員工的部門
SELECT
d.*
FROM
departments d
LEFT OUTER JOIN
employees e
ON
d.`department_id`=e.`department_id`
WHERE
e.`employee_id` IS NULL;
#案例3:查找有男朋友的女神(全外連接)
SELECT
b.*,bo.*
FROM
beauty b
FULL OUTER JOIN
boys bo
ON
b.`boyfriend_id` = bo.id
WHERE
bo.id IS NOT NULL;
交叉連接
案例1:笛卡爾乘積
SELECT
b.*,bo.*
FROM
beauty b
CROSS JOIN
boys bo;
三、sql92 PK sql99pk
/*
功能:sql99支持的較多
可讀性:sql99實現連接條件和篩選條件的分離,可讀性較高
*/
子查詢
概念:出現在其他語句內部的SELECT語句,稱爲子查詢或內查詢
內部嵌套其他SELECT語句的查詢,稱爲外查詢或主查詢
外面的語句可以是insert、update、delete、select等,一般select作爲外面語句較多
分類:
按位置
SELECT後面
僅標量子查詢
FROM後面
支持表子查詢
WHERE或HAVING後面
#標量子查詢(單行子查詢)
#列子查詢(多行子查詢)
行子查詢
EXISTS後面(相關子查詢)
表子查詢
按結果集的行列數不同
標量子查詢:結果集只有一行一列
列子查詢:結果集只有一列多行
行子查詢:結果集只有一行多列
表子查詢:結果集一般爲多行多列
WHERE或HAVING後面
#標量子查詢(單行子查詢)
#列子查詢(多行子查詢)
行子查詢
/*
特點:
子查詢放在小括號內
子查詢一般放在條件的右側
標量子查詢,一般搭配着單行操作符使用
> < >= <= = <>
列子查詢,一般搭配着多行操作符使用
in、any/some、all
子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果
*/
#1.標量子查詢
#案例1:查詢Abel的工資
SELECT
salary
FROM
employees
WHERE
last_name = 'Abel'
#案例2:查詢員工的信息,滿足 salary>案例1的結果
SELECT
*
FROM
employees
WHERE
salary>(
SELECT
salary
FROM
employees
WHERE
last_name = 'Abel'
);
#案例3:返回job_id與141號員工相同,salary比143號員工多的員工 姓名,job_id 和工資
SELECT
e.job_id,e.last_name,e.salary
FROM
employees e
WHERE
e.`job_id`=(
SELECT
job_id
FROM
employees
WHERE
employee_id=141)
AND
e.`salary`>(
SELECT
salary
FROM
employees
WHERE
employee_id = 143);
#案例4:返回公司工資最少的員工的last_name,job_id和salary
SELECT
last_name,job_id,salary
FROM
employees
WHERE
salary=(
SELECT
MIN(salary)
FROM
employees);
#案例5:查詢最低工資大於50號部門最低工資的部門id和其最低工資
SELECT
MIN(salary),department_id
FROM
employees
GROUP BY
department_id
HAVING
MIN(salary)>(
SELECT
MIN(salary)
FROM
employees
WHERE
department_id = 50);
2、#列子查詢
#案例1:返回location_id是1400或1700的部門中的所有員工姓名
SELECT
last_name
FROM
employees
WHERE
department_id =ANY(
SELECT DISTINCT
department_id
FROM
departments
WHERE
location_id IN(1400,1700)
);
3、#行子查詢
#案例1:查詢員工編號最小且工資最高的員工信息
SELECT
*
FROM
employees
WHERE
(employee_id,salary)=(
SELECT
MIN(employee_id),MAX(salary)
FROM
employees
);
SELECT後面(只支持標量子查詢,即一行一列)
#案例1:查詢每個部門的員工個數
SELECT
d.*,(SELECT
COUNT(*)
FROM
employees e
WHERE
e.department_id=d.`department_id`
FROM departments d;
#案例2:查詢員工號=102的部門名
SELECT
(
SELECT
department_name
FROM
departments d
JOIN
employees e
ON
e.department_id=d.`department_id`
WHERE
e.employee_id=102
)
部門名;
FROM後面(將子查詢結果充當一張表,要求必須起別名)
#案例1:查詢每個部門的平均工資的工資登記
SELECT
DISTINCT
ag_dep.*,g.`grade_level`
FROM(
SELECT
AVG(salary) ag,department_id
FROM
employees
GROUP BY
department_id
) ag_dep
JOIN
job_grades g
ON
ag_dep.ag BETWEEN lowest_sal AND highest_sal;
EXISTS後面(相關子查詢)
/*
語法:
exists(完整的查詢語句)
結果:
1或0
*/
#案例1:查詢有員工的部門名
SELECT
department_name
FROM
departments d
WHERE
EXISTS(
SELECT *
FROM employees e
WHERE e.department_id=d.department_id);
#案例2:查詢沒有女朋友的男生的信息
SELECT
bs.*
FROM
boys bs
WHERE
NOT EXISTS(
SELECT boyfriend_id
FROM beauty b
WHERE bs.`id`=b.`boyfriend_id`
)
分頁查詢
/*
應用場景:數據量大,服務器分頁提交請求
語法:
select 查詢列表
from 表
【join type join 表2
on 連接條件
where 篩選條件
group by 分組字段
having 分組後的篩選
order by 排序的字段】
limit 【offset,】size;
offset要顯示條目的起始索引(起始索引從0開始)
size 要顯示的條目個數
特點:
①limit語句放在查詢語句的最後
②公式
要顯示的頁數 page,每頁的條目數size
select 查詢列表
from 表
limit (page-1)*size,size;
size=10
page
1 0
2 10
3 20
*/
#案例1:有獎金的員工信息,並且工資較高的前10名顯示出來
SELECT
*
FROM
employees
WHERE
commission_pct IS NOT NULL
ORDER BY
salary DESC
LIMIT
10 ;
聯合查詢
/*
說明:當查詢結果來自於多張表,但多張表之間沒有關聯,這個時候往往使用聯合查詢,也稱爲union查詢
語法:
select 查詢列表 from 表1 where 篩選條件
union
select 查詢列表 from 表2 where 篩選條件
特點:
1、多條待聯合的查詢語句的查詢列數必須一致,查詢類型、字段意義最好一致
2、union實現去重查詢
union all 實現全部查詢,包含重複項
*/
#案例1:查詢所有國家的年齡>20歲的用戶信息
SELECT * FROM usa WHERE uage >20 UNION
SELECT * FROM chinese WHERE age >20 ;
#案例2:查詢所有國家的用戶姓名和年齡(錯誤的)
SELECT uname,uage FROM usa
UNION
SELECT age,`name` FROM chinese;
#案例3:union自動去重/union all 可以支持重複項
SELECT 1,'范冰冰'
UNION ALL
SELECT 1,'范冰冰'
UNION ALL
SELECT 1,'范冰冰'
UNION ALL
SELECT 1,'范冰冰' ;
DDL
庫的管理
#一、創建數據庫
CREATE DATABASE stuDB;
CREATE DATABASE IF NOT EXISTS stuDB;
#二、刪除數據庫
DROP DATABASE stuDB;
DROP DATABASE IF EXISTS stuDB;
表的管理
#一、創建表
數據類型:
1、整型
TINYINT SMALLINT INT BIGINT
2、浮點型
FLOAT(m,n)
DOUBLE(m,n)
DECIMAL(m,n)
m和n可選
3、字符型
CHAR(n):n可選
VARCHAR(n):n必選
TEXT
n表示最多字符個數
4、日期型
DATE TIME DATETIME TIMESTAMP
5、二進制型
BLOB 存儲圖片數據
常見約束
說明:用於限制表中字段的數據的,從而進一步保證數據表的數據是一致的、準確的、可靠的!
NOT NULL 非空:用於限制該字段爲必填項
DEFAULT 默認:用於限制該字段沒有顯式插入值,則直接顯式默認值
PRIMARY KEY 主鍵:用於限制該字段值不能重複,設置爲主鍵列的字段默認不能爲空
一個表只能有一個主鍵,當然可以是組合主鍵
UNIQUE 唯一:用於限制該字段值不能重複
字段是否可以爲空 一個表可以有幾個
主鍵 × 1個
唯一 √ n個
CHECK檢查:用於限制該字段值必須滿足指定條件
CHECK(age BETWEEN 1 AND 100)
FOREIGN KEY 外鍵:用於限制兩個表的關係,要求外鍵列的值必須來自於主表的關聯列
要求:
①主表的關聯列和從表的關聯列的類型必須一致,意思一樣,名稱無要求
②主表的關聯列要求必須是主鍵
語法:
CREATE TABLE [IF NOT EXISTS] 表名(
字段名 字段類型 【字段約束】,
字段名 字段類型 【字段約束】,
字段名 字段類型 【字段約束】,
字段名 字段類型 【字段約束】,
字段名 字段類型 【字段約束】);
#案例1:沒有添加約束
CREATE TABLE IF NOT EXISTS stuinfo(
stuid INT ,
stuname VARCHAR(20),
stugender CHAR(1),
email VARCHAR(20),
borndate DATETIME
);
#案例2:添加約束
DROP TABLE IF EXISTS stuinfo;
CREATE TABLE IF NOT EXISTS stuinfo(
stuid INT PRIMARY KEY,#添加了主鍵約束
stuname VARCHAR(20) UNIQUE NOT NULL,#添加了唯一約束+非空
stugender CHAR(1) DEFAULT '男',#添加了默認約束
email VARCHAR(20) NOT NULL,
age INT CHECK( age BETWEEN 0 AND 100),#添加了檢查約束,mysql不支持
majorid INT,
CONSTRAINT fk_stuinfo_major FOREIGN KEY (majorid) REFERENCES major(id)#添加了外鍵約束);
#二、修改表[瞭解]
語法:ALTER TABLE 表名 ADD|MODIFY|CHANGE|DROP COLUMN 字段名 字段類型 【字段約束】;
#案例1.修改表名
ALTER TABLE stuinfo RENAME TO students;
#案例2.添加字段
ALTER TABLE students ADD COLUMN borndate TIMESTAMP NOT NULL;
#案例3.修改字段名
ALTER TABLE students CHANGE COLUMN borndate birthday DATETIME NULL;
#案例4.修改字段類型
ALTER TABLE students MODIFY COLUMN birthday TIMESTAMP ;
#案例5.刪除字段
ALTER TABLE students DROP COLUMN birthday;
#三、刪除表
DROP TABLE IF EXISTS students;
#四、複製表
#僅僅複製表的結構
CREATE TABLE newTable2 LIKE major;
#複製表的結構+數據
CREATE TABLE newTable3 SELECT * FROM girls.`beauty`;
#案例:複製employees表中的last_name,department_id,salary字段到新表 emp表,但不復制數據
CREATE TABLE
emp
SELECT
last_name,department_id,salary
FROM
myemployees.`employees`
WHERE 1=2;
DML
一、數據 的插入
/*
語法:
插入單行:
insert into 表名(字段名1,字段名2 ,...) values (值1,值2,...);
插入多行:
insert into 表名(字段名1,字段名2 ,...) values
(值1,值2,...),(值1,值2,...),(值1,值2,...);
特點:
①字段和值列表一一對應
包含類型、約束等必須匹配
②數值型的值,不用單引號
非數值型的值,必須使用單引號(比如:日期,字符串)
③字段順序無要求
自增長:
語法:
列名 數據類型 約束 identity(m,n)
m表示的是初始值,n表示的是每次自動增加的值
MYSQL中則是
列名 數據類型 約束 AUTO_INCREMENT
*/
二、數據 的修改
/*
語法:
update 表名 set 字段名 = 新值,字段名=新值,...
where 篩選條件;
*/
三、數據 的刪除
/*
方式1:delete語句
語法:delete from 表名 where 篩選條件;
方式2:truncate語句(刪除表中所有數據)
語法:truncate table 表名;
*/
#【面試題】delete和truncate的區別
1.delete可以添加WHERE條件
TRUNCATE不能添加WHERE條件,一次性清除所有數據
2.truncate的效率較高
3.如果刪除帶自增長列的表,
使用DELETE刪除後,重新插入數據,記錄從斷點處開始
使用TRUNCATE刪除後,重新插入數據,記錄從1開始
4.delete 刪除數據,會返回受影響的行數
TRUNCATE刪除數據,不返回受影響的行數
5.delete刪除數據,可以支持事務回滾
TRUNCATE刪除數據,不支持事務回滾
事務
一、什麼是事務?爲什麼要用事務?
一個事務是由一條或者多條sql語句構成,這一條或者多條sql語句要麼全部執行成功,要麼全部執行失敗!
二、事務的四大特性(ACID)
原子性(Atomicity):事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗。
一致性(Consistency):事務執行後,數據庫狀態與其它業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的。
隔離性(Isolation):隔離性是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾。
持久性(Durability):一旦事務提交成功,事務中所有的數據操作都必須被持久化到數據庫中,即使提交事務後,數據庫馬上崩潰,在數據庫重啓時,也必須能保證通過某種機制恢復數據。
三、分類
隱式事務:沒有明顯的開啓和結束標記
比如dml語句的insert、update、delete語句本身就是一條事務
insert into stuinfo values(1,'john','男','[email protected]',12);
顯式事務:具有明顯的開啓和結束標記
一般由多條sql語句組成,必須具有明顯的開啓和結束標記
四、步驟:
1、取消隱式事務自動開啓的功能
2、開啓事務
3、編寫事務需要的sql語句(1條或多條)
insert into stuinfo values(1,'john','男','[email protected]',12);
insert into stuinfo values(1,'john','男','[email protected]',12);
4、結束事務
#演示事務的使用步驟
#1、取消事務自動開啓
SET autocommit = 0;
#2、開啓事務
START TRANSACTION;
#3、編寫事務的sql語句
#將張三丰的錢-5000
UPDATE stuinfo SET balance=balance-5000 WHERE stuid = 1;
#將滅絕的錢+5000
UPDATE stuinfo SET balance=balance+5000 WHERE stuid = 2;
此時存放在緩存中,尚未保存
#4、結束事務
#提交
#commit;
#回滾
ROLLBACK;
#5、查看結果
SELECT * FROM stuinfo;