Mysql入門學習筆記07—Mysql 相關案例以及面試題整理

好久好久之前學習mysql的筆記記錄,很隨意,但都是本身記錄的,但願對須要的人有所幫助。 php

    本文使用word2013編輯併發布 html

    Postbird | There I am , in the world more exciting! mysql

Postbird personal website .www.ptbird.cn linux

 

 

生活中的常識: 記帳. 程序員

帳:就是數據/信息, web

記帳-->就是儲存數據/信息 面試

 

生活中,帳通常記在哪兒呢? sql

好比:帳本上, 門上,牆上.日曆上. chrome

 

問上:10/12,老孫頭借豆種50斤 數據庫

 

不管記在哪兒: 記錄的都是信息, 變化的只是信息的載體.

 

隨着現代社會數據的急劇增多,咱們用更高效的記錄信息的方式.

 

來一個班級學生檔案

姓名,年齡,家鄉

 

 

 

 

 

60個學生,就須要60個紙片, 並且這60個紙片,上面字有重複的. 姓名/年齡/家鄉

信息有冗餘,想個辦法更讓信息更有條理.

 

姓名

年齡

家鄉

張三

22

懷柔

李四

24

密雲

 

好處:再多一個學生的話,只須要添加一行數據, 姓名/年齡/家鄉不用重寫了.

 

班級要考試,考試成績,也要記錄起來

姓名

科目

成績

張三

語文

68

李四

思想品德

23

 

 

如今這一個班級裏, 有檔案表/成績表/違紀表/就業登記表.......

這些表,都是用來管理公益1期班的信息用的.

 

所以,這些表,放在一個檔案袋裏-------檔案袋是 數據庫

 

公益1期有檔案袋(庫1), 公益2期有檔案袋(庫2) -----> 交給王大嬸子來管理

王大嬸管理着 許多庫, 咱們想要數據時,找王大嬸.

王大嬸子 -->數據庫服務器

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一臺服務器下有多個庫,一個庫下有1到多張表, 表有多行多列的數據.

做爲WEB開發程序員, 和表的操做相對多.

數據庫服務器是否是mysql呢?

答: 對於數據庫存儲數據來講,國際上有sql標準.

如:列類型,sql語法等是有ISO標準的.

不少軟件開發商,遵照sql標準,來開發一套軟件,用來儲存和管理數據.

這套軟件,就能夠稱爲數據庫管理系統.

 

就比如說,看網頁能夠用 firefox,IE,chrome,

管理數據呢,能夠用mysql, oracle,IBM DB2, sqlite, postgresql

這些軟件都可以用來管理數據.

 

數據庫大致上要遵循sql標準,但未必100%遵循.

答:不是的,各廠商的產品可能對sql標準的執行有微小差別.

好比 mysql就沒有全鏈接 full join, 沒有sql server中的 top N這種用法

就好像,html有w3c標準來約束,但各瀏覽器也有解析不兼容的地方,可是少數.

 

爲何要先用mysql來學習?

答:

1:mysql和linux php,apache,配合緊密,LAMP架構.

2:mysql開源,免費.

 

請同窗們有時間也能夠關注一下postgresql

答:postgresql也是一個開源數據庫,並且sql標準執行方面,比mysql要嚴格.

Mysql-->賣給->sun-->oracle, 版權開源方面前途未卜.

 

 

安裝Mysql,裝哪個版本?

答:對於軟件,尤爲是開源軟件,不要追求最新的版本.

每每最新的版本,意味着bug多,新用戶每每成了"小白鼠"

 

開源軟件的版本,通常會有beta版,stable版.

咱們儘可能選用穩定版.

 

目前,比較穩定的2個版本,mysql5.1, mysql5.5

鏈接數據庫:以命令行鏈接爲例:

注意:若是在命令提示下,出現以下提示:

則說明:沒有配置環境變量,致使系統找不到mysql.exe.

解決:

1:配置環境變量,指定mysql\bin目錄

2:每次進入到mysql\bin目錄,再運行mysql

 

3: 如何鏈接服務器

服務器地址( 可用IP,域名) : 端口(3306)

用戶名

密碼

Mysql -h localhost -uUserName -pPassWd

-h 若是不寫,則默認連localhost

 

若是看到下面的圖標

則說明鏈接服務器成功了.

 

 

澄清一個概念

鏈接成功後,:命令行黑窗口 和 mysql服務器是什麼關係?

答: 客戶端 client --> 服務端 server的關係.

 

就好像 你的瀏覽器與--->163網站的服務器的關係同樣.

 

還有沒有其餘mysql客戶端?

答:有,navcat,mysqlfront,phpMyAdmin,SQLyogEnt入門最基本語句

 

當連上服務器後,咱們首先面對的是?

答:是庫,庫有1個或多個,所以咱們要想對錶/行作操做的話,

得先選庫.

 

查看一下全部的庫,怎麼辦?

Mysql>Show databases;

 

選庫語句: Use 庫名

 

建立一個數據庫: create database 數據庫名 [charset 字符集]

 

刪除一個數據庫: drop database 數據庫名;

 

把數據庫改更名?

Mysql中,表/列能夠更名,database不能更名.

phpMyAdmin彷佛有這功能? 他是建新庫,把全部表複製到新庫,再刪舊庫完成的.

 

 

