(一)幾個數據庫相關的概念
1.數據庫
數據庫: 保存有組織數據的容器。
數據的所有存儲、檢索、管理和處理實際上是有數據庫軟件DBMS完成的。
我們通過數據庫軟件DBMS來創建和操縱容器。
2.表
某種特定類型數據的結構化清單。表名是唯一的,用來標識自己。
表具有一些特性,定義了數據在表中如何的存儲,存儲什么樣的數據,數據如何分解,各部分信息如何命名等。描述這組信息叫做模式(schema),它是關于數據庫和表的布局及特性信息。
3.列和數據類型
列:表中的一個字段
數據類型:每個列都有相應的數據類型
4.行
表中的一條記錄
5.主鍵
一列或者一組列,能夠唯一區分表中的每個行。
習慣上:不更新主鍵列中的值,不重用主鍵列的值,不在主鍵列中使用可能更改的值。
6.外鍵
外鍵為某個表的一列,它包含另一個表的主鍵值。
(二)mysql使用方法
1.mysql是什么?
mysql是一種DBMS,即是一種數據庫軟件。它是一種基于客戶機-服務器的數據庫。
2.mysql的優點:
(1)因為開源,成本低
(2)執行速度快,性能好
(3)可信賴
(4)易于安裝和使用
3.連接好數據庫后,就可以訪問數據庫并做操作,其中use是用來選擇數據庫的,show是用來查看mysql數據庫、表、每部信息的。
(1)use + database name;
? ? ? 表示切換使用哪個數據庫。
? ? ? 用use打開數據庫,才能讀取其中的數據。
(2)show database;
? ? ? 返回數據庫的列表
(3)show tables;
? ? ? 獲取一個數據庫內的表的列表
(4)show columns from customers;
? ? ? 顯示每列的信息,后面用的比較多的是 desc customers;
(三)用select檢索數據
1.select:
用途:從表中檢索一個或者多個數據列。
select語句中需要體現兩種信息:選什么,從什么地方選。
2.檢索單列
例如:select prod_name from products;
解釋:從products表中檢索出來prod_name列
注意:返回結果是未排序的。
3.檢索多列
例如:select prod_id,prod_name,prod_price from products;
4.檢索所有列
select * from product;
優點:不明確列名的時候使用。
5.distinct關鍵字
作用:指示mysql只返回不同的值的行
例如:select distinct vend_id from products;
使用:它必須放在列名前面
6.limit
作用:返回結果的前幾行
例如:select prod_name from products limit 5;
如果是 select prod_name from products limit 5,5;則表示從行5開始,檢索5行.
注意:檢索出來第一行是行0。如果行數不夠,能返回多少就返回多少。
7.完全限定的表名
select products.prod_name from product;
(四)用where進行數據過濾
1、where子句
作用:指定搜索條件,因為一般數據庫表都包含大量的數據,很少我們需要所有的行,通常會根據特定需要來提取數據的子集。where語句就是來指定搜索條件(過濾條件)
位置:放在from之后,order by之前
例子:select prod_name,prod_price from products where prod_price = 2.50
解釋:這里采用了相等測試,只返回prod_price為2.5的行,還可以有等于、不等于、小于、小于等、大于、大于等、between操作符。
擴展:根據這些操作符,可以做單個值匹配(=)、不匹配檢查(!=或者<>)、范圍值檢查(between)、空值檢查(is null)
例子1:between用法,它需要兩個值。
select prod_name,prod_price from products where prod_price between 5 and 10;
例子2:空值檢查
select cust_id from customers where cust_email is null;
2.組合where子句
目的:為了進行更強的過濾控制,mysql允許給出多個where自居,以邏輯操作符and或者or的方式使用。
and例子:
select prod_id,prod_price,prod_name
from products
where vend_id =1003 and prod_price <=10;
解釋:必須同時滿足兩個條件
or例子:
select prod_id,prod_price,prod_name
from products
where vend_id =1003 or vend_id =1002;
解釋:滿足任意一個條件即可
注意:計算次序用圓括號界定,要不容易混淆。
3、in操作
作用:指定條件范圍
例子:select prod_name,prod_price
from products
where vend_id in (1002,1003);
解釋:檢索供應商1002和1003制造的所有產品。in操作符后面跟著的是合法值得清單。
另一種寫法:
select prod_name,prod_price
from products
where vend_id = 1002 or vend_id = 1003;
那么為什么使用in操作符呢,優點是什么呢?
(1)清楚只管
(2)計算次序容易理解
(3)in執行比or執行的快
(4)在in中可以包含其他的select語句
4、not操作符:
作用:where子句中用來否定后跟條件的關鍵字。
例如:select prod_name,prod_price
from products
where vend_id not in (1002,1003);
解釋:檢索除了1002和1003之外的所有。
(五)通配符過濾
1、應用場景
? 之前說的數據過濾都是對已知值進行過濾的,比如說匹配一個值或者多個值,大于某個值或者是小于某個值,或者是檢查某個范圍的值。
? 但是如果我要搜索產品名中包含anvil的所有產品呢,這時候通配符就可以大顯身手了,我們可以利用通配符搜索模式,找出產品名中任何位置出現anvil的產品。
2、什么是通配符
概念:用來匹配值得一部分的特殊字符
如何使用:為了在搜索子句中使用通配符,必須使用like操作符。
3、有哪些通配符以及如何使用呢?
(一)百分號通配符%
表示:任何字符出現任意次數,也可以是0次
例子:
(1)找到以jet開頭的產品,接受jet后面為任意多個字符
select prod_id,prod_name
from products
where prod_name like 'jet%';
(2)匹配任何位置包含anvil,不論在之前還是之后出現什么字符。
select prod_id,prod_name
from products
where prod_name like '%anvil%';
(3)找到以s起頭、以e結尾的所有產品:
select prod_name
from products
where prod_name like 's%e';
注意:
(1)可以用‘**%’的形式進行尾空格處理,也可以用trim函數進行處理
(2)%通配符不能匹配null
(二)下劃線通配符_
表示:下劃線只匹配單個字符而不是多個字符
這也是與%的區別,這里就不舉例贅述了。
4、小結:
通配符是一種非常有用的搜索工具,但是不能過度使用,否則搜索時間會很長。
(六)正則表達式匹配
1、啥是正則表達式
正則表達式的作用是匹配文本,將一個正則表達式與一個文本串進行比較,mysql用where子句對正則表達式提供了初步的支持,允許指定正則表達式,過濾select檢索出的數據。
2、like與regexp的區別
舉個例子來看兩者的差別:
(一)like統配符
select prod_name
from products
where prod_name like '1000'
order by prod_name;
結果:不返回數據
(二)正則表達式
select prod_name
from products
where prod_name regexp '1000'
order by prod_name;
結果:返回一行
原因:like匹配的是整個列,只有使用通配符的時候才會返回。而regexp是在列值中匹配,如果被匹配的文本在列值中出現regexp將會找到他,相應的行將被返回。
3、有哪幾種匹配呢?
(一)基本字符匹配
例1:檢索列prod_name包含文本1000的所有行
select prod_name
from products
where prod_name regexp '1000'
order by? prod_name;
注意:regexp后所跟的東西作為正則表達式處理。
例2:檢索列prod_name包含000的所有行
select prod_name
from products
where prod_name regexp '.000'
order by? prod_name;
注意:.是正則表達式語言中的一個特殊的字符,它表示的匹配任意一個字符,所以1000和2000都符合條件。
(二)or匹配
使用:當我想搜索兩個串之一時,使用|
例子:匹配prod_name為1000或者2000的情況
select prod_name
from products
where prod_name regexp '1000|2000'
order by prod_name;
(三)匹配幾個字符之一
表示:匹配任何一個單一字符,當想匹配特定字符的時候,可通過制定一組用[]括起來的字符來完成。
例1:
select prod_name
from products
where prod_name regexp '[123] Ton'
order by prod_name;
解釋:正則表達式是[123] Ton,[123]定義了一組字符,即匹配1或者2或者3,這么看,其實[ ]是另一種形式or語句,也可以看做是[1|2|3]的縮寫。
例2:
select prod_name
from products
where prod_name regexp '[^123] Ton'
order by prod_name;
解釋:匹配的是除這些字符意外的任何東西。
(三)匹配范圍
集合可以用來定義要匹配的一個或者多個字符,如果想匹配0到9,可以用[0123456789],也可以用[0-9],并且范圍不一定是數值,也可以匹配字符,[a-z]匹配任意的字母字符。
例1:
select prod_name
from products
where prod_name regexp '[1-5] Ton'
order by prod_name;
解釋:這個表達式的意思是匹配1到5,例如.5 Ton也會返回。
(四)匹配特殊字符
為了匹配特殊字符,必須使用\\為前導
例如:
(1) \\-匹配-,\\.匹配.
(2) 匹配\用\\\
(五)匹配字符類
(1)[:alnum:]? --? 任意字符和數字
(2)[:alpha:]? --? 任意字符
(3)[:blank:]? --? 空格和制表
(4)[:cntrl:]? --? ascii控制字符
(5)[:digit:]? --? 任意數字
(6)[:graph:]? --? 與[:print:]相同,但是不包含空格
(7)[:print:]? --? 任意可打印字符
(8)[:lower:]? --? 任意小寫字母
(9)[:punct:]? --? 既不在[:alpha:]也不在[:cntrl:]中的任意字符
(10)[:space:]? --? 包括空格在內的任意空白字符
(11)[:upper:]? --? 任意大寫字母
(12)[:xdigit:]? --? 任意十六進制數字
(六)匹配多個實例
意義:之前的正則表達式師徒匹配單詞出現。但是有的時候需要對匹配書目進行更強的控制
例1:
select prod_name
from products
where prod_name regexp '\\([0-9] sticks?\\)'
order by prod_name;
解釋:其中\\是用來匹配括號的,[0-9]用來匹配任意數字,sticks?匹配stick和sticks,因為?匹配他前面任何字符的0次或者1次出現。
例2:
select prod_name
from products
where prod_name regexp '[[:digit:]]{4}'
order by prod_name;
解釋:[:digit:]匹配任意數字,{4}確切的要求它前面的數字出現4次,所有正則表達式匹配連在一起的任意4位數字。
同理,可以寫成:
select prod_name
from products
where prod_name regexp '[0-9][0-9][0-9][0-9]’
order by prod_name;
擴展:
*表示0個或者過個匹配
+表示1個或者多個匹配
?表示0個或者1個匹配
{n}表示指定書目的匹配
{n,}表示不少于指定數目的匹配
{n,m}表示匹配數目的范圍
(七)定位符
目的:為了匹配特定位置的文本。
例子:找出以一個數或者小數點開始的所有產品,這里需要定位符^,表示文本的開始。
select prod_name
from products
where prod_name regexp '^[0-9\\.]'
order by prod_name;
注意:在集合^[123]中表示否定該集合,在此處表示的是文本的開始。
擴展:
(1)^ 文本的開始
(2)$ 文本的結尾
(七)計算字段
--為什么需要計算字段?
因為存儲在數據庫表中的數據一般不是應用程序所需要的格式,有的時候我們需要對原始數據做一些變換等需求。這就是計算字段發揮作用的時候了。
注意:
(1)我們需要直接從數據庫中檢索出轉換、計算或者格式化過的數據,而不是檢索出數據,然后再在客戶機應用程序或者報告程序中重新格式化。
(2)計算字段并不實際存在于數據庫表中,計算字段是運行時在select語句內創建的。
本文主要介紹兩個知識點,一個是拼接字段,一個是執行算數計算。
1、拼接字段
拼接:將值聯結到一起構成一個單個值。在select語句中,使用concat()函數來拼接兩個列,待拼接的各個串用逗號分隔。
例子:
select concat(vend_name,' (',vend_country,') ')
from vendors
order by vend_name;
2、執行算數計算
例子:
select prod_id,
? ? ? ? ? quantity,
? ? ? ? ? item_price,
? ? ? ? ? quantity*item_price as expanded_price
from orderitems
where order_name = 20005;
解釋:其中expanded_price是一個計算字段,計算為quantity*item_price。在執行算數計算的時候,加減乘除都可以甲酸,并且用圓括號來確定計算順序。
擴展:刪除右側的所有空格,可以用rtrim()函數,如果是刪除左側的所有空格,可用ltrim(),去掉兩邊的空格是trim(),在拼接字段有時候會用到。例如:
select concat(rtrim(vend_name),' (',rtrim(vend_country),')') as
vend_title
from vendors
order by vend_name;
(八)數據處理函數
本文主要介紹mysql支持什么樣的函數,以及如何使用這些函數。
1、使用函數,那么主要有哪些種類的函數呢?
(1)用于處理文本串的文本函數。比如說:刪除或者填充值,轉化大小寫
(2)用于在數值數據上進行算數計算,比如說:返回絕對值以及代數運算
(3)用于處理日期和時間值,并且從這些值中提取特定的成分的日期和時間函數,比如說返回這兩個值的日期之差,檢查日期的有效性。
(4)返回DBMS正使用的特殊信息的系統函數。比如返回用戶登錄信息、檢查版本細節。
2、文本處理函數
(1)rtrim():去除列值右邊的空格
(2)upper():將文本轉換大寫
(3)left():返回串左邊的字符
(4)length():返回串的長度
(5)locate():找出串的一個子串
(6)lower():轉換為小寫
(7)soundex():返回串的soundex值,發音相似
(8)substring():返回子串的字符
例子:
select cust_name,cust_contact
from customers
where soundex(cust_contact) = soundex('Y Lie');
3、日期和時間處理函數
(1)adddate() :增加一個日期(天、周)
(2)addtime() :增加一個時間(時、分)
(3)curdate():返回當前日期
(4)date():返回日期時間的日期部分
(5)datediff():計算兩個日期之差
(6)day():返回一個日期的天數部分
(7)dayofweek():對應一個日期返回對應星期幾
(8)hour():返回一個日期的小時部分
(9)minute():返回一個時間的分鐘部分
(10)month():返回一個時間的月份部分
(11)now():返回當前日期的時間
(12)second():返回一個時間的秒部分
(13)time():返回一個日期時間的時間部分
(14)year():返回一個日期的年份部分
注意:不管是插入表還是更新表還是用where子句進行過濾,日期必須為yyyy-mm-dd的格式,雖然其他的日期格式可能可行,但是這是首選的日期格式,它排除了多意義性。
例如:
select cust_id,order_num
from orders
where order_date = '2015-09-01';
如果日期的形式是‘2015-09-01 00:00:00’,那么就檢索不出來,所以更加可靠的形式為:
select cust_id,order_num
from orders
where date(order_date) = '2015-09-01';
如果我想檢索出2005年9月下的所有訂單:
方法一:
select cust_id,order_num
from orders
where date(order_date) between '2005-09-01' and '2015-09-30';
方法二:
select cust_id,order_num
from orders
where year(order_date) =2005 and month(order_date)=9;
4、數值處理函數:
它一般用于代數、三角或幾何運算。
abs、cos、exp、mod、pi、rand、sin、sqrt、tan
(九)匯總數據
這部分主要介紹聚集函數以及如何利用它們來匯總表的數據。
1、聚集函數的概念:運行在行組上,計算和返回單個值的函數。
2、mysql主要的聚集函數有哪些?
(1)avg:返回某個列的平均值
(2)count:返回某列的行數
(3)max:返回某列的最大值
(4)min:返回某列的最小值
(5)sum:返回某列值之和
3、avg
概念:
(1)通過對表中的行數計數病計算特定列值之和。求得該列的平均值。
(2)avg可以用來返回所有列的平均值,也可以用來范數特定列或行的平均值。
例子:
selelct avg(prod_price) as avg_price
from product;
解釋:返回products表中所有產品的平均價格
select avg(prod_price) as avg_price
from products
where vend_id = 1003;
解釋:指定特定行或者特定列求平均值,它返回的是特定供應商1003所提供產品的平均價格。
注意:
(1)avg只能確定特定數值列的平均值,而且列名必須作為函數的參數給出。如果說我們想獲得更多列的平均值,要使用多個avg()函數。
(2)avg()函數忽略列值為NULL的行
4、count
概念:
(1)count()主要是用來計數
(2)利用count()確定表中行的數目,以及符合特定條件的行的數目
注意:
(1)使用count(*)對表中行的數目進行統計,不管是表列中包含的是null和非null
(2)使用count(column)對特定的具有值的行進行計數,忽略null
例子:
select count(*) as num_cust
from customers;
解釋:返回customers表中客戶的總數,這里利用count(*)對所有的行進行計數,不管各行中有什么值,計數值將在num_cust中返回。
select count(cust_emial) as num_cust
from customers;
解釋:只對有點子郵件的客戶進行計數。
5、max()
概念:max()返回指定列的最大值,但是max()需要制定列名
例子:
select max(prod_price) as max_price
from products;
解釋:返回products表中最貴的物品。
注意:
(1)在用于文本數據的時候,如果數據是按相應的列排序,則max()返回的是最后一行。
(2)max()函數忽略列值為null的行
6、min()
概念:max()返回指定列的最小值,但是max()需要制定列名,使用方法與max同理
7、sum
概念:用來返回指定列值的和(總計)
例子:
select sum(quantity) as items_ordered
from orderitems
where order_num = 20005;
解釋:sum(quantity)用來返回訂單中所有物品的數量之和,where子句值統計某個物品訂單中的物品。
同理,sum也可以用來合計計算值。例如下面的例子,可以得到總的訂單金額,where子句同樣保證只統計某個物品訂單中的物品。
select sum(item_price*quantity) as total_price
from orderitems
where order_num = 20005;
注意:sum()會忽略列值為null的行。
8、在聚合函數中用distinct
例子:加了distinct參數之后,平均值只考慮各個不同的價格
select avg(distinct prod_price) as avg_price
from products
where vend_id = 1003;
注意:
(1)distinct只能用于count()
(2)不能用count(distinct)
(3)不能用distinct count(*)
9、組合聚集函數,看到這個例子就會秒懂~
例如:
select count(*) as num_items
? ? ? ? ? min(prod_price) as price_min,
? ? ? ? ? max(prod_price) as price_max,
? ? ? ? ? avg(prod_price) as price_avg
from products;
(十)排序檢索數據
目的:為了明確的排序用select語句檢索出來的數據,可以用order by子句,order by往往取一個或者多個列的名字,根據此對輸出進行排序。
1、如何用order by
按照單個列排序的例子:
select prod_name
from products
order by prod_name;
如果按照多個列進行排序的話,只要列出列名,列名之間用逗號分隔。例如下面的例子,首先按照價格排序,再按照商品名字排序。
select prod_id,prod_price,prod_name
from products
order by prod_price,prod_name;
注意:對于上述例子,僅僅在多個行具有相同的prod_price值時才對prod_name進行排序。如果prod_price列中所有的值都是唯一的,那么就不會按照prod_name排序。
2、指定排序方向
升序:asc,默認的
降序:desc
例子:按照價格降序,最貴的在前面。
select prod_id,prod_price,prod_name
from products
order by prod_price desc;
如果按照多個列進行排序呢?例如:
select prod_id,prod_price,prod_name
from products
order by prod_price desc,prod_name;
解釋:以降序排序產品,然后再對產品名排序。
注意:這里只對prod_price降序了,如果想在多個列上進行姜旭排序,必須對每個列指定desc關鍵字。
擴展:使用order by和limit的組合,能夠找出一個列的最高和最低的值。
例如:如何找出最昂貴物品的值
select prod_price
from products
order by prod_price desc
limit 1;
(十一)分組數據
1、什么是分組?
分組就是匯總表內容的子集,分組允許把數據分為多個邏輯組,以便能對每個組進行聚集計算。
2、涉及的子句
group by子句和having子句
3、下面從兩個部分介紹分組:
(1)創建分組 --group by
(2)過濾分組 --having
(一)創建分組
舉例:
select vend_id, count(※) as num_prods
from products
group by vend_id;
解釋:
對vend_id分組,并且統計個數。
group by指定要被分組的目標(vend_id),并做統計。
注意:
(1)group by子句可以包含任意數目的列
(2)如果在group by子句中嵌套了分組,數據將會在最后規定的分組上進行匯總。
(3)在group by中列出的列不能是聚集函數
(4)如果在select中使用表達式,則必須在group by子句中指定相同的表達式,不能使用別名。
(5)除了聚集計算語句之外,select語句中的沒個列都必須在group by子句中給出。
(6)如果分組列中具有null,則它們將會作為一個分組返回。
(7)group by必須在where語句之后,order語句之前。
(二)過濾分組
意義:規定了包括哪些分組,排除哪些分組
比如:我想列出至少有兩個訂單的所有顧客,此時,必須基于完整的分組進行過濾,而不是根據個別的行進行過濾。
注意:where過濾指定的是行而不是分組。where沒有分組的概念。
引入:having進行過濾分組,事實上,所有類型的where子句都可以用having來代替。
where和having的區別:where過濾行,having過濾分組
舉例1:
select cust_id, count(※)? as orders
from orders
group by cust_id
having count(※)>2;
解釋:訂單數大于2的用戶
舉例2:
select vend_id, count(※) as num_prods
from products
where prod_price >10
group by vend_id
having count(※)>2;
解釋:同時用了where和having,表示具有2個以上,價格10以上的產品的供應商。
最后注意:
一般在使用group by子句的時候,應該給出order by子句,這是保證數據正確排序的唯一方法。千萬不要依賴group by的排序數據。
總結:
select子句的順序:
select
from
where
group by
having
order by
limit
(十二)子查詢
子查詢經常出現的場景:
(1)where子句的in操作符中
(2)用來填充計算列
1、在這里舉一個例子,就知道子查詢是什么,以及子查詢如何使用了。
舉例:列出訂購物品TNT2的所有客戶。
參考:mysql必知必會樣例表
涉及的表:orderitems、orders、customers
檢索的步驟:
(1)檢索包含物品TNT2的所有訂單號
select order_num
from orderitems
where prod_id = 'TNT2';
得到的結果是:order_num:20005和20007
(2)查詢具有訂單20005和20007的客戶
select cust_id
from orders
where order_num in (20005,20007);
得到的結果是:cust_id:10001和10004
(3)檢索客戶id為10001和10004的客戶信息
select cust_name,cust_contact
from customers
where cust_id in (10001,10004);
即得到了最后的結果
將這三個查詢合并為一個:
select cust_name,cust_contact
from customers
where cust_id in (select cust_id
? ? ? ? ? ? ? ? ? ? ? ? ? ? from orders
? ? ? ? ? ? ? ? ? ? ? ? ? ? where order_num in (select order_num
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? from orderitems
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? where prod_id = 'TNT2'));
2、再舉一個例子:現在需要顯示customers表中每個客戶的訂單總數。
涉及的表:customers,orders(存儲訂單與相應的客戶id)
(1)先過濾某個特定用戶的訂單數量,再推廣到每個用戶。
select count(※) as orders
from orders
where cust_id = 10001;
(2)對每個用戶進行count計算
select cust_name,
? ? ? ? ? cust_state,
? ? ? ? ? (select count(※)
? ? ? ? ? ? from orders
? ? ? ? ? ? where orders.cust_id = customers.cust_id) as orders
from customers
order by cust_name;
備注:該子查詢對檢索出的每個客戶執行一次
子查詢的優缺點:
優點:
在where子句中使用子查詢能夠編寫出功能很強并且很靈活的SQL語句
缺點:
(1)包含子查詢的select語句難以閱讀和調試。
(2)雖然對嵌套的子查詢的數目沒有限制,不過在實際使用中由于性能的限制,不能嵌套太多的子查詢。