mysql輕快入門

生活中的常識: 記帳.php

帳:就是數據/信息,html

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

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

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

 

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

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


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

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

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

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

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

 

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

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

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

 

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

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

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

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

 

爲何要先用mysql來學習?

:

1:mysqllinux 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 表名

 

 

 

Truncatedelete是有區別的,

在於 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 () ,變長字節.

 

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

見下例:

 

字符串型 

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, 能存2utf8字符. 好比'中國'charvarchar型的選擇原則:

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.   若是不匹配,數據將會丟失,或者在mysqlstrict_mode,修改不了.


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

:不想讓表中出現null.

 

爲何不想要的null的值

:

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

碰到運算符,一概返回null

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

 

所以,咱們每每,在建表時 not null default ''/0
Select 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

 

 

 

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

select * from goods order by goods_id desc limit 1;

 

 

良好的理解模型

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中不支持外鏈接

 

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.

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

 

 

 

問: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函數和編程語言(c、c++)函數都實現某個功能,優先用哪個?

 

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

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

好比 email ,@ 先後拆分.

 

 

2:若是確實要用函數,

好比 時間的格式化

mysql裏用date_format,在編程語言(如php裏用date能夠實現)

優先放在業務邏輯層,即編程語言層處理.

 

 

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是先完成觸發,再增刪改,

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

 begin

declare id int default  0;//定義變量

set id=new.id//賦值

select count(*) into id from t1;//查詢結果給id

while 條件[repeat...util,loop ....]

end while

end 

典型案例:

對於所下訂單,進行判斷,若是訂單的數量 > 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,存儲過程和函數的區別,

一個是名稱不一樣,

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

delimiter / ========>把;改成/

create procedure addemp1(in name varchar(25),in age int(3),out last_id int)
begin
insert into emp1(name,age) values(name,age);
select count(*) into last_id from emp1;
end

/

 

調用:

call  addemp1('bwb',10,@last_id)/

select @last_id 獲得返回值

相關文章
相關標籤/搜索