當選了庫以後,咱們面對的是表

查看庫下面的全部表: show tables;

 

先給你們提供一個簡單的建表語句,供練習用

create table stu (

snum int,

sname varchar(10)

)engine myisam charset utf8;

/// engine是指表引擎,和性能特色相關,此處先照抄.

 

刪除表: drop table stu;

 

修改表名:

 

清空表數據: truncate 表名

 

Truncate和delete是有區別的,

在於 truncate至關於刪表再重建一張一樣結構的表,操做後獲得一張全新表.

而delete是從刪除全部的層面來操做的.

Trucate至關於把舊的學籍表扔了重畫一張,

Delete至關於用橡皮把學籍表的數據庫擦掉.

若是決定全清空的下,truncate速度更快一些.

 

 

查看錶結構

答: desc tableName; //查看錶結構

Id

title

 

 

 

12: 解決字符集問題:

默認建表通常用utf8, 而咱們在windows下窗口是GBK的,

所以,須要聲明字符集.

Set names gbk;

 

發現的1小問題

語句打錯之後應該退出本語句,再繼續打新語句.也能夠打\c,退出本語句.

 

如何破解數據庫的密碼:

1:經過任務管理器或者服務管理,關掉mysqld(服務進程)

2:經過命令行+特殊參數開啓mysqld

Mysqld --skip-grant-tables

3:此時,mysqld服務進程已經打開,而且,不須要權限檢查.

4:mysql -uroot 無密碼登錄服務器.

5: 修改權限表

A: use mysql;

B:update user set Password = password('11111') where User = 'root';

C:flush privileges;

6:經過任務管理器,或服務管理,關掉mysqld服務進程.

7:再次經過服務管理,打開mysql服務.

便可用修改後的新密碼登錄.

 

 

增刪改查基本語法學習

 

增: insert

Insert 3問:

1: 插入哪張表?

2: 插入哪幾列?

3: 這幾列分別插入什麼值?

 

Insert into TableName

(列1,列2.... 列n)

Values

(值1,值2,....值n)

 

值 與 列,按順序,一一對應

 

 

特殊: insert語句 允不容許不寫列名

答: 容許.

若是沒有聲明列明,則默認插入全部列.

所以,值應該與所有列,按順序一一對應.

 

例:建一張工資登記表

 

2:插入部分列

 

3:插入全部列

注:文中的set names gbk;是爲了告訴服務器,客戶端用的GBK編碼,防止亂碼.

 

4:插入全部的列的簡單寫法.

改: Update 語句

Update 4問

改哪張表?

改哪幾列的值?

分別改成什麼值?

在哪些行生效?

 

語法:

Update 表名

Set

列1 = 新值 1,

列2 = 新值2,

列n = 新值n.....

Where expr

例:

 

 

刪除: delete

Delete 2問

從哪張表刪除數據?

要刪除哪些行?

 

語法:

Delete from 表名 where expr

 

例:

 

查: select

查詢3問

1:查哪張表的數據?

2:查哪些列的數據?

3:查哪些行的數據?

 

語法:

Select 列1, 列2, 列3,...列n

From 表名

Where expr;

注: 若是取一張表的全部列, 能夠用 * 代替全部列

怎麼建表?

以在A4紙上建表爲例,

學號

姓名

家鄉

入學年份

自我介紹

001

張三

衡水

2012

 
         

 

分析:咱們只要把第一行,表頭建好了,這張表也就完成了.

至於下面的001,張三,這不是表的概念,而是表中儲存的數據.

 

其實,建表過程,就是一個畫表頭的過程,

從術語上講,這張表有5個列,

建表的過程,就是一個 聲明字段 過程

 

 

那麼建表和列類型又有什麼關係呢?

分析: 再看上面的表,A4紙是數據的存儲空間,而A4的大小是有限的.

請問:你準備給學號留多寬? 給姓名留多寬? 自我介紹又留多寬?

 

天然的, 姓名若是留的過寬,好比20個字都能存,可是通常人的姓名,就三四字---浪費了.

若是留的過窄,致使存不下,更有問題.

 

對應的,A4紙空間有限,硬盤空間也有限,

咱們建列時,天然想的是------可以容納放置的內容,可是又不浪費.

 

存儲一樣的數據,不一樣的列類型,所佔據的空間和效率是不同的--這就是咱們建表前要前列類型的意義.

 

 

因此---重點學列類型的存儲範圍與佔據的字節關係.

 

 

 

列類型學習

mysql三大列類型

數值型

整型

Tinyint/ smallint/ mediumint/int/ bigint(M) unsigned zerofill

 

整型系列所佔字節與存儲範圍的關係.

定性: 佔字節越多,存儲範圍越大.

下圖: 是具體的數字分析

 

Tinyint 1個字節 8個位 0 - 2^8-1 , 0-255

-2^7 ----> +2^7-1

 

 

分析:

Smallint 2個字節 , 16位 0----2^16-1 = 65535

-2^15 ---> +2^15-1, -32768 -> 32767

 

通常而言,設某類型 N字節

N字節 , 8N位.

0 ----> 2^8N-1

 

-2^(8N-1) ---> +2^(8N-1) -1;

 

