mysql 之 知識點與細節

來源:互聯網
上載者:User

這些天又把mysql系統的看了一遍,溫故而知新……

1. char/varchar 類型區別

  • char定長字串,長度固定為建立表時聲明的長度(0-255),長度不足時在它們的右邊填充空格以達到聲明長度。當檢索到CHAR值時,尾部的空格被刪除掉
  • varchar變長字串(0-65535),VARCHAR值儲存時只儲存需要的字元數,另加一個位元組來記錄長度(如果列聲明的長度超過255,則使用兩個位元組),varchar值儲存時不進行填充。當值儲存和檢索時尾部的空格仍保留。
  • 它們檢索的方式不同,char速度相對快些

注意它們的長度表示為字元數,無論中文還是英文均是那麼長

text搜尋速度稍慢,因此如果不是特別大的內容,用char/varchar,另外text不能加預設值

2. windows中mysql內建的用戶端中查詢的內容亂碼,那是因為系統的編碼為gbk,使用前發送一條"set names gbk"語句即可

3. 小數型:float(M,D),double(M,D),decimal(M,D)  M代表總位元,不包括小數點,D代表小數位,如(5,2) -999.99——999.99

    M是小數總位元,D是小數點後面的位元。如果MD被省略,根據硬體允許的限制來儲存值。單精確度浮點數精確到大約7位小數位。

4. group by與彙總函式結合使用才有意義(sum,avg,max,min,count),group by 有一個原則,就是 select 後面的所有列中,沒有使用彙總函式的列,必須出現在 group by 後面,如果沒有出現,只取每類中第一行的結果

如果想查詢每個欄目下面最貴的商品:id,價格,商品名,種類。用select goods_id,cat_id,goods_name,max(shop_price) from goods group by cat_id;查詢的結果商品名,id是和最貴商品不匹配的,如果再加上order by哪?也是錯誤的,因為:Select語句執行有順序(文法前後也有): 

  •  where子句基於指定的條件對記錄行進行篩選; 
  • group by子句將資料劃分為多個分組; 
  • 使用聚集合函式進行計算;
  • 使用having子句篩選分組; 
  • 計算所有的運算式; 
  • 使用order by對結果集進行排序。
可以用下面查詢語句: select * from (select goods_id,cat_id,goods_name,shop_price from goods order by cat_id asc,shop_price desc) as tmp group by cat_id;

5. having  having子句在查詢過程中慢於彙總語句(sum,min,max,avg,count).而where子句在查詢過程中則快於彙總語句(sum,min,max,avg,count)。 
簡單說來: 
where子句: 
select sum(num) as rmb from order where id>10 
//只有先查詢出id大於10的記錄才能進行彙總語句 

having子句: 
select reportsto as manager, count(*) as reports from employees 
group by reportsto having count(*) > 4

以下這條語句是錯誤的:
 select goods_id,cat_id,market_price-shop_price as sheng where cat_id=3 where sheng>200; 應改為:
 select goods_id,cat_id,market_price-shop_price as sheng where cat_id=3 having sheng>200;  where針對錶中的列發揮作用,查詢資料,having針對查詢結果中的列發揮作用,篩選資料

看下面的一道面試題:

有下面一張表

查詢:有兩門及兩門以上不及格成績同學的平均分


起初用的以下語句: select name,count(score<60) as s,avg(score) from stu group by name having s>1;這條語句是不行的

首先弄清以下2點:

a,count(exp) 參數無論是什麼,查詢的都是行數,不受參數結果影響如

b,

可以用如下語句,將count換成sum:

或者:select name,avg(score) from stu group by name having sum(score<60)>1;寫法

6. 子查詢

   a. where 子查詢:把內層查詢的結果作為外層查詢的比較條件。eg:查詢最新的商品

select max(goods_id),goods_name from goods;報錯:Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns
is illegal if there is no GROUP BY clause

可以用這樣的查詢:select goods_id,goods_name from goods where goods_id=(select max(goods_id) from goods);

查詢每個欄目下的最新商品: select goods_id,cat_id,goods_name from goods where goods_id in(select max(goods_id) from goods group by cat_id);

   b.from 型子查詢:把內層查詢結果當成暫存資料表,供外層sql重新查詢(暫存資料表必須加一個別名)
查詢每個欄目下最新商品  select * from (select goods_id,cat_id,goods_name from goods order by cat_id asc,goods_id desc) as t group by cat_id;
5中 查詢掛科兩門及以上同學的平均分   select sname from (select name as sname from stu) as tmp;

    c. exists子查詢:把外層查詢的結果變數,拿到內層,看內層的查詢是否成立

查詢有商品的欄目:select cat_id,cat_name from category where exists
(select * from goods where goods.cat_id=category.cat_id);

由於沒有條件,將會查出所有欄目: select cat_id,cat_name from category where exists (select * from goods); 用in也可實現

7. in(v1,v2-----)    between v1 and v2(包括v1,v2)   like(%,_)       order by column1(asc/desc),column2(asc/desc)先按第一個排序,然後在此基礎上按第二個排序

