1. 程式人生 > 資料庫 >mysql_複習02

mysql_複習02

select

  • 基本語法:
select 查詢列 from 表名
  • 常量
select 常量值1,常量值2,常量值3;

select查詢基礎篇

  • 基礎語法:
    select 查詢的列 from 表名
    
    select a from text;
    
    • 查詢常量
    select 常量值1,常量值2,常量值3;
    
    • 查詢表示式
    select 表示式;
    
    • 查詢函式
    select 函式;
    
  • 指定欄位查詢語法
	select 欄位1,欄位2,欄位3 from 表名;
  • 查詢所有列
select * from text;
  • 列表名
  • 語法;
select 列 [as] 別名 from 表;
  • 表列名
select 別名.欄位,別名.*from 表名 [as] 別名;
例子:
select t.age as '年齡',t.name as '名字' from temp02 as t;

select條件查詢

  • 語法;
select 列名 from 表名 where 列 運算子 值;
條件運算子
+ = 		等於
+ <>或者 != 不等於
+ '>' 		大於
+ <			小於
+ '>='		大於等於
+ <= 		小於等於
邏輯運算子
+ AND	多條件成立
+ OR 	多個條件滿足一個
like模糊查詢
  • 語法:
select 列名 from 表名 where 列 like pattern;

pattern 中可以包含萬用字元,有一下幾種萬用字元
%: 表示匹配任意一個或多個字元
_ :表示匹配任意一個字元

between and(區間查詢)
  • 概念; 操作符between and(區間查詢)會選取介於兩個值之間的資料範圍,這些值可以是資料,文字或者日期,屬於一個閉區間查詢。
select 列名 from 表名 where 列名 between 值1 and 值2;

返回between和and裡面的資料,between and可以提高語句的簡潔

IN操作符

  • 當查詢同一個欄位但要查詢很多資料,我們會使用or,但是or不夠簡潔
  • IN操作符
    • 語法: select 列名 from 表名 where 欄位 in(值1,值2,值3);

這樣會變得更加簡潔
in列表不支援萬用字元,in滿足裡面任意一個都會返回對應的值

  • 例子:
	select * from text t where t.age in(1,2,3,4);

not in 查詢

  • 概念;not in 和 in剛好相反,in列表匹配會返回,not in是和列表不匹配才會返回.
	select 列名 from 表名 where 欄位 not in (值1,值2,值3)

NULL存在的坑

  • 如果資料裡面為null,那麼使用條件查詢,是查詢不到的。所以我們因該使用,NULL的專門查詢方式
  • IS NULL(返回值為空的記錄)
select 列名 from 表名 where 列 is null;
指定的列的值為null的記錄
  • is not NULL(返回值不為空的記錄)
select 列名 from 表名 where 列 is not null;
查詢指定的列的值不為null的記錄

<=>(安全等於)

  • 功能: 既可以判斷NULL值,又可以判斷普通的數值,可讀性較低,用的少.

排序和分頁(order by,limit)

select 欄位名 from 表名 order by 欄位1 [asc|desc],欄位2 [asc|desc];

asc|desc表示排序的規則,asc:升序,desc:降序.預設asc
排序支援單欄位和多欄位排序。
也可以在where後面來排序

limit介紹

  • 概念: limit用來限制select查詢返回的行數,常用來分頁等操作
  • 語法:
select 列 from 表 limit [offset,] count;

說明:
offset:表四偏移量,通俗點來講就是跳過了多少行,offset可以省略,預設為0,表示跳過0行
count :跳過offset行之後開始取資料,取count行記錄;範圍:[0,+∞]

limit分頁查詢
  • limit分頁查詢,使用limit來分頁
select 列 from 表名 limit (page - 1) * pageSize,pageSize;
page: 表示為第幾頁
pageSize: 表示每頁顯示多少條記錄

limit中不能使用表示式,limit後面只能跟明確的數字.limit後面數字不能為負數

  • 分頁查詢的坑
  • 當b欄位出現重複的值,那麼排序將會打亂,資料出現重複的值。處理方案:將兩個欄位都要進行升降排列

分頁排序時,排序不要有二義性,二義性情況下可能會導致分頁結果亂序,可以在後面追加一個主
鍵排序

分組查詢(group by,having)

  • 語法:
SELECT column, group_function,... FROM table
[WHERE condition]
GROUP BY group_by_expression
[HAVING group_condition];
  • 說明:

group_function:聚合函式。
group_by_expression:分組表示式,多個之間用逗號隔開。
group_condition:分組之後對資料進行過濾。
分組中,select後面只能有兩種型別的列:

  1. 出現在group by後的列
  2. 或者使用聚合函式的列
  • group_function:聚合函式
    • max: 指定列的最大值
    • min: 查詢指定列的最小值
    • count: 統計查詢結果的行數
    • sum: 求和,返回指定的總和
    • avg: 求平均數,返回列資料的平均值