對於int型 : 佔的字節越多,存儲的範圍也越大.

整型系統的可選參數 : XXint(M) unsigned zerofill

例: age tinyint(4) unsigned ,或者 stunum smallint(6) zerofill;

Unsigned: 表明此列爲無符號類型, 會影響到列的存儲範圍. (範圍從0開始)

(不加unsinged, 則該列默認是有符號類型,範圍從負數開始)

 

 

 

Zerofill: 表明0填充, 即: 若是該數字不足參數M位, 則自動補0, 補夠M位.

1: 若是沒有zerofill屬性, 單獨的參數M,沒有任何意義.

2:若是設置某列爲zerofill,則該列已經默認爲 unsigned,無符號類型.

 

 

 

小數型

 

Float(M,D),decimal(M,D)

M叫"精度" ---->表明"總位數",而D是"標度",表明小數位.(小數右邊的位數)

 

 

浮點數佔多大的空間呢

答: float 能存10^38 ,10^-38

若是M<=24, 點4個字節,不然佔8字節

 

用來表示數據中的小數,除了float---浮點.

還有一種叫定點decimal,定點是把整數部分, 和小數部分,分開存儲的.

比float精確,他的長度是變化的.

 

空間上的區別:

Float(M,D), M<=24, 4個字節, 24 <M <=53, 8個字節

Decimal () ,變長字節.

 

區別: decimal比float精度更高, 適合存儲貨幣等要求精確的數字,

見下例:

字符串型

Char(M)

Varchar(M)

Text 文本類型

 

日期時間類型

Date 日期

Time 時間

Datetime 時間時間類型

Year 年類型

 

 

 

Mysql 字符串類型

Char 定長類型

Char(M) , M 表明寬度, 0<=M<=255之間

例:Char(10) ,則能輸入10個字符.

 

Varchar 變長類型

Varchar(M), M表明寬度, 0<=M<=65535(以ascii字符爲例,utf822000左右)

 

類型

類型

寬度

可存字符

實存字符(i<=M)

實佔空間

利用率

Char

M

M

i

M

i/M <= 100%

Varchar

M

M

i

i字符+(1-2)字節

i/(i+1-2) < 100%

 

0000000000

00\0\0\0\0\0 (char型,若是不夠M個字符,內部用空格補齊,取出時再把右側空格刪掉)

注:這意味着,若是右側自己有空格,將會丟失.

 

Varchar(10)

[2]張三

[3]二麻子

[4]司馬相如

 

Char(8)

00000000

'Hello '

'hello '

Char(M)如何佔據M個字符寬度?

答: 若是實際存儲內容不足M個,則後面加空格補齊.

取出來的時候, 再把後面的空格去掉.(因此,若是內容最後有空格,將會被清除).

 

 

速度上: 定長速度快些

 

注意: char(M),varchar(M)限制的是字符,不是字節.

即 char(2) charset utf8, 能存2個utf8字符. 好比'中國'char與varchar型的選擇原則:

1:空間利用效率, 四字成語表, char(4),

我的簡介,微博140字, varchar(140)

2:速度

用戶名: char

 

 

Char 與 varchar相關實驗

 

 

Text : 文本類型,能夠存比較大的文本段,搜索速度稍慢.

所以,若是不是特別大的內容,建議用char,varchar來代替.

Text 不用加默認值 (加了也沒用).

 

Blob,是二進制類型,用來存儲圖像,音頻等二進制信息.

意義: 2進制,0-255都有可能出現.

Blob在於防止由於字符集的問題,致使信息丟失.

好比:一張圖片中有0xFF字節, 這個在ascii字符集認爲非法,在入庫的時候,被過濾了.

 

日期時間類型

Year 年(1字節) 95/1995, [1901-2155],

在insert時,能夠簡寫年的後2位,可是不推薦這樣.

[00-69] +2000

[70-99] + 1900,

即: 填2位,表示 1970 - 2069

 

Date 日期 1998-12-31

範圍: 1000/01/01 ,9999/12/31

 

Time 時間 13:56:23

範圍: -838:59:59 -->838:59:59


datetime 時期時間 1998-12-31 13:56:23

範圍: 1000/01//01 00:00:00 ---> 9999:12:31 23:59:59

 

timestamp

 

時間戳:

是1970-01-01 00:00:00 到當前的秒數.

通常存註冊時間,商品發佈時間等,並非用datetime存儲,而是用時間戳.

由於datetime雖然直觀,但計算不便.

 

 

建表案例,某高端白領私密社交網站

 

定長與變長分離

經常使用與不經常使用列分離

 

主鍵

用戶名

性別

體重(KG)

生日

工資

上次登錄

我的簡介

id

Username

gender

weight

birth

salary

Lastlogin

intro

 

列名稱

列類型

默認值

是否主鍵

Id

Int unsigned

 

PRI

Username

Varchar(20)

''

 

gender

Char(1) /tinyint/enum(男/女)

   

weight

Tinyint unsigned

   

Birth

Date

   

Salary

Decimal(8,2)

   

lastlogin

Datetime

   

intro

Varchar(1500)

   

 

這張表不夠好,能夠優化

分析:這張表除了username/intro列以外,每一列都是定長的.

咱們不妨讓其全部列,都定長,能夠極大提升查詢速度.