8. union 把兩次或多次查詢結果合并起來

  • 兩次查詢的列數一致 ,對應列的類型一致
  • 列名不一致時,取第一個sql的列名
  • 如果不同的語句中取出的行的值相同,那麼相同的行將會合并(去重複),如果不去重用union all來指定 
  • 如果子句中有order by,limit 子句必須加(),

select * from ta union all select * from tb;
   取第四欄目商品,價格降序排列,還想取第五欄目商品,價格也按降序排列
   (select goods_id,cat_id,goods_name,shop_price from  goods where cat_id=4 order by shop_price desc) union (select goods_id,cat_id,goods_name,shop_price from goods          where cat_id=5 order by shop_price desc);
   推薦放到所有子句之後,即:對最終合并的結果來排序
        ( select goods_id,cat_id,goods_name,shop_price from  goods where cat_id=4 order by shop_price desc) union (select goods_id,cat_id,goods_name,shop_price from                   goods where cat_id=5 order by shop_price desc);
9. 串連查詢
 左串連:
 select column1,column2,columnN from ta left join tb on ta列=tb列[此處表串連成一張大表,完全當成普通的表看]
 where group,having....照常寫
 右串連:
 select column1,column2,columnN from ta right join tb on ta列=tb列[此處表串連成一張大表,完全當成普通的表看]
 where group,having....照常寫
 內串連:
 select column1,column2,columnN from ta inner join tb on ta列=tb列[此處表串連成一張大表,完全當成普通的表看]
 where group,having....照常寫

 左串連以左表為準,去右表找匹配資料,沒有匹配的列用null補齊,有多個的均列出

如有下兩表:


 select boy.*,girl.* from boy left join girl on boy.flower=girl.flower;
結果:


 左右串連可以相互轉化,推薦用左串連,資料庫移植方便
內串連:查詢左右表都有的資料(左右串連的交集) 選取都有配對的組合 

左或右串連查詢實際上是指定以哪個表的資料為準,而預設(不指定左右串連)是以兩個表中都存在的列資料為準,也就是inner join 

mysql不支援外串連 outer join 即左右串連的並集

當多個表中都有的欄位要指明哪個表中的欄位

三個表串連查詢 brand,goods,category
select g.goods_id,cat_name,g.brand_id,brand_name,goods_name from goods g left join brand b on b.brand_id=g.brand_id left join category c on g.cat_id=c.cat_id;

10. 事務transaction:引擎innodb acid

          start transaction;

  sql語句

 commit(提交)/roolback(復原)
     注意有一些語句會造成事務的隱式提交,比如start transaction
11.Database Backup與恢複  mysql 內建的工具:mysqldump
匯出t庫下表:
mysqldump -u 使用者名稱 -p 密碼 庫名 表1 表2 表n > 地址
eg: mysqldump -u root -p 123456 test boy > d:\boy.sql
匯出所有表:
mysqldump -u 使用者名稱 -p 密碼 庫名 > 地址
以庫為單位匯出:
mysqldump -u 使用者名稱 -p 密碼 -B 庫1 庫2 庫n > 地址
匯出所有庫
mysqldump -u 使用者名稱 -p 密碼 -A > 地址

恢複資料庫 source 地址
12:預存程序:把一段代碼封裝起來,當要執行這一段代碼的時候,可以通過調用該預存程序來實現
在封裝的語句體裡面可以用if/else,case,while等控制結構。
可以進行sql編程
 顯示所有預存程序:show procedure status;
 drop procedure 名字           delimiter $

 create procedure p1()
 begin
 select * from boy;
 end$
調用: call 名字()
 create procedure p2(num int)
 begin
 select * from boy where id>num
 end$

 create procedure p2(num int,level char(1))
 begin
 if j='h' then
 select * from boy where id>num
 else
 select * from g where id<num;
 end if;
 end$

13.視圖view 由查詢結果形成的一張虛擬表 

如果某個查詢結果出現的非常頻繁,也就是拿這個結果當做進行子查詢出現頻繁,可以把這個結果做成一個視圖
create view 視圖名 as select語句         
14. 觸發器:trigger,監視某種情況並觸發某種操作
四要素:監視地點(table),監視事件(insert/update/delete),觸發時間after/before,觸發事件(insert/update/delete)
文法:create trigger triggerName
      after/before insert/update/delete on 表名
      for each row
      begin
      sql語句 #一句或多句(insert/update/delete),以;結束
      end;
如何在觸發器引用行的值
對於insert:新增的行用new來表示,行中的每一列的值用new.列名來表示
對於delete:刪除的行用old來表示,行中的每一列的值用old.列名來表示
對於update:修改的行 修改前行的值用old來表示,修改後的用new
訂單表與商品表
 #買三隻羊
 #監視地點:o表
 #監視操作:insert
 #觸發振作:update
 #觸發時間:after
delimiter $
create trigger tg1
after insert on order
for each row
begin
update goods set num=num-new.much where id=new.gid;   #much/gid 是order中的列
end$


before執行某些操作之前驗證
create trigger tg1
before insert on order
for each row
begin 
if new.much>100 then
set new.much=5;
end if;
update goods set num=num-new.much where id=new.gid;   #much/gid 是order中的列
end$



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.