having

  • 分組後篩選資料 使用having

where & group by & having & order by & limit 一起協

select 列 from
表名
where [查詢條件]
group by [分組表示式]
having [分組過濾條件]
order by [排序條件]
limit [offset,] count;

必須按照上面順序來寫

mysql常用函式彙總

數值型函式

函式名稱 作 用
abs 求絕對值
sqrt 求二次方根
mod 求餘數
ceil 和 ceiling 兩個函式功能相同,都是返回不小於引數的最小整數,即向上取整
floor 向下取整,返回值轉化為一個BIGINT
rand 生成一個0~1之間的隨機數,傳入整數引數是,用來產生重複序列
round 對所傳引數進行四捨五入
sign 返回引數的符號
pow 和 power 兩個函式的功能相同,都是所傳引數的次方的結果值
sin 求正弦值
asin 求反正弦值,與函式 SIN 互為反函式
cos 求餘弦值
acos 求反餘弦值,與函式 COS 互為反函式
tan 求正切值
atan 求反正切值,與函式 TAN 互為反函式
cot 求餘切值

MySQL 字串函式

函式名稱 作 用
length 計算字串長度函式,返回字串的位元組長度
concat 合併字串函式,返回結果為連線引數產生的字串,引數可以使一個或多個
insert 替換字串函式
lower 將字串中的字母轉換為小寫
upper 將字串中的字母轉換為大寫
left 從左側字擷取符串,返回字串左邊的若干個字元
right 從右側字擷取符串,返回字串右邊的若干個字元
trim 刪除字串左右兩側的空格
replace 字串替換函式,返回替換後的新字串
substr 和substring 擷取字串,返回從指定位置開始的指定長度的字元換
reverse 字串反轉(逆序)函式,返回與原始字串順序相反的字串

MySQL 日期和時間函式

函式名稱 作 用
curdate 和current_date 兩個函式作用相同,返回當前系統的日期值
curtime 和current_time 兩個函式作用相同,返回當前系統的時間值
now 和 sysdate 兩個函式作用相同,返回當前系統的日期和時間值
unix_timestamp 獲取UNIX時間戳函式,返回一個以 UNIX 時間戳為基礎的無符號整數
from_unixtime 將 UNIX 時間戳轉換為時間格式,與UNIX_TIMESTAMP互為反函式
month 獲取指定日期中的月份
monthname 獲取指定日期中的月份英文名稱
dayname 獲取指定曰期對應的星期幾的英文名稱
dayofweek 獲取指定日期是一週中是第幾天,返回值範圍是1~7,1=週日
week 獲取指定日期是一年中的第幾周,返回值的範圍是否為 0〜52 或 1〜53
dayofyear 獲取指定曰期是一年中的第幾天,返回值範圍是1~366
dayofmonth 獲取指定日期是一個月中是第幾天,返回值範圍是1~31
year 獲取年份,返回值範圍是 1970〜2069
time_to_sec 將時間引數轉換為秒數
sec_to_time 將秒數轉換為時間,與TIME_TO_SEC 互為反函式
date_add 和 adddate 兩個函式功能相同,都是向日期新增指定的時間間隔
date_sub 和 subdate 兩個函式功能相同,都是向日期減去指定的時間間隔
addtime 時間加法運算,在原始時間上新增指定的時間
subtime 時間減法運算,在原始時間上減去指定的時間
datediff 獲取兩個日期之間間隔,返回引數 1 減去引數 2 的值
date_format 格式化指定的日期,根據引數返回指定格式的值
weekday 獲取指定日期在一週內的對應的工作日索引

MySQL 流程控制函式

  • if 判斷,流程控制

IF(expr,v1,v2)
當 expr 為真是返回 v1 的值,否則返回 v2

  • ifnull 判斷是否為空

IFNULL(v1,v2):v1為空返回v2,否則返回v1.

  • case 搜尋語句

類似於java中的if..else if..else

CASE <表示式>
 WHEN <值1> THEN <操作>
 WHEN <值2> THEN <操作>
 ...
 ELSE <操作>
END CASE;
或者
CASE
 WHEN <條件1> THEN <命令>
 WHEN <條件2> THEN <命令>
 ...
 ELSE commands
END CASE;

其他函式

函式名稱 作用
version 資料庫版本號
database 當前資料庫
user 當前連線使用者
password 返回字串密碼形式
md5 返回字串md5資料

深入瞭解連線查詢及原理

  • 但我們要查詢多個表的時候,使用連線查詢來提高查詢效率!