列名稱

列類型

默認值

是否主鍵

Id

Int unsigned

 

PRI

Username

char(20)

''

 

gender

Char(1) /tinyint

   

weight

Tinyint unsigned

   

Birth

Date

   

Salary

Decimal(8,2)

   

lastlogin

Int unsigned

   

 

Username char(10) 是會形成空間的浪費,可是提升的速度,值.

Intro char(1500) 卻浪費的太多了,另外一方面,人的簡介,一旦註冊完,改的頻率也並不高.

咱們能夠把 intro列單獨拿出來,另放一張表裏.

 

列名稱

列類型

默認值

是否主鍵

Id

Int unsigned

 

PRI

Username

char(20)

''

 

intro

Varchar(1500)

   

 

在開發中,會員的信息優化每每是 把頻繁用到的信息,優先考慮效率,存儲到一張表中.

不經常使用的信息和比較佔據空間的信息,優先考慮空間佔用,存儲到輔表中.建表語法

所謂建表就是一個聲明列的過程.

create table 表名 (

列名1 列類型1 列1參數,

列名2 列類型2 列2參數,

....

...

列名n 列類型n 列n參數

)engine myisam/innodb/bdb charset utf8/gbk/latin1...

 

 

修改表的語法

一張表,建立完畢,有了N列.

以後還有可能要增長或刪除或修改列

 

Alter table 表名 add 列名稱 列類型 列參數; [加的列在表的最後]

例: alter table m1 add birth date not null default '0000-00-00';

Alter table 表名 add 列名稱 列類型 列參數 after 某列 [把新列加在某列後]

例: alter table m1 add gender char(1) not null default '' after username;

 

Alter table 表名 add 列名稱 列類型 列參數 first [把新列加在最前面]

例: alter table m1 add pid int not null default 0 first;

 

 

刪除列:

Alter table 表名 drop 列名

 

 

修改列類型:

Alter table 表名 modify 列名 新類型 新參數

例:alter table m1 modify gender char(4) not null default '';

 

修改列名及列類型

Alter table 表名 change 舊列名 新列名 新類型 新參數

例:alter table m1 change id uid int unsigned;

 

做業: 讓咱們建一個電子商城, 如何來設計商品表.

再把商城表的字段,一個個刪掉,再一個個加上.

並穿插改列操做.

 

??若是列類型改變了,致使數據存不下怎麼辦?

好比,int 改爲smallint列. 若是不匹配,數據將會丟失,或者在mysql的strict_mode下,修改不了.

爲何建表時,加not null default '' / default 0

答:不想讓表中出現null值.

 

爲何不想要的null的值

答:

很差比較,null是一種類型,比較時,只能用專門的is null 和 is not null來比較.

碰到運算符,一概返回null

效率不高,影響提升索引效果.

 

所以,咱們每每,在建表時 not null default ''/0Select 5種子句詳解

1:where子句 條件查詢

 

查出一張表的全部行,全部列

Select * from tableName;

 

查出一張表的全部行,部分列.

Select id,name,salary from tableName

 

查出一張表的全部列,部分行(id >=2 的行)

Select * from tableName where id >=2;

 

 

 

 

模糊查詢:

案例:想查找"諾基亞"開頭的全部商品

Like->像

 

% --> 通配任意字符

'_' --> 單個字符

 

查詢模型(重要)

列就是變量,在每一行上,列的值都在變化.

Where條件是表達式,在哪一行上表達式爲真,

哪一行就取出來

好比下面的條件, shop_price在不一樣的行,有不一樣的值.

在哪一行時,shop_price>5000若是爲真,則這行取出來.

 

查詢結果集--在結構上能夠當成表看select count(*) from 表名, 查詢的就是絕對的行數,哪怕某一行全部字段全爲NULL,也計算在內.

而select couht(列名) from 表名,

查詢的是該列不爲null的全部行的行數.

 

用count(*),count(1),誰好呢?

其實,對於myisam引擎的表,沒有區別的.

這種引擎內部有一計數器在維護着行數.

Innodb的表,用count(*)直接讀行數,效率很低,由於innodb真的要去數一遍.

 

Group

思考:

全班同窗排隊,

校長對老師說: 統計班級同窗的姓名和平均年齡[返回1行]

語義上的疑問: 平均年齡好算,只有一個結果,可是,把誰的姓名和平均年齡放在一塊返回呢?

語義上就解釋不通,可是mysql中卻恰恰能夠取姓名,並且是把隊伍的第一位同窗的姓名返回.

 

這是mysql的一個特色,出於可移植性和規範性,不推薦這麼寫.

嚴格的講,以group by a,b,c 爲列,則select的列,只能在a,b,c裏選擇,語義上纔沒有矛盾.

 

 

having

 

Order by

當最終結果集出來後,能夠進行排序.

排序的語法:

Order by 結果集中的列名 desc/asc

 

例:order by shop_price desc ,按價格降序排列

Order by add_time asc ,按發佈時間升序排列.

 

多字段排序也很容易

Order by 列1 desc/asc , 列2 desc/asc , 列3 desc,asc

 

 

Limit 在語句的最後, 起到限制條目的做用

 

Limit [offset,] N

Offset: 偏移量,----跳過幾行

N: 取出條目

