MySQL學習筆記(三) 黃金

運算符

算術運算符

  • 加:+
  • 減:-
  • 乘:*
  • 除:/  或  div
    •     div只保留整數部分
  • 模:%  或  mod
#查詢員工的姓名和原來的薪資和漲薪1000元后的薪資
SELECT ename,salary,salary + 1000 FROM t_employee;

#查詢9/4的結果
SELECT 9/4

#查詢9/4的結果
SELECT 9 DIV 4

#查詢員工的姓名,和天天的薪資,假設每月的工做日是22天
SELECT ename AS "姓名", salary / 22 AS "日薪" FROM t_employee

#查詢9%4的結果
SELECT 9%4, 9 MOD 4;

比較運算符

  • 大於:>
  • 小於:<
  • 大於等於:>=
  • 小於等於:<=
  • 等於:=    
    •    賦值和比較都是用=
  • 不等於:!=  或  <>
  • 安全等於:<=>
#查詢薪資大於20000的員工
SELECT * FROM t_employee WHERE salary > 20000;

#查詢薪資等於9000
SELECT * FROM t_employee WHERE salary = 9000;

#查詢部門編號不是1的員工
SELECT * FROM t_employee WHERE did != 1;
SELECT * FROM t_employee WHERE did <> 1;

#查詢獎金比例是NULL的員工

SELECT * FROM t_employee WHERE commission_pct <=> NULL;
SELECT * FROM t_employee WHERE commission_pct IS NULL;

邏輯運算符

  • 與:&& 或 and
  • 或:|| 或 or
  • 非:!  或 not
#查詢薪資高於10000 而且低於15000的女員工
SELECT * FROM t_employee
WHERE salary > 10000 && salary <15000 AND gender = '女'

#查詢薪資高於20000  或者  籍貫是 浙江
SELECT * FROM t_employee
WHERE salary > 20000 || native_place = '浙江';

#查詢非浙江籍的男生
SELECT * FROM t_employee
WHERE NOT native_place = '浙江' AND gender = '男';

#查詢獎金比例非空的員工
SELECT * FROM t_employee
WHERE commission_pct IS NOT NULL;

集合運算符

  • in (值列表)
  • not in(值列表)
#查詢籍貫是 「浙江」、「北京」、「上海」、「黑龍江」的員工
SELECT * FROM t_employee
WHERE native_place IN ('浙江','上海','北京','黑龍江');

#查詢籍貫不是 「浙江」、「北京」、「上海」、「黑龍江」的員工
SELECT * FROM t_employee
WHERE native_place NOT IN ('浙江','上海','北京','黑龍江');

區間範圍

  • between xx and yy:[xx,yy]
  • not between xx and yy:  小於xx 或 大於yy
#查詢薪資大於等於10000 而且小於等於15000的員工
SELECT * FROM t_employee
WHERE salary BETWEEN 10000 AND 15000;

關聯查詢

  • 內鏈接
  • 外鏈接
    • 左外鏈接:left join
    • 右外鏈接:right join
    • 全外鏈接:full join  mysql不支持

關聯查詢的結果一共有七種:
關聯查詢必須有兩張或兩張以上,如下用兩張來示例:mysql

(1)A ∩ B用內鏈接sql

                               


(2)A用左鏈接數據庫


(3)A - (A ∩ B)用左鏈接
                                  安全

(4)B    用右鏈接多線程

(5)B - A ∩ B用右鏈接
                        
(6)A ∪ B本類應該用全外鏈接,如今用union併發


(7)A ∪ B - A ∩ B本類應該用全外鏈接,如今用union
                                        函數


 

內鏈接

--形式一
select 字段列表
from A表 inner join B表
on 關聯條件
【where 其餘篩選條件】