笛卡爾積

  • 兩個集合a和b,產生的可能是a*b。(兩集合相互關聯的所有可能)
  • 語法:
select 欄位 from 表1,表2[,表N];
或者
select 欄位 from 表1 join 表2 [join 表N];

內連線

select 欄位 from 表1 inner join 表2 on 連線條件;
或
select 欄位 from 表1 join 表2 on 連線條件;
或
select 欄位 from 表1, 表2 [where 關聯條件];

內連線相當於在笛卡爾積的基礎上加上了連線的條件
當沒有連線條件的時候,內連線上升為笛卡爾積。
內連線使用第三種,簡潔!

外連線

  • 外連線涉及2個表,分為:主表和從表,要查詢的資訊主要來自於那個表,誰就是主表
  • 外連線查詢結果為主表中所有記錄。如果從表中有和它匹配的,則顯示匹配的值,這部分相當於內連線查詢出來的結果;如果從表中沒有和它匹配的,則顯示null。
  • 最終:外連線查詢結果 = 內連線的結果 + 主表中有的而內連線結果中沒有的記錄。
  • 外連線分為2種:
    • 左外連結:使用left join關鍵字,left join左邊的是主表。
    • 右外連線:使用right join關鍵字,right join右邊的是主表。
左連線
  • 語法;
select 列 from 主表 left join 從表 on 連線條件;
右連線
  • 語法:
select 列 from 從表 right join 主表 on 連線條件

子查詢♥

  • 簡要:出現在select語句中的select語句,稱為子查詢或內查詢
  • 子查詢分類
    • 標量子查詢(結果集只有一行一列)
    • 列子查詢(結果集只有一列多行)
    • 行子查詢(結果集有一行多列)
    • 表子查詢(結果集一般為多行多列)
  • select後面:僅僅支援標量子查詢。
  • from後面:支援表子查詢。
  • where或having後面:支援標量子查詢(單列單行)、列子查詢(單列多行)、行子查詢(多列多行)
  • exists後面(即相關子查詢):表子查詢(多行、多列)
select後面的子查詢
  • select 裡面還有select查詢
from後面的子查詢
  • 將子查詢結果的表當作一張表,必須起別名,否則找不到表,然後將真實的表和子查詢結果的表進行連線查詢.
where和having後面的子查詢
  • mysql中的in,any,some,all
  • in,any,some,all分別是子查詢關鍵詞之一
    • in(not in):列表中的"任意一個"
    • any或者some:和子查詢返回某一個值比較,比如a>some(10,20,30),a大於子查詢中任意一個即可,等同於a>min(10,20,30)
    • all:等同於 a>all(10,20,30),a大於子查詢中的所有制

NULL的坑

in和null比較

mysql> select * from test1;
+------+------+
| a   | b   |
+------+------+
|   1 |   1 |
|   1 | NULL |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from test1 where a in (null);
Empty set (0.00 sec)
mysql> select * from test1 where a in (null,1);
+------+------+
| a   | b   |
+------+------+
|   1 |   1 |
|   1 | NULL |
+------+------+
2 rows in set (0.00 sec)

結論: 當in和null比較時,無法查詢出為null的記錄.

not in和null比較

mysql> select * from test1 where a not in (1);
Empty set (0.00 sec)
mysql> select * from test1 where a not in (null);
Empty set (0.00 sec)
mysql> select * from test1 where a not in (null,2);
Empty set (0.00 sec)
 
mysql> select * from test1 where a not in (2);
+------+------+
| a   | b   |
+------+------+
|   1 |   1 |
|   1 | NULL |
+------+------+
2 rows in set (0.00 sec)

結論:當not in後面有null值時,不論什麼情況下,整個sql查詢結果都為空.

exists,not exists和null比較

mysql> select * from test2;
+------+------+
| a   | b   |
+------+------+
|   1 |   1 |
|   1 | NULL |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from test1 t1 where exists (select * from test2 t2 where t1.a =
t2.a);
+------+------+
| a   | b   |
+------+------+
|   1 |   1 |
|   1 | NULL |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from test1 t1 where not exists (select * from test2 t2 where
t1.a = t2.a);
+------+------+
| a   | b   |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

結論: 因為=不能比較null

聚合函式的null坑

mysql> select count(a),count(b),count(*) from test1;
+----------+----------+----------+
| count(a) | count(b) | count(*) |
+----------+----------+----------+
|     2 |     1 |     3 |
+----------+----------+----------+
1 row in set (0.00 sec)

count(a)返回了2行記錄,a欄位為NULL的沒有統計出來。
count(b)返回了1行記錄,為NULL的2行記錄沒有統計出來。
count(*)可以統計所有資料,不論欄位的資料是否為NULL。

mysql> select * from test1 where a is null;
+------+------+
| a   | b   |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)
 