Offset,若是不寫,則至關於 limit 0,N

 

 

 

思考: 取出每一個欄目下的最新的商品???

20分鐘,1個select語句實現,

 

良好的理解模型

Where 表達式 ,把表達式放在行中,看錶達式是否爲真

列: 理解成變量,能夠運算

取出結果: 能夠理解成一張臨時表

子查詢

Where型子查詢: 指把內層查詢的結果做爲外層查詢的比較條件.

典型題:查詢最大商品,最貴商品

 

Where型子查詢

若是 where 列=(內層sql),則內層sql返回的必是單行單列,單個值

若是 where 列 in (內層sql), 則內層sql只返回單列,能夠多行.

 

From 型子查詢: 把內層的查詢結果當成臨時表,供外層sql再次查詢

典型題:查詢每一個欄目下的最新/最貴商品

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

典型題: 查詢有商品的欄目

 

 

 

 

 

集合(set)的知識

高中時學過的集合

 

集合的特色: 無序性,下面兩個集合是等價的

 

 

 

 

 

 

集合的特色:惟一性

下面這個集合是一個錯誤的集合,沒有知足惟一性.

 

 

 

 

 

集合的運算: 求並集,求交集,笛卡爾積(相乘)

 

笛卡爾積,即集合的元素,作兩兩的組合.

 

 

 

 

 

 

集合A*B = 什麼?

 

 

 

 

 

 

 

 

 

一道數學題:

集合A 有 M個元素

集合B, 有N個元素

A*B = C

C 有多少個元素? 答: M*N行表與集合的關係

 

一張表就是一個集合

每一行就是一個元素

 

疑問:集合不能重複,但我有可能兩行數據徹底同樣

答:mysql內部每一行,還有一個rowid.

 

 

兩表作全相乘

從行的角度來看: 就是2表每一行,兩兩組合.

從列的角度來看: 結果集中的列,是兩表的列名的相加.

 

做全相乘時,也能夠有針對性的取出某幾列.

 

 

左鏈接的語法:

 

假設A表在左,不動,B表在A表的右邊滑動.

A表與B表經過一個關係來篩選B表的行.

語法:

A left join B on 條件 條件爲真,則B表對應的行,取出

 

A left join B on 條件

這一塊,造成的也是一個結果集,能夠當作一張表 設爲C

既如此,能夠對C表做查詢,天然where,group ,having ,order by ,limit 照常使用

 

問:C表的能夠查詢的列有哪些列?

答: A B的列均可以查

 

 

 

 

 

 

 

/*

左鏈接 右鏈接,內鏈接的區別在哪兒?

 

*/

 

同窗見面會:

男生表

姓名

配偶

屌絲

A

李四

B

王五

C

高富帥

D

鄭七

E

 

女生表

姓名

配偶

空姐

B

大S

C

阿嬌

D

張柏芝

D

林黛玉

E

寶釵

F

 

主持人大聲說:

全部的男士,站到舞臺上,帶上本身的配偶,(沒有的拿塊牌子, 上寫NULL)

思考:張三上不上舞臺呢?

答:上,

問:張三沒有對應的行怎麼辦?

答:用NULL補齊

結果以下

姓名

配偶

女生姓名

配偶

屌絲

A

NULL

NULL

李四

B

空姐

B

王五

C

大S

C

高富帥

D

阿嬌

D

高富帥

D

張柏芝

D

鄭七

E

林黛玉

E

 

這種狀況就是 男生 left join 女生.

 

主持人說:全部女生請上舞臺,有配偶的帶着, 沒有的,寫個NULL補齊.

Select 女生 left join 男生 on 條件

 

 

左右鏈接是能夠互換的

A left join B, 就等價於 B right join A

 

注意:既然左右鏈接能夠互換,儘可能用左鏈接,出於移植時兼容性方面的考慮.

內鏈接的特色

主持人說: 全部有配偶的男生/女生,走到舞臺上來

這種狀況下: 屌絲和寶釵都出局

姓名

配偶

女生姓名

配偶

李四

B

空姐

B

王五

C

大S

C

高富帥

D

阿嬌

D

高富帥

D

張柏芝

D

鄭七

E

林黛玉

E

 

 

若是從集合的角度

A inner join B

和 left join /right join的關係

答: 內鏈接是左右鏈接的交集

 

問題:

主持人說:全部男生/女生,走上舞臺.

有配偶的,帶着配偶;

沒配偶的,拿牌子寫NULL

即:結果是左右鏈接的並集

 

這種叫作外鏈接,可是,在mysql中不支持外鏈接

 

兩道題!

1:預習union,合併結果集,完成外鏈接的效果.

2:祕籍5.4用友面試題

 

 

 

 

 

2:根據給出的表結構按要求寫出SQL語句。

Match 賽程表

字段名稱

字段類型

描述

matchID

int

主鍵

hostTeamID

int

主隊的ID

guestTeamID

int

客隊的ID

matchResult

varchar(20)