--形式二
select 字段列表
from A表 , B表
where 關聯條件 【and 其餘篩選條件】
  • 若是不寫關聯條件,會出現一種現象:笛卡爾積(將兩(或多)個表的全部行進行組合,鏈接後的行數爲兩(或多)個表的乘積數.
  •    關聯條件的個數 = n - 1,n是幾張表關聯
  •    on只能和join一塊兒用
#查詢全部的員工的姓名和他所在部門的編號和部門的名稱,不包括那些沒有安排部門的員工
--形式一
select ename,t_employee.did,dname
from t_employee inner join t_department
on t_employee.did =t_department.did;

--形式二
SELECT ename,t_employee.did,dname 
FROM t_employee , t_department
WHERE t_employee.did = t_department.did ;


#查詢全部的女員工的姓名和他所在部門的編號和部門的名稱,不包括那些沒有安排部門的員工
--1
SELECT ename,t_employee.did,dname 
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did
WHERE gender = '女';
--2
SELECT ename,t_employee.did,dname 
FROM t_employee , t_department
WHERE t_employee.did = t_department.did AND gender = '女';



#查詢員工編號,員工的姓名,部門編號,部門名稱,職位編號,職位名稱
SELECT t_employee.eid, t_employee.`ename`, t_department.did,t_department.`dname`, t_job.`job_id`,t_job.`job_name`
FROM t_employee INNER JOIN t_department INNER JOIN t_job
ON t_employee.did = t_department.did AND t_employee.`job_id` = t_job.`job_id`

SELECT t_employee.eid, t_employee.`ename`, t_department.did,t_department.`dname`, t_job.`job_id`,t_job.`job_name`
FROM t_employee , t_department , t_job
WHERE t_employee.did = t_department.did AND t_employee.`job_id` = t_job.`job_id`

左鏈接和右鏈接

左鏈接和右鏈接的區別:
(1)left換成right
(2)以左邊的表爲主仍是以右邊的表爲主spa

--左鏈接
select 字段列表
from A表 left join B表
on 關聯條件
where 從表的關聯字段 is null

--右鏈接
select 字段列表
from A表 right join B表
on 關聯條件
where 從表的關聯字段 is null
#查詢全部員工和他的部門編號,部門名稱,包括那些沒有部門的員工
SELECT * 
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did

#查詢全部沒有部門的員工

SELECT * 
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

全鏈接

mysql沒有全鏈接,使用union實現全鏈接的效果線程

select 字段列表
from A表 left join B表
on 關聯條件
union 
select 字段列表
from A表 right join B表
on 關聯條件
#查詢全部員工和部門信息,包括那些沒有部門的員工和沒有員工的部門
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
UNION
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did


#查詢那些沒有部門的員工和沒有員工的部門
SELECT *
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL
UNION 
SELECT *
FROM t_employee RIGHT JOIN t_department
ON t_employee.did = t_department.did
WHERE t_employee.did IS NULL

select語句的子句

以前:
select * from 表名稱 【where 條件】;
select 字段列表 from 表名稱 【where 條件】;3d

如今select 
select語句的5個子句:

  • (1)where
    •          where 條件   用於從表中篩選出符合條件的記錄(行)
  • (2)group by
  • (3)having
  • (4)order by
  • (5)limit

這5個子句能夠同時出現,也能夠只出現其中的一部分,其中若是有having前面必須有group by,可是有group by不必定有having
若是5個子句有多個同時出現的,那麼必須按照(1)-(5)的順序

where

#查詢全部的女員工
SELECT * FROM t_employee WHERE gender = '女';

#查詢全部女員工的姓名和薪資
SELECT ename,salary FROM t_employee WHERE gender = '女';

group by

#查詢每一個部門的平均工資
SELECT did,AVG(salary) FROM t_employee GROUP BY did;

#查詢每一個部門的平均工資,排除沒有部門的員工
SELECT did,AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did ;

#查詢每一個部門的女員工的最高工資
SELECT did,MAX(salary) FROM t_employee WHERE gender = '女' GROUP BY did;
SELECT did,MAX(salary) FROM t_employee WHERE gender = '女' AND did IS NOT NULL GROUP BY did;

#查詢男、女員工的平均工資
SELECT gender,AVG(salary) FROM t_employee GROUP BY gender;

#查詢每一個部門的男、女員工的平均工資分別是多少
#先按部門再按男女
SELECT did, gender, AVG(salary) FROM t_employee GROUP BY did,gender;
SELECT did, gender, AVG(salary) FROM t_employee WHERE did IS NOT NULL GROUP BY did,gender;


#查詢每一個部門的工資總數
SELECT did,SUM(salary) FROM t_employee GROUP BY did;

#查詢每一個部門的男、女員工的人數
SELECT did, gender, COUNT(*) FROM t_employee WHERE did IS NOT NULL GROUP BY did,gender;

having

having只用於group by分組統計語句

where和having的區別:

  • (1)where後面是不容許使用分組函數,having後面能夠加分組函數
  • where是用於「原」表中的記錄的篩選,而having是用於「統計結果」的篩選
#查詢每一個部門的平均工資,只顯示平均工資在12000以上的
SELECT did,AVG(salary) FROM t_employee  GROUP BY did HAVING AVG(salary) > 12000

#查詢每一個部門的最高工資,要求顯示最高工資低於12000
SELECT did,MAX(salary) FROM t_employee GROUP BY did HAVING MAX(salary) < 12000
SELECT did,MAX(salary) AS "m" FROM t_employee GROUP BY did HAVING m < 12000

order by

按一個或多個字段對查詢結果進行排序,asc是升序,desc爲降序,默認是升序

#查詢員工的姓名和薪資,按照薪資的從高到低排序
SELECT ename,salary FROM t_employee ORDER BY salary DESC;


#查詢員工的編號,姓名和薪資,按照薪資的從高到低排序,若是薪資相同,再按照編號升序排列
SELECT eid,ename,salary FROM t_employee ORDER BY salary DESC,eid ASC;


#查詢每一個部門的平均工資,按照平均工資的升序排序
SELECT did,AVG(salary) FROM t_employee GROUP BY did ORDER BY AVG(salary) ASC;


#查詢每一個部門的女員工的平均工資,按照平均工資的升序排序,而且只顯示平均工資高於12000的
SELECT did,AVG(salary) 
FROM t_employee 
WHERE gender = '女' 
GROUP BY did 
HAVING AVG(salary) > 12000
ORDER BY AVG(salary) ASC;

limit 分頁

limit m,n
m = (page - 1)*每頁的記錄數
n = 每頁的記錄數

#查詢員工信息,每頁顯示10條,顯示第一頁
SELECT * FROM t_employee LIMIT 0,10

#查詢員工信息,每頁顯示10條,顯示第二頁
SELECT * FROM t_employee LIMIT 10,10

#查詢每一個部門的女員工的平均工資,按照平均工資的升序排序,而且只顯示平均工資高於12000的,
#每頁顯示1條,顯示第二頁
SELECT did,AVG(salary) 
FROM t_employee 
WHERE gender = '女' 
GROUP BY did 
HAVING AVG(salary) > 12000
ORDER BY AVG(salary) ASC
LIMIT 1,1;

子查詢

某些狀況下,當進行一個查詢時,須要的條件或數據要用另一個 select 語句的結果,這個時候,就要用到子查詢。

  • 爲了給主查詢(外部查詢)提供數據而首先執行的查詢(內部查詢)被叫作子查詢。
  • 通常根據子查詢的嵌入位置分爲,where型子查詢,from型子查詢,exists型子查詢。

where型子查詢

  1. 子查詢要包含在括號內。
  2. 建議將子查詢放在比較條件的右側。
  3. 單行操做符對應單行子查詢,多行操做符對應多行子查詢。

 條件的運算符分爲兩類:
    =,>,>=,<,<=,!=  後面接子查詢的結果必須是「單值」
    in, = any, >all,>= ,<all.....  後面接子查詢的結果能夠是「多值」

#查詢全公司最高工資的員工的信息
#(1)查詢最高工資
SELECT MAX(salary) FROM t_employee;

#(2)查詢最高工資的員工的信息
SELECT * FROM t_employee WHERE salary = 130990

#(3)合起來
SELECT * FROM t_employee WHERE salary = (SELECT MAX(salary) FROM t_employee)

--------------------------------------------------------------------------
#查詢和孫紅雷,劉燁,范冰冰三我的中任意一個工資同樣的員工
SELECT * FROM t_employee WHERE salary IN (SELECT salary FROM t_employee WHERE ename IN ('孫紅雷','劉燁','范冰冰'))

SELECT * FROM t_employee WHERE salary = ANY (SELECT salary FROM t_employee WHERE ename IN ('孫紅雷','劉燁','范冰冰'))


-------------------------------------------------------------------------

#查詢比李冰冰工資高的女員工
SELECT * FROM t_employee WHERE gender = '女' AND salary > (SELECT salary FROM t_employee WHERE ename = '李冰冰');


#查詢全公司最高工資的員工的信息
SELECT * FROM t_employee WHERE salary >= ALL(SELECT salary FROM t_employee)

from型

查詢每一個部門編號,部門名稱,和平均工資,排除沒有部門的員工,包括那些沒有員工的部門

SELECT t_department.*, temp.pingjun
FROM t_department LEFT JOIN (SELECT did,AVG(salary) AS pingjun FROM t_employee  WHERE did IS NOT NULL GROUP BY did) AS temp
ON t_department.did = temp.did

exists型

#查詢部門信息,該部門必須有員工
SELECT * FROM t_department
WHERE EXISTS (SELECT * FROM t_employee WHERE t_employee.did = t_department.did)


#把SELECT * FROM t_department的每一行記錄,根據t_employee.did = t_department.did,代入到(SELECT * FROM t_employee)中查,若是能夠查到結果,說明該行要留下,不然就排除掉
 

#使用內鏈接查詢,也能夠實現
SELECT  DISTINCT t_department.* 
FROM t_department INNER JOIN t_employee
ON t_employee.did = t_department.did

單行函數(瞭解)

數學函數

ABS(x)

返回x的絕對值

CEIL(x)

返回大於x的最小整數值

FLOOR(x)

返回大於x的最大整數值

MOD(x,y)

返回x/y的模

RAND(x)

返回0~1的隨機值

ROUND(x,y)

返回參數x的四捨五入的有y位的小數的值

TRUNCATE(x,y)

返回數字x截斷爲y位小數的結果

SQRT(x)

返回x的平方根

POW(x,y)

返回x的y次方

 

字符串函數

CONCAT(S1,S2,......,Sn)

鏈接S1,S2,......,Sn爲一個字符串

CONCAT_WS(s, S1,S2,......,Sn)

同CONCAT(s1,s2,...)函數,可是每一個字符串之間要加上s

CHAR_LENGTH(s)

返回字符串s的字符數

LENGTH(s)

返回字符串s的字節數,和字符集有關

INSERT(str, index , len, instr)

將字符串str從第index位置開始,len個字符長的子串替換爲字符串instr

UPPER(s) 或 UCASE(s)

將字符串s的全部字母轉成大寫字母

LOWER(s)  或LCASE(s)

將字符串s的全部字母轉成小寫字母

LEFT(s,n)

返回字符串s最左邊的n個字符

RIGHT(s,n)

返回字符串s最右邊的n個字符

LPAD(str, len, pad)

用字符串pad對str最左邊進行填充,直到str的長度爲len個字符

RPAD(str ,len, pad)

用字符串pad對str最右邊進行填充,直到str的長度爲len個字符

LTRIM(s)

去掉字符串s左側的空格

RTRIM(s)

去掉字符串s右側的空格

TRIM(s)

去掉字符串s開始與結尾的空格

TRIM(【BOTH 】s1 FROM s)

去掉字符串s開始與結尾的s1

TRIM(【LEADING】s1 FROM s)

去掉字符串s開始處的s1

TRIM(【TRAILING】s1 FROM s)

去掉字符串s結尾處的s1

REPEAT(str, n)

返回str重複n次的結果

REPLACE(str, a, b)

用字符串b替換字符串str中全部出現的字符串a

STRCMP(s1,s2)

比較字符串s1,s2

SUBSTRING(s,index,len)

返回從字符串s的index位置其len個字符

日期時間函數

CURDATE() 或 CURRENT_DATE()

返回當前日期

CURTIME() 或 CURRENT_TIME()

返回當前時間

NOW()

 

SYSDATE()

CURRENT_TIMESTAMP()

LOCALTIME()

LOCALTIMESTAMP()

返回當前系統日期時間

YEAR(date)

MONTH(date)

DAY(date)

HOUR(time)

MINUTE(time)

SECOND(time)

返回具體的時間值

WEEK(date)

WEEKOFYEAR(date)

返回一年中的第幾周

DAYOFWEEK()

返回周幾,注意:週日是1,週一是2,。。。週六是7

WEEKDAY(date)

返回周幾,注意,周1是0,周2是1,。。。週日是6

DAYNAME(date)

返回星期:MONDAY,TUESDAY.....SUNDAY

MONTHNAME(date)

返回月份:January,。。。。。

DATEDIFF(date1,date2)

TIMEDIFF(time1, time2)

返回date1 - date2的日期間隔

返回time1 - time2的時間間隔

DATE_ADD(datetime, INTERVAL  expr  type)

返回與給定日期時間相差INTERVAL時間段的日期時間

DATE_FORMAT(datetime ,fmt)

按照字符串fmt格式化日期datetime值

STR_TO_DATE(str, fmt)

按照字符串fmt對str進行解析,解析爲一個日期

 

流程函數

IF(value,t ,f)

若是value是真,返回t,不然返回f

IFNULL(value1, value2)

若是value1不爲空,返回value1,不然返回value2

CASE

WHEN 條件1 THEN result1

WHEN 條件2 THEN result2

....

[ELSE resultn]

END

 

至關於Java的if...else if...

CASE  expr

WHEN 常量值1 THEN 值1

WHEN 常量值1 THEN 值1

....

[ELSE 值n]

END

至關於Java的switch

 

SELECT ename ,CASE

WHEN salary>=15000 THEN '高薪'

WHEN salary>=10000 THEN '潛力股'

WHEN salary>=8000 THEN '屌絲'

ELSE '草根'

END

FROM t_employee;

 

SELECT oid,`status`, CASE `status`

WHEN 1 THEN '未付款'

WHEN 2 THEN '已付款'

WHEN 3 THEN '已發貨'

WHEN 4 THEN '確認收貨'

ELSE '無效訂單'

END

FROM t_order;

 

事務

表示一組操做(sql),要麼同時成功,要麼同時失敗,那麼這種操做就構成了一個事務。

例如:
    張三  給  李四  轉帳  500元
    (1)把張三的餘額減小500
    ...
    (2)把李四的餘額增長500
    
    不容許出現:張三的錢減小了500,而李四的錢沒有加。
須要在(1)以前開啓事務,若是同時成功,那麼就提交這個事務,不然就回滾(還原到(1))以前的狀態。

 

事務的ACID特性

  • 原子性(Atomicity):原子意爲最小的粒子,或者說不能再分的事物。數據庫事務的不可再分的原則即爲原子性。
  • 組成事務的全部SQL必須:要麼所有執行,要麼所有取消(就像上面的銀行例子)。
  • 一致性(Consistency):指數據的規則,在事務前/後應保持一致
  • 隔離性(Isolation):簡單點說,某個事務的操做對其餘事務不可見的.
  • 持久性(Durability):當事務提交完成後,其影響應該保留下來,不能撤消

事務的用法

mysql默認狀況下是自動提交事務模式,即執行一句,自動提交一句,一旦提交就不能回滾。
若是想要開始手動提交模式,那麼能夠經過如下語句完成: set autocommit = false;

  • 開啓事務(start transaction)
  • 執行sql操做(普通sql操做)
  • 提交/回滾(commit/rollback)

建表的時候,選擇 Innodb引擎才支持事務

#開啓手動提交模式,做用範圍是一次鏈接(從登陸到退出)
SET autocommit = FALSE;

DELETE FROM t_department WHERE did > 5;

INSERT INTO t_department VALUES(NULL,'yy','yyyy');

ROLLBACK;
#COMMIT;

mysql中只有Innodb引擎才支持事務。
事務只對DML語句有效,對DDL語句無效。

事務的隔離級別

對於同時運行的多個事務(多線程併發), 當這些事務訪問數據庫中相同的數據時, 若是沒有采起必要的隔離機制, 就會致使各類併發問題: (問題的本質就是線程安全問題,共享數據的問題)

  • 髒讀

     一個事務讀取了另外一個事務還未提交的數據

  • 不可重複讀

     一個事務讀取了另外一個事務「修改」已提交的數據,致使一個事務期間對同一個數據的先後兩次讀取,結果不一致。

  • 幻讀

     一個事務讀取了另外一個事務新增長並已經提交的數據,致使一個事務期間記錄數不同。
     一個事務讀取了另外一個事務刪除並已經提交的數據,致使一個事務期間記錄數不同。

事務的隔離級別:
(1)READ-UNCOMMITTED:讀取未提交的數據
(2)READ-COMMITTED:讀取已提交的數據
(3)REPEATABLE-READ:可重複讀取
(4)SERIALIZABLE:序列化

mysql的默認隔離級別是:(3)

若是當前鏈接的隔離級別是READ-UNCOMMITTED,你會讀取到別人未提交的數據,這個現象稱爲髒讀。
若是避免「髒讀」,就是提升隔離級別,提升爲READ-COMMITTED或它以上。

若是當前鏈接的隔離級別是READ-UNCOMMITTED和READ-COMMITTED,都會出現不可重複的的現象,
若是要避免「不可重複讀」,仍是提升隔離級別,提升爲REPEATABLE-READ或它以上。

(3)REPEATABLE-READ和(4)SERIALIZABLE都能避免髒讀、不可重複讀、幻讀,那麼有什麼區別呢?
REPEATABLE-READ:行
SERIALIZABLE:表
相關文章
相關標籤/搜索