mysql> select count(a) from test1 where a is null;
+----------+
| count(a) |
+----------+
|     0 |
+----------+
1 row in set (0.00 sec)

上面第1個sql使用is null查詢出了結果,第2個sql中count(a)返回的是0行。
結論:count(欄位)無法統計欄位為NULL的值,count(*)可以統計值為null的行。

NULL不能作為主鍵的值

  • 但我們建立主鍵時,雖然沒有指定not null但是,使用show create table xx 會發現建立的主鍵自動變成了not null
總結
  • 操作null其實很複雜,也很容易出錯,最有效的方法時避免使用null

事務詳解

  • 什麼時事務?
    • 資料庫中的事務是指對資料庫執行一批操作,這些操作最終要麼全部執行成功,要麼全部失敗,不會存在部分成功的情況。
      舉個例子
      比如A使用者給B使用者轉賬100操作,過程如下:
      如果在事務的支援下,上面最終只有2種結果:
  1. 操作成功:A賬戶減少100;B賬戶增加100
1.從A賬戶扣100
2.給B賬戶加100
  1. 操作失敗:A、B兩個賬戶都沒有發生變化
    如果沒有事務的支援,可能出現錯:A賬戶減少了100,此時系統掛了,導致B賬戶沒有加上100,而A賬戶憑空少了100。
  • 事務有四種特性
    • 原子性
    • 一致性
    • 隔離性
    • 永續性

mysql中事務操作

隱式事務
  • 預設是隱式事務,執行insert,updatae,delete操作的時候。
  • 檢視變數autocommit是否開啟了自動提交
show variables like 'autocommit'

autocommit為NO表示開啟了自動提交

顯式事務

顯式事務需要手動開啟,提交或回滾。有開發者自己控制

  • 方法一:
  • 語法:
//設定不自動提交事務
set autocommit=0;
//執行事務操作
commit|rollback;
  • 方法二:
  • 語法:
start transaction;//開啟事務
//執行事務操作
commit|rollback;

savepoint關鍵字

  • 功能可以回滾我們想要指定的回滾某個部分
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test1 values (1);
Query OK, 1 row affected (0.00 sec)
mysql> savepoint part1;//設定一個儲存點
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test1 values (2);
Query OK, 1 row affected (0.00 sec)
mysql> rollback to part1;//將savepint = part1的語句到當前語句之間所有的操作回滾
Query OK, 0 rows affected (0.00 sec)
mysql> commit;//提交事務
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from test1;
+------+
| a   |
+------+
|   1 |
+------+
1 row in set (0.00 sec)

從上面可以看出,執行了2次插入操作,最後只插入了1條資料。
savepoint 需要結合 rollback to sp1 一起使用,可以將儲存點 sp1 到 rollback to 之間的操作回滾掉。

只讀事務

  • 表示在事務中執行的是一些只讀操作,如查詢,但是不會做insert、update、delete操作,資料庫內部對只讀事務可能會有一些效能上的優化
  • 語法:
start transaction read only;

事務中的一些問題

  • 這些問題主要是基於資料在多個事務中的可見性來說的。
髒讀
  • 一個事務在執行的過程中讀取到了其他事務還沒有提交的資料。這個還是比較好理解的。
讀已提交
  • 從字面上我們就可以理解,即一個事務操作過程中可以讀取到其他事務已經提交的資料。事務中的每次讀取操作,讀取到的都是資料庫中其他事務已提交的最新的資料(相當於當前讀)
可重複讀
  • 一個事務操作中對於一個讀取操作不管多少次,讀取結果都是一樣的!
幻讀
  • 幻讀在可重複讀的模式下才會出現,其他隔離級別中不會出現

事務的隔離級別

  • 隔離級別分為4種:
  1. 讀未提交:READ-UNCOMMITTED
  2. 讀已提交:READ-COMMITTED
  3. 可重複讀:REPEATABLE-READ
  4. 序列:SERIALIZABLE

檢視

  • 檢視好處。
    • 簡化複製sql操作,不用知道實現細節
    • 隔離了原始表,可以不讓使用檢視的人接觸原始的表,從而保護了原始資料,提高了安全性.
  • 建立檢視
create view 檢視名
as 
查詢語句;
  • 修改檢視
    • 方法一
    create or replace view 檢視名
    as 
    查詢語句;
    
    • 方法二
    alter view 檢視名
    as 
    查詢語句;
    
  • 刪除檢視
  • 語句
drop view 檢視名去 [檢視名2] [檢視名n];

可以同時刪除多個檢視,多個檢視名稱之間用逗號隔開。

  • 查詢檢視結構
# 方法一
desc 檢視名稱
# 方法二
show create view 檢視名稱;
  • 更新檢視【基本不用】