比賽結果,如(2:0

matchTime

date

比賽開始時間

Team 參賽隊伍表

字段名稱

字段類型

描述

teamID

int

主鍵

teamName

int

隊伍名稱

 

MatchhostTeamIDguestTeamID都與Team中的teamID關聯

查出 2006-6-1 2006-7-1之間舉行的全部比賽,而且用如下形式列出:

拜仁 20 不來梅 2006-6-21

 

 

3 2 2:0

2:5 1:2

 

3: 國安

2: 申花

5: 紅牛

 

 

Union:合併2條或多條語句的結果

語法:

Sql1 union sql2

 

 

可否從2張表查詢再union呢?

答:能夠,union 合併的是"結果集",不區分在自於哪一張表.

 

問:取自於2張表,經過"別名"讓2個結果集的列一致.

那麼,若是取出的結果集,列名字不同,還可否union.

答:能夠,以下圖,並且取出的最終列名,以第1條sql爲準

 

問:union知足什麼條件就能夠用了?

答:只要結果集中的列數一致就能夠.

 

問:列的類型不同,也行嗎?

答:見上題 .

     
     

       
       

 

問: union後結果集,能否再排序呢?

答:能夠的.

Sql1 union sql2 order by 字段

注意: order by 是針對合併後的結果集排的序.

 

問: 使用order by 的注意事項

以下,內層語句的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)

order by shop_price asc;

 

外層語句還要對最終結果,再次排序.

所以,內層的語句的排序,就沒有意義.

 

所以:內層的order by 語句單獨使用,不會影響結果集,僅排序,

在執行期間,就被Mysql的代碼分析器給優化掉了.

內層的order by 必須可以影響結果集時,纔有意義.

好比 配合limit 使用. 以下例.

 

思考下個問題:

查出: 第3個欄目下,價格前3高的商品,和第4個欄目下,價格前2高的商品.

用union來完成

這一次:內層的order by 發揮了做用,由於有limit ,order 會實際影響結果集,有意義.

 

若是Union後的結果有重複(即某2行,或N行,全部的列,值都同樣),怎麼辦?

答:這種狀況是比較常見的,默認會去重.

 

問:若是不想去重怎麼辦?

答: union all

 

若是mysql函數和PHP函數都實現某個功能,優先用哪個?

 

1:mysql的函數確定是要影響查詢速度.

應該在建表時,經過合理的表結構減小函數的使用.

好比 email ,按@ 先後拆分.

 

 

2:若是確實要用函數,

好比 時間的格式化

在mysql裏用date_format,在php裏用date能夠實現

優先放在業務邏輯層,即php層處理.

 

 

3:在查詢時使用了函數,最大的一個壞處,

以 date_format(A)爲例

則A列的索引將沒法使用.

 

若是你針對某列做操做,而這次查詢,又使用的此列的索引.

此時,速度將顯著變慢.

 

 

例:

sname, email 兩列

email加了索引

 

Select name,email from table where right(email,6)='qq.com';

將會致使這次查詢中, email的索引並不會產生效果.視圖 view

在查詢中,咱們常常把查詢結果 當成臨時表來看.

View是什麼? View能夠看一張虛擬表. 是表經過某種運算獲得的一個投影.

 

 

 

 

 

 

 

既然視圖只是表的某種查詢的投影,因此主要步驟在於查詢表上.

查詢的結果命名爲視圖就能夠了.

 

 

視圖的定義:

視圖是由查詢結果造成的一張虛擬表.

 

視圖的建立語法:

Create view 視圖名 as select 語句;

 

視圖的刪除語法:

Drop view 視圖名

 

爲何要視圖?

答:1:能夠簡化查詢

 

2: 能夠進行權限控制

把表的權限封閉,可是開放相應的視圖權限,視圖裏只開放部分數據

 

3: 大數據分表時能夠用到

好比,表的行數超過200萬行時,就會變慢,

能夠把一張的表的數據拆成4張表來存放.

News表

Newsid, 1,2,3,4

News1,news2,news3,news4表

 

把一張表的數據分散到4張表裏,分散的方法不少,

最經常使用能夠用id取模來計算.

Id%4+1 = [1,2,3,4]

 

好比 $_GET['id'] = 17,

17%4 + 1 = 2, $tableName = 'news'.'2'

 

Select * from news2 where id = 17;

 

還能夠用視圖, 把4張表造成一張視圖

Create view news as select from n1 union select from n2 union.........

 

 

視圖的修改

Alter view 視圖名 as select xxxxxx

 

 

視圖是表的一個影子.

表與視圖,數據變化時的相互影響問題.

 

 

視圖與表的關係

視圖是表的查詢結果,天然表的數據改變了,影響視圖的結果.

 

視圖改變了呢?

0: 視圖增刪改也會影響表

1: 可是,視圖並是老是能增刪改的.

 

視圖某種狀況下,是能夠修改的.

要求: 視圖的數據和表的數據 11對應. 就像函數的映射.

表-->推出視圖對應的數據

視圖-->推出表對應的數據

對於視圖insert還應注意,

視圖必須包含表中沒有默認值的列.

以這個例子而言,平均價來自於多行的的shop_price的計算結果.

若是pj列的值的變子,映射過去,到底修改哪幾行shop_price?

 

視圖的algorithm

Algorithm = merge/ temptable/ undefined

Merge: 當引用視圖時,引用視圖的語句與定義視圖的語句合併.

Temptable:當引用視圖時,根據視圖的建立語句創建一個臨時表

Undefined:未定義,自動,讓系統幫你選.

 

Merge,意味着視圖只是一個規則,語句規則, 當查詢視圖時,

把查詢視圖的語句(好比where那些)與建立時的語句where子句等合併,分析.

造成一條select 語句.

例: 建立視圖的語句:

mysql> create view g2 as select goods_id,cat_id,goods_name,shop_price from goods where shop_price>2000

查詢視圖的語句:

select * from g2 where shop_price < 3000;

 

最終執行的語句:

select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000 and shop_price < 3000

 

而temptable是根據建立語句瞬間建立一張臨時表,

而後查詢視圖的語句從該臨時表查數據.

create algorethm=temptable view g2 as select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000

查詢視圖的語句:

select * from g2 where shop_price < 3000;

 

最終執行的2句話: 取數據並放在臨時表,而後去查臨時表.

Select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000;

========> temptable

 

再次查臨時表

Select * from temptable where shop_price< 3000

 

 

字符集與校對集

Create table 表名(

列聲明

) charset utf8;

 

Mysql的字符集設置很是靈活

能夠設置服務器默認字符集

數據庫默認字符集

表默認字符集

列字符集

若是某一個級別沒有指定字符集,則繼承上一級.

 

以表聲明utf8爲例:

存儲的數據在表中,最終是utf8;

'中國',

 

 

 

1:告訴服務器,我給你發送的數據是什麼編碼的? character_set_client

2:告訴轉換器,轉換成什麼編碼? Character_set_connection

3:查詢的結果用什麼編碼? Character_set_results

 

若是以上3者都爲字符集N, 則能夠簡寫爲 set names N

 

 

 

推論: 什麼時將會亂碼?

1: client聲明與事實不符

2:results與客戶端頁面不符的時候.

 

什麼時間將會丟失數據?

Connetion和服務器的字符集比client小時.

 

 

校對集: 指字符集的排序規則

一種字符集能夠有一個或多個排序規則.

以Utf8爲例, 咱們默認使的utf8_general_ci 規則,也能夠按二進制來排, utf8_bin

 

怎麼樣聲明校對集?

Create table ()... Charset utf8 collate utf8_general_ci;

 

注意:聲明的校對集必須是字符集合法的校對集.

 

 

 

 

 

存儲引擎

一部電影, mp4,wmv,avi,rmvb,flv, 一樣的一部電影,在硬盤上有不一樣的存儲格式,

所佔空間與清晰程度也不同.

 

表裏的數據存儲在硬盤上,具體如何存儲的?

存儲的方式方法也有多種.

 

對於用戶來講 一樣一張表的數據,不管用什麼引擎來存儲,用戶看到的數據是同樣的.

可是對於服務器來講,有區別.

 

 

經常使用的表的引擎

Myisam ,批量插入速度快, 不支持事務,鎖表

Innodb, 批量插入相對較慢,支持事務,鎖行.

 

全文索引:目前5.5版本,myisam,innodb都已經支持

事務:

通俗的說事務: 指一組操做,要麼都成功執行,要麼都不執行.---->原子性

在全部的操做沒有執行完畢以前,其餘會話不可以看到中間改變的過程-->隔離性

事務發生前,和發生後,數據的總額依然匹配----->一致性

事務產生的影響不可以撤消------>持久性

若是出了錯誤,事務也不容許撤消, 只能經過"補償性事務"

 

轉帳

李三: --->支出 500, 李三 -500

趙四: ---->收到500, 趙四 +500

 

關於事務的引擎:

選用innodb /bdb

 

 

開啓事務: start transaction;

Sql....

Sql....

 

Commit 提交

 

rollback 回滾

 

注意: 當一個事務commit,或者rollback就結束了

 

注意:有一些語句會形成事務的隱式的提交,好比 start transaction

事務 的基本原理 (瞭解)

 

不用事務,直接做用於表

 

 

 

 

 

 

 

 

用了事務以後,

 

 

觸發器:trigger, 槍擊,扳擊,引線的意思

一觸即發,

做用: 監視某種狀況並觸發某種操做.

 

 

觀察如下場景:

一個電子商城,

商品表, g

主鍵

商品名

庫存

1

電腦

28

2

自行車

12

 

訂單表, o

訂單主鍵

商品外鍵

購買數量

1

2

3

2

1

5

 

完成下單與減小庫存的邏輯

Insert into o (gid,num) values (2,3); // 插入語句

Update g set goods_num = goods_num - 3 where id = 2;// 更新過程

 

這兩個邏輯能夠當作一個總體,或者說, insert ---> 引來 update

 

 

用觸發器能夠解決上述問題.

咱們能夠監視某表的變化,當發生某種變化時,觸發某個操做.

 

 

觸發器:

能監視: 增,刪,改

觸發操做: 增,刪,改

 

四要素:

監視地點

監視事件

觸發時間

觸發事件

 

建立觸發器的語法

Create trigger triggerName

After/before insert/update/delete on 表名

For each row #這句話是固定的

Begin

Sql語句; # 一句或多句,insert/update/delete範圍內

End;

 

刪除觸發器的語法:

Drop trigger 觸發器名

 

查看觸發器

Show triggers

 

如何在觸發器引用行的值

對於insert而言, 新增的行 用new 來表示,

行中的每一列的值 ,用new.列名來表示.

 

對於 delete來講, 本來有一行,後來被刪除,

想引用被刪除的這一行,用old,來表示, old.列名,就能夠引用被刪行中的值.

 

對於update來講,

被修改的行,

修改前的數據 ,用 old來表示, old.列名引用被修改以前行中的值

修改後的數據,用new 來表示, new.列名引用被修改以後行中的值

 

 

觸發器裏after 和before的區別

After 是先完成數據的增,刪,改再觸發,

觸發的語句晚於監視的增,刪,改,沒法影響前面的增刪改動做.

 

Before是先完成觸發,再增刪改,

觸發的語句先於監視的增,刪,改發生,咱們有機會判斷,修改即將發生的操做.

 

 

典型案例:

對於所下訂單,進行判斷,若是訂單的數量 > 5 ,就認爲是惡意訂單,

強制把所訂的商品數量改爲5

 

備份與恢復

系統運行中, 增量備份,與總體備份.

例: 每週日總體備份一次, 週一到週六備份當天.

若是週五出了問題,能夠用週日的總體 + 週一,二,三,四來恢復.

 

備份的工具

有第3方的收費備份工做,

目前咱們所學的是系統自帶的備份功能, mysqldump

 

Mysqldump能夠導出

 

例1: 導出mugua庫下面的表

Mysqldump -u用戶名 -p密碼 庫名 表1 表2 表3 > 地址/備份文件名稱

導出的是建表語句及insert語句

 

例2:如何導出一個庫下面的全部表?

Mysqldump -u用戶名 -p密碼 庫名 > 地址/備份文件名稱

 

例3: 如何導出以庫爲單位導出?

Mysqldump -u用戶名 -p密碼 -B 庫1 庫2 庫3 > 地址/備份文件名稱

 

例4: 如何導出全部庫?

Mysqldump -u用戶名 -p密碼 -A > 地址/備份文件名稱

 

恢復:

1:登錄到mysql命令行

對於庫級的備份文件

Mysql> source 備份文件地址

 

對於表級的備份文件

Mysql > use 庫名

Mysql> source 備份文件地址

 

2:不登錄到mysql命令行

針對庫級的備份文件

Mysql -u用戶名 -p密碼 < 庫級備份文件地址

 

針對表級的備份文件

Mysql -u用戶名 -p密碼 庫名 < 表級備份文件地址

 

索引

索引:是針對數據所創建的目錄.

做用: 能夠加快查詢速度

負面影響: 下降了增刪改的速度.

 

案例:

設有新聞表15列,10列上有索引,共500W行數據, 如何快速導入?

1:把空表的索引所有刪除

2:導入數據

3:數據導入完畢後,集中建索引.

 

索引的建立原則:

1:不要過分索引

2:在where條件最頻繁的列上加.

3:儘可能索引散列值,過於集中的值加索引意義不大.

 

索引的類型

普通索引: index 僅僅是加快查詢速度.

惟一索引: unique index 行上的值不能重複

主鍵索引: primary key 不能重複.

主鍵必惟一,可是惟一索引不必定是主鍵.

一張表上,只能有一個主鍵, 可是能夠用一個或多個惟一索引.

全文索引 : fulltext index

(上述3種索引,都是針對列的值發揮做用,但全文索引,能夠針對值中的某個單詞,好比一篇文章,)

 

創建索引

能夠在建表時,直接聲明索引,即在列聲明完畢後,聲明索引.

例以下:

create table test5 (

id int,

username varchar(20),

school varchar(20),

intro text,

primary key (id),

unique (username),

index (school),

fulltext (intro)

) engine myisam charset utf8;

 

查看一張表上全部索引

Show index from 表名

 

創建索引

Alter table 表名 add index /unique/fulltext [索引名] (列名)

Alter table 表名 add primary key (列名) // 不要加索引名,由於主鍵只有一個

 

刪除索引

刪除非主鍵索引:Alter table 表名 drop index 索引名;

刪除主鍵: alter table 表名 drop primary key

 

 

關於全文索引的用法

Match (全文索引名) against ('keyword');

 

關於全文索引的中止詞

全文索引不針對很是頻繁的詞作索引,

如this, is, you, my等等.

 

全文索引:在mysql的默認狀況下, 對於中文意義不大.

由於英文有空格,標點符號來拆成單詞,進而對單詞進行索引.

而對於中文,沒有空格來隔開單詞,mysql沒法識別每一箇中文詞.

 

 

 

 

存儲過程: procedure

概念相似於函數,就是把一段代碼封裝起來,

當要執行這一段代碼的時候,能夠經過調用該存儲過程來實現.

在封裝的語句體裏面,能夠用if/else, case,while等控制結構.

能夠進行sql編程.

 

查看現有的存儲過程:

Show procedure status

 

刪除存儲過程

Drop procedure 存儲過程的名字

 

調用存儲過程

Call 存儲過程名字();

 

 

第1個存儲過程 ,體會"封裝sql"

第2個存儲過程, 體會"參數"

 

第3個存儲過程,體會"控制結構"

第4個存儲過程,體會"循環"

 

在mysql中,存儲過程和函數的區別,

一個是名稱不一樣,

二個就是存儲過程沒有返回值.

相關文章
相關標籤/搜索