[TOC]python
數據庫
""" 一、什麼是數據庫:管理數據的系統 - 安裝某種管理數據的系統 - 管理的對象本質是文件 二、存儲數據的位置:內存、硬盤 三、什麼是系統:運行在硬件基礎上,管理其餘軟件 """ # 數據庫的組成 """ 庫:存放多張表 - 文件夾 表:包含多條相同結構的記錄 - 文件 記錄:包含多個key-value鍵值對的一條數據 - 二進制數據 字段:描述信息 - 信息自己 == key-value - 二進制數據 stu id name age gender 1 Bob 18 男 2 Tom 17 女 ... teacher ... """
數據庫的分類
# 1)關係與非關係 # 關係:數據庫中表與表之間有聯繫 - mysql # 非關係:沒有表概念 - redis、mongodb(介於關係與非關係) # 2)內存與硬盤 # 硬盤:數據能夠永久存儲 - mysql、mongodb # 內存:數據的存取效率極高 - redis、memcache # 3)sql與nosql # sql:數據庫操做經過sql語句 # nosql:數據庫操做就是key-value形式(value就是一條記錄) # stu - {'name': 'Bob', 'age': 18} # stus - [{'name': 'Bob', 'age': 18}, {'name': 'Tom', 'age': 18}] # name - 'Jerry'
安裝
""" 一、解壓免安裝版本(5.6 - 沒有初始密碼) 二、配置環境變量:數據庫絕對路徑下的bin 三、配置服務: 啓動管理員終端:mysqld --install [nmysql] #安裝服務端 """
卸載
""" 前提)啓動終端,輸入 mysql,若是不是提示 不是內部或外部命令,表明已安裝數據庫 1)直接連入 i 搜索:服務,檢索mysql服務,有 中止服務,並移除服務 - 啓動管理員終端:mysqld --remove ii 搜索:服務,檢索mysql服務,無 (mysql使用命令啓動) 中止服務,啓動管理員終端 tasklist | findstr mysql taskkill /pid 進程pid /f 2)鏈接超時 搜索:服務,檢索mysql服務,移除服務便可 3)移除環境變量 總結:若是能連入,先中止服務 | 若是添加了服務,就移除服務 | 取消環境變量配置 """
鏈接數據庫
1)遊客登錄(不必定能登入,登入了也啥都不能幹) >: mysql 2)帳號密碼登陸 >: mysql -u root -p[密碼] 再輸入密碼,沒有任何提示,沒有密碼直接回車 3)鏈接指定服務器的mysql >: mysql -h ip地址 -P 端口號 -u 帳號 -p[密碼] 回車後敲入密碼 eg: >: mysql -hlocalhost -P3306 -uroot -p[密碼] 4)退出數據庫 >: quit >: exit
用戶信息查看
1)查看當前登陸的用戶 mysql>: select user(); mysql>: select version(); 查看mysql版本: 2)root權限下能夠查看全部用戶信息 mysql>: select * from mysql.user; #查看全部用戶的全部信息 mysql>: select * from mysql.user \G; #查看全部用戶的權限 mysql>: select user,password,host from mysql.user; #查看全部用戶的(user,password,host) 3)root登陸下,刪除遊客(操做後要重啓mysql服務) mysql>: delete from mysql.user where user=''; 4)root登陸下,修改密碼(操做後要重啓mysql服務) mysql>: update mysql.user set password=password('12345678') where host='localhost'; updata mysql.user set password=password('root') where host='localhost'; 5)沒有登陸 >: mysqladmin -u用戶名 -p舊密碼 -h域名 password "新密碼" eg>: mysqladmin -uroot -p12345678 -hlocalhost password "root" 6)root登陸下,建立用戶 mysql>:grant 權限們 on 數據庫名.表名 to 用戶名@主機名 identified by '密碼';
數據庫的基本操做
1)查看已有數據庫(當前用戶能夠操做的)全部數據庫 mysql>:show databases; 2)選擇某個數據庫 mysql>:use 數據庫名 #進入某個具體的數據庫,能夠直接對該數據庫下的表進行操做,不須要用 . 3)查看當前所在數據庫 mysql>:select database(); #須要經過 use 進入具體數據庫,並查看當前數據庫鎖擁有的表 4)建立數據庫 mysql>:create database 數據庫名 [charset=編碼格式]; #不指定編碼格式的話,默認爲latin1 eg>: create database owen; eg>: create database zero charset=utf8; eg>: create database tank; 5)查看建立數據庫的詳細內容 mysql>:show create database 數據庫名; eg>: show create database owen; 6)刪除數據庫 mysql>: drop database 數據庫名; eg>: drop database tank; 7)修改字符編碼 mysql>: alter database 數據庫名 charset=編碼格式;
SQL語句、語句擴展
top:TOP 子句用於規定要返回的記錄的數目。 列(s) = * sql top 語法 select top number|precent 列(s) from table_name; # 列(s) 表示 全部的列名稱 top number例:select top 2 * from table_name; 或 select * from table_name limit 2; top precent例:select top 50 precent * from table_name; # 選取表中50%的記錄 like:LIKE 操做符用於在 WHERE 子句中搜索列中的指定模式 sql like 語法 select 列(s) from table_name where 列 like pattern; 例:select * from table_name where 列 like 'A%'(在表中搜尋以A開頭的)|'%B'(以B結尾的)|'%AB%'(包含AB的); in:IN 操做符容許咱們在 WHERE 子句中規定多個值 sql in 語法 select * from table_name where 列 in(值1,值2,...); between:操做符 BETWEEN ... AND 會選取介於兩個值之間的數據範圍。這些值能夠是數值、文本或者日期。 sql between 語法 select * from table_name where 列 between 值1 and 值2; # 範圍取頭不取尾 alias:爲列名稱和表名稱指定別名(Alias)。 sql alias 語法 表:select * from table_name as alias_name; 表別名例:select p.列1,p.列2,p.列3 from table_name1 as p,table_name2 as po where p.列1='值1' and p.列2='值2'; 列:select 列 as alias_name from table_name; 列別名例:select 列1 as alias_name1,列2 as alias_name2 from table_name; join:用於根據兩個或多個表中的列之間的關係,從這些表中查詢數據。 sql join 語法 select tb1.列1,tb1.列2,tb2.列 from tb1 inner join tb2 on tb1.列3=tb2.列3 order by tb1.列1; 或 select tb1.列1,tb1.列2,tb2.列 from tb1,tb2 where tb1.列3=tb2.列3; 備註:不一樣的 SQL JOIN 除了在上面的例子中使用的 INNER JOIN(內鏈接),還能夠使用其餘幾種鏈接。 下面列出了能夠使用的 JOIN 類型,以及它們之間的差別。 JOIN: 若是表中有至少一個匹配,則返回行 LEFT JOIN: 即便右表中沒有匹配,也從左表返回全部的行 RIGHT JOIN: 即便左表中沒有匹配,也從右表返回全部的行 FULL JOIN: 只要其中一個表中存在匹配,就返回行 inner join 關鍵字語法:在表中存在至少一個匹配時,INNER JOIN 關鍵字返回行。 select * from tb1 inner join tb2 on tb1.列=tb2.列; # inner join 與join是相同的 left join 關鍵字語法:LEFT JOIN 關鍵字會從左表(tb1)那裏返回全部的行,即便在右表(tb2)中沒有匹配的行。 select * from tb1 left join tb2 on tb1.列=tb2.列; right join 關鍵字語法:RIGHT JOIN 關鍵字會右表(tb2)那裏返回全部的行,即便在左表(tb1)中沒有匹配的行。 select * from tb1 right join tb2 on tb1.列=tb2.列; full join 關鍵字語法:只要其中某個表存在匹配,FULL JOIN 關鍵字就會返回行 select * from tb1 full join tb2 on tb1.列=tb2.列; 十一、union:用於合併兩個或多個 SELECT 語句的結果集(UNION 內部的 SELECT 語句必須擁有相同數量的列。列也必須擁有類似的數據類型。同時,每條 SELECT 語句中的列的順序必須相同) sql union 與 union all 語法 select * from table_name1 union select * from table_name2; select * from table_name1 union all select * from table_name2; 備註:默認地,union 選取不一樣的值,若是容許重複的值,就使用 union all(列出全部的值) select into:從一個表中選取數據,而後把數據插入另外一個表中。經常使用於建立表的備份復件或者用於對記錄進行存檔。 sql select into 語法 select * into new_table_name [in externaldatabase] from old_table_name; # 全部列插入新表 select 列 into new_table_name [in externaldatabase] from old_table_name; # 某一列插入新表 例:備份某張表 select * into tb1_backup from tb1; 向另外一個數據庫中拷貝表 select * into tb1 in 'backup.mdb' from tb1; 多表查詢存入到新表 select tb1.列1,tb2.列2 into new_table_name from tb1 inner join tb2 on tb1.列3=tb2.列3; create index:用於在表中建立索引。在不讀取整個表的狀況下,索引使數據庫應用程序能夠更快地查找數據。 註釋:更新一個包含索引的表須要比更新一個沒有索引的表更多的時間,這是因爲索引自己也須要更新。所以,理想的作法是僅僅在經常被搜索的列(以及表)上面建立索引。 sql create index 語法 create index index_name on table_name(列); # 簡單的索引,容許使用重複的值 create index index_name on table_name(列1 desc,列2); # 默認是升序,但願降序在列名稱後添加保留字 desc,索引不止一個列能夠逗號隔開 sql create unique index 語法 # 惟一的索引 create unique index index_name on table_name(列); # 惟一的索引意味着兩個行不能擁有相同的索引值 alter table : 語句用於在已有的表中添加、修改或刪除列。 sql alter table 語法 添加列:alter table table_name add 列 數據類型; 刪除列:alter table table_name drop column 列; 改變列中數據類型:alter table table_name modify column 列 須要修改的類型; 只修改列的數據類型的方法: 一般能夠寫成 alter table 表名 modify column 列名 新的列的類型 例如:student表中列sname的類型是char(20),如今要修改成varchar(20),SQL語句以下 alter table student modify column sname varchar(20); 同時修改列名和列的數據類型的方法: 一般能夠寫成 alter table 表名 change column 舊列名 新列名 新的列類型 例如:student表中列sname的類型是char(20),如今要修改成stuname varchar(20),SQL語句以下 alter table student change column sname stuname varchar(20); alter table table_name add <新列名> <數據類型> [約束條件][FLRST(添加列到表的最前面)|AFTER(指定列後面) <已存在的列>]; # 添加列 alter table table_name <舊列名> <新列名> <新數據類型>; # 修改列名 alter table table_name modify <列名> <數據類型>; # 修改列的數據類型 alter table table_name modify <列1(想要改變的列)> <數據類型> FLRST|AFTER <列2>; # 修改列的位置 alter table table_name drop <列>; # 刪除列 alter table <舊錶名> rename to <新表名>; # 修改表名 view(視圖): 視圖是可視化的表。視圖包含行和列,就像一個真實的表 註釋:數據庫的設計和結構不會受到視圖中的函數、where 或 join 語句的影響。 sql create view 語法 create view view_name as select 列(s) from table_name where 條件; 註釋:視圖老是顯示最近的數據。每當用戶查詢視圖時,數據庫引擎經過使用 SQL 語句來重建數據。 更新視圖:create or replace view view_name as select 列(*) from table_name where 條件; 刪除視圖:drop view view_name;
數據庫配置
# 經過配置文件統一配置的目的:統一管理 服務端(mysqld) 、客戶端(client) # 配置了 mysqld(服務端) 的編碼爲utf8,那麼再建立的數據庫,默認編碼都採用utf8 # 配置流程 # 1)在mysql安裝根目錄下,建立配置文件:my.ini # mac下配置文件名叫 my.cnf # 2)設置配置文件內容並保存 [mysqld] # 服務器配置 port=3306 # 能夠修改數據庫默認端口(若是數據庫端口被其餘軟件佔用) character-set-server=utf8 # 編碼格式 #非安全模式 sql_mode = no_engine_substitution #安全模式 #sql_mode = strict_trans_tables #設置引擎 default-storage-engine=INNODB collation-server=utf8_general_ci # 排序方式(默認跟編碼格式走) #utf8_general_ci 不區分大小寫,這個你在註冊用戶名和郵箱的時候就要使用。 #utf8_general_cs 區分大小寫,若是用戶名和郵箱用這個 就會照成不良後果 #utf8_bin:字符串每一個字符串用二進制數據編譯存儲。 區分大小寫,並且能夠存二進制的內容 [client] # mysql本身的客戶端叫[mysql],配置[client]即配置了[mysql],也配置了其餘存在方式的客戶端,好比Navicat可視化客戶端 default-character-set=utf8 # 編碼格式 # 3)重啓數據庫服務
用戶操做:重點
# 爲特定的數據庫分配有該數據庫 操做權限 的用戶 mysql>: grant 權限們 on 數據庫.表 to 用戶名@'主機名' identified by '密碼'; # 1)all:全部權限 # 2)oldboy.*:oldboy數據庫下全部表 # 3)oldboy@'localhost':本機能夠經過oldboy用戶登入 # 4)identified by 'Oldboy123':密碼爲Oldboy123 eg>: grant all on oldboy.* to oldboy@'localhost' identified by 'Oldboy123'; # 1)select,delete,update,insert,drop,alter:指定的權限 # 2)oldboy.*:oldboy數據庫下全部表 # 3)oldboy@'%':任何機器能夠經過oldboy用戶登入 # 4)identified by 'Oldboy123':密碼爲Oldboy123 eg>: grant select,delete,update,insert,drop,alter on oldboy.* to oldboy@'%' identified by 'Oldboy123'; # 撤銷權限 mysql>: revoke 權限1,權限2,... on 數據庫名.表名 from 用戶名@'主機名'; # 禁掉本地oldboy用戶對oldboy數據庫的全部表的drop權限 eg:> revoke drop on oldboy.* from oldboy@'localhost'; # 刪除用戶 drop user 用戶名@'主機名';
數據庫表的引擎:驅動數據的方式 - 數據庫優化
# 前提: 引擎是建表是規定, 提供給表使用的, 不是數據庫 # 展現全部引擎 mysql> show engines; # innodb(默認): 支持事務, 行級鎖, 外鍵 mysql>: create table t11(id int)engine=innodb; # myisam: 查詢效率要優於innodb, 當不須要支持事務, 行級鎖, 外鍵, 能夠經過設置myisam來優化數據庫 mysql>: create table t12(id int)engine=myisam; # blackhole:黑洞,存進去的數據都會消失(能夠理解不存數據) mysql>: create table t13(id int)engine=blackhole; # memory:表結構是存儲在硬盤上的,可是表數據所有存儲在內存中 mysql>: create table t14(id int)engine=memory;
MySQL各大存儲引擎:
最好先看下你下的MySQL支持什麼數據庫引擎mysql
存儲引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Blackhole, 5. CSV, 6. Performance_Schema, 7. Archive, 8. Federated , 9 Mrg_Myisamlinux
可是咱們主要分析使用MyIsam 和InnoDB。其他略微帶過,詳情請分別百度。程序員
(1)InnoDB:
定義:(默認的存儲引擎)web
InnoDB是一個事務型的存儲引擎,有行級鎖定和外鍵約束。redis
Innodb引擎提供了對數據庫ACID事務的支持,而且實現了SQL標準的四種隔離級別,關於數據庫事務與其隔離級別的內容請見數據庫事務與其隔離級別這類型的文章。該引擎還提供了行級鎖和外鍵約束,它的設計目標是處理大容量數據庫系統,它自己其實就是基於MySQL後臺的完整數據庫系統,MySQL運行時Innodb會在內存中創建緩衝池,用於緩衝數據和索引。可是該引擎不支持FULLTEXT類型的索引,並且它沒有保存表的行數,當SELECT COUNT(*) FROM TABLE時須要掃描全表。當須要使用數據庫事務時,該引擎固然是首選。因爲鎖的粒度更小,寫操做不會鎖定全表,因此在併發較高時,使用Innodb引擎會提高效率。可是使用行級鎖也不是絕對的,若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表。算法
//這個就是select鎖表的一種,不明確主鍵。增刪改查均可能會致使鎖全表,在之後咱們會詳細列出。 SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
適用場景:sql
1)常常更新的表,適合處理多重併發的更新請求。mongodb
2)支持事務。數據庫
3)能夠從災難中恢復(經過bin-log日誌等)。
4)外鍵約束。只有他支持外鍵。
5)支持自動增長列屬性auto_increment。
MySQL官方對InnoDB的講解:
1)InnoDB給MySQL提供了具備提交、回滾和崩潰恢復能力的事務安全(ACID兼容)存儲引擎。
2)InnoDB鎖定在行級而且也在SELECT語句提供一個Oracle風格一致的非鎖定讀,這些特點增長了多用戶部署和性能。沒有在InnoDB中擴大鎖定的須要,由於在InnoDB中行級鎖定適合很是小的空間。
3)InnoDB也支持FOREIGN KEY強制。在SQL查詢中,你能夠自由地將InnoDB類型的表與其它MySQL的表的類型混合起來,甚至在同一個查詢中也能夠混合。
4)InnoDB是爲處理巨大數據量時的最大性能設計,它的CPU效率多是任何其它基於磁盤的關係數據庫引擎所不能匹敵的。
5) InnoDB被用來在衆多須要高性能的大型數據庫站點上產生。
**補充:**什麼叫事務?簡稱ACID
A 事務的原子性(Atomicity):指一個事務要麼所有執行,要麼不執行.也就是說一個事務不可能只執行了一半就中止了.好比你從取款機取錢,這個事務能夠分紅兩個步驟:1劃卡,2出錢.不可能劃了卡,而錢卻沒出來.這兩步必須同時完成.要麼就不完成.
C 事務的一致性(Consistency):指事務的運行並不改變數據庫中數據的一致性.例如,完整性約束了a+b=10,一個事務改變了a,那麼b也應該隨之改變.
I 獨立性(Isolation):事務的獨立性也有稱做隔離性,是指兩個以上的事務不會出現交錯執行的狀態.由於這樣可能會致使數據不一致.
D 持久性(Durability):事務的持久性是指事務執行成功之後,該事務所對數據庫所做的更改即是持久的保存在數據庫之中,不會平白無故的回滾.
(2)M4yIsam:
定義:
MyIASM是MySQL默認的引擎,可是它沒有提供對數據庫事務的支持,也不支持行級鎖和外鍵,所以當INSERT(插入)或UPDATE(更新)數據時即寫操做須要鎖定整個表,效率便會低一些。
MyIsam 存儲引擎獨立於操做系統,也就是能夠在windows上使用,也能夠比較簡單的將數據轉移到linux操做系統上去。
意味着:引擎在建立表的時候,會建立三個文件,一個是.frm文件用於存儲表的定義,一個是.MYD文件用於存儲表的數據,另外一個是.MYI文件,存儲的是索引。操做系統對大文件的操做是比較慢的,這樣將表分爲三個文件,那麼.MYD這個文件單獨來存放數據天然能夠優化數據庫的查詢等操做。有索引管理和字段管理。MyISAM還使用一種表格鎖定的機制,來優化多個併發的讀寫操做,其代價是你須要常常運行OPTIMIZE TABLE命令,來恢復被更新機制所浪費的空間。
適用場景:
1)不支持事務的設計,可是並不表明着有事務操做的項目不能用MyIsam存儲引擎,能夠在service層進行根據本身的業務需求進行相應的控制。
2)不支持外鍵的表設計。
3)查詢速度很快,若是數據庫insert和update的操做比較多的話比較適用。
4)成天 對錶進行加鎖的場景。
5)MyISAM極度強調快速讀取操做。
6)MyIASM中存儲了表的行數,因而SELECT COUNT(*) FROM TABLE時只須要直接讀取已經保存好的值而不須要進行全表掃描。若是表的讀操做遠遠多於寫操做且不須要數據庫事務的支持,那麼MyIASM也是很好的選擇。
缺點:
就是不能在表損壞後恢復數據。(是不能主動恢復)
補充:ISAM索引方法–索引順序存取方法
定義:
是一個定義明確且歷經時間考驗的數據表格管理方法,它在設計之時就考慮到 數據庫被查詢的次數要遠大於更新的次數。
特性:
ISAM執行讀取操做的速度很快,並且不佔用大量的內存和存儲資源。
在設計之初就預想數據組織成有固定長度的記錄,按順序存儲的。—ISAM是一種靜態索引結構。
缺點:
1.它不 支持事務處理
2.也不可以容錯。若是你的硬盤崩潰了,那麼數據文件就沒法恢復了。若是你正在把ISAM用在關鍵任務應用程序裏,那就必須常常備份你全部的實 時數據,經過其複製特性,MYSQL可以支持這樣的備份應用程序。
(3)Memory(也叫HEAP)堆內存嘛:
定義:
使用存在內存中的內容來建立表。每一個MEMORY表只實際對應一個磁盤文件。MEMORY類型的表訪問很是得快,由於它的數據是放在內存中的,而且默認使用HASH索引。
可是一旦服務關閉,表中的數據就會丟失掉。 HEAP容許只駐留在內存裏的臨時表格。駐留在內存裏讓HEAP要比ISAM和MYISAM都快,可是它所管理的數據是不穩定的,並且若是在關機以前沒有進行保存,那麼全部的數據都會丟失。在數據行被刪除的時候,HEAP也不會浪費大量的空間。HEAP表格在你須要使用SELECT表達式來選擇和操控數據的時候很是有用。
適用場景:
1)那些內容變化不頻繁的代碼表,或者做爲統計操做的中間結果表,便於高效地堆中間結果進行分析並獲得最終的統計結果。
2)目標數據比較小,並且很是頻繁的進行訪問,在內存中存放數據,若是太大的數據會形成內存溢出。能夠經過參數max_heap_table_size控制Memory表的大小,限制Memory表的最大的大小。
3)數據是臨時的,並且必須當即可用獲得,那麼就能夠放在內存中。
4)存儲在Memory表中的數據若是忽然間丟失的話也沒有太大的關係。
注意: Memory同時支持散列索引和B樹索引,B樹索引能夠使用部分查詢和通配查詢,也能夠使用<,>和>=等操做符方便數據挖掘,散列索引相等的比較快可是對於範圍的比較慢不少。
特性要求:
1)要求存儲的數據是數據長度不變的格式,好比,Blob和Text類型的數據不可用(長度不固定的)。
2)要記住,在用完表格以後就刪除表格。
(4)Mrg_Myisam:(分表的一種方式–水平分表)
定義:
是一個相同的能夠被看成一個來用的MyISAM表的集合。「相同」意味着全部表一樣的列和索引信息。
也就是說,他將MyIsam引擎的多個表聚合起來,可是他的內部沒有數據,真正的數據依然是MyIsam引擎的表中,可是能夠直接進行查詢、刪除更新等操做。
好比:咱們可能會遇到這樣的問題,同一種類的數據會根據數據的時間分爲多個表,若是這時候進行查詢的話,就會比較麻煩,Merge能夠直接將多個表聚合成一個表統一查詢,而後再刪除Merge表(刪除的是定義),原來的數據不會影響。
(5)Blackhole(黑洞引擎)
定義
任何寫入到此引擎的數據均會被丟棄掉, 不作實際存儲;Select語句的內容永遠是空。
他會丟棄全部的插入的數據,服務器會記錄下Blackhole表的日誌,因此能夠用於複製數據到備份數據庫。
使用場景:
1)驗證dump file語法的正確性
2)以使用blackhole引擎來檢測binlog功能所須要的額外負載
3)充當日誌服務器
其他引擎,你們感興趣就各自先百度吧。本文主要是對比引擎使用以及其原理。
數據庫的模式
# mysql 5.7 之後默認都是安全模式 # mysql 5.6 版本 sql_model=no_engine_substitution # 非安全性,默認 sql_model=strict_trans_tables # 安全性 # 查看當前數據庫模式: show variables like "%sql_mode%"; # %匹配0~n個任意字符 => 模糊查詢 # 臨時設置爲安全模式,服務重啓後會被重置 mysql>: set global sql_mode="strict_trans_tables"; # 在root用戶登陸狀態下 # 在設置後,quit斷開數據庫鏈接後(服務器不重啓)就會進入安全模式 # 安全模式下,非安全模式下sql執行的警告語句,都會拋異常 eg>: create table t1(name char(2)); eg>: insert into t1 values ("ab") # 正常 eg>: insert into t1 values ("owen") # 錯誤 Data too long for column 'name' at row 1
經常使用字符集
位(bit):是計算機 內部數據 儲存的最小單位,11001100是一個八位二進制數。
字節(byte):是計算機中 數據處理 的基本單位,習慣上用大寫 B 來表示,1B(byte,字節)= 8bit(位)
字符:是指計算機中使用的字母、數字、字和符號
ASCIIS碼: 1個英文字母(不分大小寫)= 1個字節的空間
1箇中文漢字 = 2個字節的空間
1個ASCII碼 = 一個字節
UTF-8編碼:1個英文字符 = 1個字節
英文標點 = 1個字節
1箇中文(含繁體) = 3個字節
中文標點 = 3個字節
Unicode編碼:1個英文字符 = 2個字節
英文標點 = 2個字節
1箇中文(含繁體) = 2個字節
中文標點 = 2個字節
數據存儲是以「字節」(Byte)爲單位,數據傳輸大可能是以「位」(bit,又名「比特」)爲單位,一個位就表明一個0或1(即二進制),每8個位(bit,簡寫爲b)組成一個字節(Byte,簡寫爲B),是最小一級的信息單位。
B與iB
1KiB(Kibibyte)=1024byte
1KB(Kilobyte)=1000byte
1MiB(Mebibyte)=1048576byte
1MB(Megabyte)=1000000byte
硬盤生產商是以GB(十進制),即10的3次方=1000,如1MB=1000KB)計算的,而電腦(操做系統)是以GiB(2進制,即2的10次方, 如1MiB=1024KiB)計算的,可是國內用戶通常理解爲1MiB=1M=1024 KB, 因此爲了便於中文化的理解,翻譯MiB爲MB也是能夠的。
一樣根據硬盤)廠商與用戶對於1MB大小的不一樣理解,因此好多160G的硬盤實際容量按計算機實際的1MiB=1024KB算都不到160G,這也能夠解釋爲何新買的硬盤「缺斤短兩」並無它所標示的那麼大。
國際單位制(SI):
1KB=1024B;1MB=1024KB=1024×1024B。
1B(byte,字節)= 8 bit(見下文);
1KB(Kilobyte,千字節])=1024B= 2^10 B;
1MB(Megabyte,兆字節,百萬字節,簡稱「兆」)=1024KB= 2^20 B;
1GB(Gigabyte,吉字節,十億字節,又稱「千兆」)=1024MB= 2^30 B;
1TB(Terabyte,萬億字節,太字節)=1024GB= 2^40 B;
1PB(Petabyte,千萬億字節,拍字節)=1024TB= 2^50 B;
1EB(Exabyte,百億億字節,艾字節)=1024PB= 2^60 B;
1ZB(Zettabyte,十萬億億字節,澤字節) =102424EB= 2^70 B;
1YB(Yottabyte,一億億億字節,堯字節)= 1024ZB= 2^80 B;
1BB(Brontobyte,一千億億億字節)= 1024YB= 2^90 B;
1NB(NonaByte,一百萬億億億字節) = 1024BB = 2^100 B;
1DB(DoggaByte,十億億億億字節) = 1024 NB = 2^110 B;
數據存儲是以10進製表示,數據傳輸是以2進製表示的,因此1KB不等於1000B。
-
ASCII
ASCII是7比特的字符集,涵蓋了英語中的絕大多數字符。編碼從0到127.
ASCII碼實現的是大小寫英文字母,阿拉伯數字,及經常使用的標點符、運算符、控制字符(換行、刪除等)和通訊字符(文頭、確認等)與計算機編碼之間的對應。ASCII編碼採用單字節(8 Bit)存儲,實際數據存儲空間是7 Bit,最高位的1 Bit是奇偶校驗位。
ASCII編碼對於英語國家足夠用了,可是卻沒法表達非英語國家字符到計算機編碼之間的映射,如中文漢字、法語字母等。因此,出現了不少非ASCII編碼(但大多數都是兼容ASCII碼的)。
-
ISOLatin-1(the ISO-8859-1 standard)
ISO Latin-1是8比特的字符集,定義了256個字符。前128個字符(00000000-01111111)與ASCII徹底一致。
Latin1是ISO-8859-1的別名,有些環境下寫做Latin-1。Latin1編碼是單字節編碼,向下兼容ASCII,其編碼範圍是0x00-0xFF,0x00-0x7F之間徹底和ASCII一致,0x80-0x9F之間是控制字符,0xA0-0xFF之間是文字符號。
ASCII編碼是一個7位的容器,ISO-8859-1編碼是一個8位的容器。
由於Latin1編碼範圍使用了單字節內的全部空間,在支持Latin1編碼的系統中傳輸和存儲其餘任何編碼的字節流都不會被拋棄。換言之,把其餘任何編碼的字節流看成Latin1編碼看待都沒有問題。這是個很重要的特性,MySQL數據庫默認編碼是Latin1就是利用了這個特性。
-
Unicode
世界上存在着多種編碼方式,同一個二進制數字能夠被解釋成不一樣的符號。所以,要想打開一個文本文件,就必須知道它的編碼方式,不然用錯誤的編碼方式解讀,就會出現亂碼。爲何電子郵件經常出現亂碼?就是由於發信人和收信人使用的編碼方式不同。
能夠想象,若是有一種編碼,將世界上全部的符號都歸入其中。每個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。這就是Unicode。
Unicode固然是一個很大的集合,如今的規模能夠容納100多萬個符號。每一個符號的編碼都不同須要注意的是,Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。
若是全部字符都按照最大存儲空間存儲,那必然會浪費很大的空間,好比全部字符都按照3字節存儲,可是英文字母只須要一個字節存儲就夠了,就等於說一個Unicode編碼的英文文檔是ASCII編碼文檔存儲空間的三倍。 因此,便有了變長編碼—-UTF-8。
Unicode只是定義了字符的編碼值,並未指定值以何種形式存儲。好比漢字「田」的Unicode編碼是7530,轉換爲二進制是01110101,00110000。比方如今定義一種unicode的實現方式UTF-FAKE,規則是
a. 使用24個字節
b. 每一個字節的高7位都是1
c. 每一個字節的最末一位存儲unicode編碼值
那麼01110101,00110000的存儲形式是
11111110, 11111110, 11111110, 11111110, 11111110, 11111110, 11111110, 11111110,
11111110, 11111111, 11111111, 11111111, 11111110, 11111111, 11111110, 11111111,
11111110, 11111110, 11111111, 11111111, 11111110, 11111110, 11111110, 11111110
其中末位爲藍色0的字節爲補足字節。
實際使用的編碼方式UTF-8使用三個字節存儲「田」 01110101,00110000,以下
11100111, 10010100, 10110000
Unicode的第一個版本於1991年發佈,該版本容許的的最大編碼空間是兩個字節。96年發佈的Unicode 2.0版本引入了surrogate pair,將Unicode的編碼數目擴充到了百萬級,因爲可見的未來該數目不大可能用光,所以Unicode委員會對外宣稱該上限永不會更改。Surrogate pair在UTF-16和UTF-32中獲得了實現。Unicode的前256個字符及編碼值與Latin-1徹底一致。好比大寫字母A在Latin-1和Unicode中的編碼值都是0x41(十進制的65)。
Unicode的編碼值範圍是 000000hex 到10FFFFhex,可劃分爲17個plane,每一個plane包含65536(= 216)個字符。Plane的代碼從0到16(十進制),對應於 000000hex,010000hex,020000hex,… … ,0F0000hex,10FFFFhex的藍色部分。
Unicode的表示方式通常是」U+」後綴上4到6個十六進制字符,如」田「的Unicode表示方式是U+7530。
-
UTF-8
UTF-8就是在互聯網上使用最廣的一種Unicode的實現方式。其餘實現方式還包括UTF-16和UTF-32,不過在互聯網上基本不用。
UTF-8最大的一個特色,就是它是一種變長的編碼方式。它能夠使用1~4個字節表示一個符號,根據不一樣的符號而變化字節長度。如ASCII編碼的內容UTf-8中就是用一個字符存儲的。
UTF-8採用可變長度的編碼,長度從1到4個字節不等。某些應用識別非標準的"utf8" 或"UTF 8"別名。只有ASCII字符在UTF-8中使用一個字節編碼,且值與ASCII徹底相同,其他字符在UTF-8中使用2到4個字節。所以UTF-8中的單字節且只有單字節編碼字符的最高的1個比特是0。
UTF-8對Unicode字符的編碼規則以下
說明以下:
-
只有ASCII使用單字節編碼
-
Unicode編碼值大於127的字符使用多個字節編碼。多字節序列的第一個字節稱爲leading byte,後續的字節稱爲continuation bytes。Leading byte的高位是110,1110或11110,其中的「1」的個數標明瞭序列中的字節總數。如2個字節序列的leading byte爲110xxxxx,其中的11標明瞭這是一個雙字節的序列,亦即該序列有1個continuation byte。Continuation bytes的每一個字節的高兩位均是10。
-
單字節序列、leading bytes和continuationbytes的高位分別是0,110/1110/11110和10,所以不會混淆。
仍是以漢字」田「爲例,展現Unicode字符如何按照UTF-8存儲。」田「的Unicode值是U+7530,比對上表發現介於U+0800 - U+FFFF之間,所以須要3個字節來存儲。7530轉爲二進制是1110101,00110000,一共15位。但因爲UTF-8的3字節編碼存儲16個比特,所以將1110101,00110000的高一位補零變成16比特01110101,00110000。而後將這16比特依次填入三字節序列1110xxxx 10xxxxxx 10xxxxxx的x中,獲得結果
11100111 10010100 10110000,寫成16進制就是E7 94 B0
注意:雖然Unicode中的前256個字符及編碼值與Latin-1徹底一致,但UTF-8只對前128個即ASCII字符采用單字節編碼,其他128個Latin-1字符是採用2個字節編碼。所以ASCII編碼的文件能夠直接以UTF-8方式讀取,而Latin-1的文件若包含值爲128-255的字符則不能夠。
UTF-8是一種變長字節編碼方式。對於某一個字符的UTF-8編碼,若是隻有一個字節則其最高二進制位爲0;若是是多字節,其第一個字節從最高位開始,連續的二進制位值爲1的個數決定了其編碼的位數,其他各字節均以10開頭。UTF-8最多可用到6個字節。 如表: 1字節 0xxxxxxx 2字節 110xxxxx 10xxxxxx 3字節 1110xxxx 10xxxxxx 10xxxxxx 4字節 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 5字節 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 6字節 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx Unicode
UNICODE UTF8轉換規則
符號範圍 | UTF-8編碼方式
(十六進制) | (二進制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下面,仍是以漢字「嚴」爲例,演示如何實現UTF-8編碼。
下面,仍是以漢字「嚴」爲例,演示如何實現UTF-8編碼。
已知「嚴」的unicode是4E25(100111000100101),根據上表,能夠發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),所以「嚴」的UTF-8編碼須要三個字節,即格式是「1110xxxx 10xxxxxx 10xxxxxx」。而後,從「嚴」的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就獲得了,「嚴」的UTF-8編碼是「11100100 10111000 10100101」,轉換成十六進制就是E4B8A5。
-
-
UTF-16
UTF-16也是採用可變長度編碼,能夠是一個或者兩個16比特。某些應用中容許使用非標準的UTF_16或者UTF16做爲別名。Unicode中的第一個plane的65536(= 216)codepoints採用16比特編碼,其他的16個plane均採用2個16比特編碼。採用2個16比特編碼的先後兩個16bit分別稱爲lead surrogate pair和trail surrogate pair,之因此稱爲surrogate是由於單獨一個16bit不表明任何字符,只有組合起來纔有意義。
既然UTF-16也是可變長度編碼,如何區分某個16bit是單獨表示一個字符仍是與後續的16bit組合起來表示一個字符呢?Unicode將D800–DBFF和DC00–DFFF這兩個範圍做爲保留區間,沒有將之分配給任何Unicode字符,若某16比特落在D800–DBFF範圍內,即可將之視爲採用2個16bit編碼字符的第一個16bit,而落在DC00–DFFF的16bit可視爲採用2個16bit編碼字符的第二個16bit。這就使得Unicode第一個plane實際可分配使用的code points只有65536 – (DFFF - D800 + 1) = 65536 – 8*256 = 63488。
採用一個16bit編碼的Unicode字符在UTF-16中的編碼值與其在Unicode中是相等的,好比英文大寫字母A的Unicode值是U+0041,其UTF-16編碼是0041 hex 。Unicode第二到第十七個plane採用兩個16bit即surrogate pairs的字符從其Unicode code point到UTF-16的轉換規則是
-
範圍爲0x10000 … 0x10FFFF的codepoint減去0x010000,減事後的結果範圍是0x00000到0xFFFFF,使得該結果能夠使用5位16進制亦即20位2進制數表示
-
結果中高10位(範圍是0x0到0x3FF)加上0xD800(結果範圍是0xD800到0xDBFF)做爲雙16bit的第一個16bit即leadsurrogate
-
結果中低10位(範圍是0x0到0x3FF)加上0xDC00(結果範圍是0xDC00到0xDFFF)做爲雙16bit的第二個16bit即trailsurrogate
這樣UTF-16與UTF-8都是self-synchronizing的,即某個16bit是不是一個字符的開始無需檢查其前一個或者後一個16bit。與UTF-8的不一樣之處是,UTF-16不支持從某個隨機的字節開始讀取。
舉例:UTF-16 序列 0041, D801DC01 (字符"A"),若第一個字節丟失即從第二個字節讀取,那麼UTF-16認爲序列是41D8,01DC,01;而UTF-8不存在這個問題。
-
-
GKB
GBK 是又一個漢字編碼標準,全稱《漢字內碼擴展規範》(GBK),英文名稱 Chinese Internal Code Specification ,中華人民共和國全國信息技術標準化技術委員會 1995 年 12 月 1 日製訂,國家技術監督局標準化司、電子工業部科技與質量監督司 1995 年 12 月 15 日聯合以技監標函 [1995] 229 號文件的形式,將它肯定爲技術規範指導性文件,發佈和實施。這一版的 GBK 規範爲 1.0 版。GB 即「國標」,K 是「擴展」的漢語拼音第一個字母。
GBK 向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1 國際標準,是前者向後者過渡過程當中的一個承上啓下的標準。 ISO 10646 是國際標準化組織 ISO 公佈的一個編碼標準,即 Universal Multilpe-Octet Coded Character Set(簡稱 UCS),大陸譯爲《通用多八位編碼字符集》,臺灣譯爲《廣用多八位元編碼字元集》,它與 Unicode 組織的 Unicode 編碼徹底兼容。ISO 10646.1 是該標準的第一部分《體系結構與基本多文種平面》。我國 1993 年以 GB 13000.1 國家標準的形式予以承認(即 GB 13000.1 等同於 ISO 10646.1)。 ISO 10646 是一個包括世界上各類語言的書面形式以及附加符號的編碼體系。其中的漢字部分稱爲「CJK 統一漢字」(C 指中國,J 指日本,K 指朝鮮)。而其中的中國部分,包括了源自中國大陸的 GB 23十二、GB 1234五、《現代漢語通用字表》等法定標準的漢字和符號,以及源自臺灣的 CNS 11643 標準中第 一、2 字面(基本等同於 BIG-5 編碼)、第 14 字面的漢字和符號。
1、字彙 GBK 規範收錄了 ISO 10646.1 中的所有 CJK 漢字和符號,並有所補充。具體包括:
- GB 2312 中的所有漢字、非漢字符號。
- GB 13000.1 中的其餘 CJK 漢字。以上合計 20902 個 GB 化漢字。
- 《簡化字總表》中未收入 GB 13000.1 的 52 個漢字。
- 《康熙字典》及《辭海》中未收入 GB 13000.1 的 28 個部首及重要構件。
- 13 個漢字結構符。
- BIG-5 中未被 GB 2312 收入、但存在於 GB 13000.1 中的 139 個圖形符號。
- GB 12345 增補的 6 個拼音符號。
- 漢字「○」。
- GB 12345 增補的 19 個豎排標點符號(GB 12345 較 GB 2312 增補豎排標點符號 29 個,其中 10 個未被 GB 13000.1 收入,故 GBK 亦不收)。
- 從 GB 13000.1 的 CJK 兼容區挑選出的 21 個漢字。
- GB 13000.1 收入的 31 個 IBM OS/2 專用符號。
2、碼位分配及順序 GBK 亦採用雙字節表示,整體編碼範圍爲 8140-FEFE,首字節在 81-FE 之間,尾字節在 40-FE 之間,剔除 xx7F 一條線。總計 23940 個碼位,共收入 21886 個漢字和圖形符號,其中漢字(包括部首和構件)21003 個,圖形符號 883 個。 所有編碼分爲三大部分:
-
漢字區。包括: a. GB 2312 漢字區。即 GBK/2: B0A1-F7FE。收錄 GB 2312 漢字 6763 個,按原順序排列。 b. GB 13000.1 擴充漢字區。包括: (1) GBK/3: 8140-A0FE。收錄 GB 13000.1 中的 CJK 漢字 6080 個。 (2) GBK/4: AA40-FEA0。收錄 CJK 漢字和增補的漢字 8160 個。CJK 漢字在前,按 UCS 代碼大小排列;增補的漢字(包括部首和構件)在後,按《康熙字典》的頁碼/字位排列。
-
圖形符號區。包括: a. GB 2312 非漢字符號區。即 GBK/1: A1A1-A9FE。其中除 GB 2312 的符號外,還有 10 個小寫羅馬數字和 GB 12345 增補的符號。計符號 717 個。 b. GB 13000.1 擴充非漢字區。即 GBK/5: A840-A9A0。BIG-5 非漢字符號、結構符和「○」排列在此區。計符號 166 個。
-
用戶自定義區:分爲(1)(2)(3)三個小區。 (1) AAA1-AFFE,碼位 564 個。 (2) F8A1-FEFE,碼位 658 個。 (3) A140-A7A0,碼位 672 個。 第(3)區儘管對用戶開放,但限制使用,由於不排除將來在此區域增補新字符的可能性。
3、字形 GBK 對字形做了以下的規定:
- 原則上與 GB 13000.1 G列(即源自中國大陸法定標準的漢字)下的字形/筆形保持一致。
- 在 CJK 漢字認同規則的總框架內,對全部的 GBK 編碼漢字實施「無重碼正形」(「GB 化」);即在不形成重碼的前提下,儘可能採用中國新字形。
- 對於超出 CJK 漢字認同規則的、或認同規則還沒有明確規定的漢字,在 GBK 碼位上暫安放舊字形。這樣,在許多狀況下 GBK 收入了同一漢字的新舊兩種字形。
- 非漢字符號的字形,凡 GB 2312 已經包括的,與 GB 2312 保持一致;超出 GB 2312 的部分,與 GB 13000.1 保持一致。
- 帶聲調的拼音字母取半角形式。
GBK編碼是在GB2312-80(也稱做GB2312,GB碼)標準基礎上的內碼擴展規範,使用了雙字節編碼方案。
GBK是國家標準GB2312基礎上擴容後兼容GB2312的標準。GBK的文字編碼是用雙字節來表示的,即不論中、英文字符均使用雙字節來表示,爲了區分中文,將其最高位都設定成1。GBK包含所有中文字符,是國家編碼,通用性比UTF8差,不過UTF8佔用的數據庫比GBK大
GBK、GB2312等與UTF8之間都必須經過Unicode編碼才能相互轉換:
GBK、GB2312<= = =>Unicode<= = =>UTF8
補充:
GB2312 最先一版的中文編碼,每一個字佔據2bytes。因爲要和ASCII兼容,那這2bytes最高位不能夠爲0 了(不然和ASCII會有衝突)。在GB2312中收錄了6763個漢字以及682個特殊符號,已經囊括了生活中最 經常使用的全部漢字。
GBK 因爲GB2312只有6763個漢字,我漢語博大精深,只有6763個字怎麼夠?因而GBK中在保證不和 GB23十二、ASCII衝突(即兼容GB2312和ASCII)的前提下,也用每一個字佔據2bytes的方式又編碼了許多 漢字。通過GBK編碼後,能夠表示的漢字達到了20902個,另有984個漢語標點符號、部首等。值得注意 的是這20902個漢字還包含了繁體字。
GB18030 然而,GBK的兩萬多字也已經沒法知足咱們的需求了,還有更多可能你本身歷來沒見過的漢字 須要編碼。這時候顯然只用2bytes表示一個字已經不夠用了(2bytes最多隻有65536種組合,然而爲了和 ASCII兼容,最高位不能爲0就已經直接淘汰了一半的組合,只剩下3萬多種組合沒法知足所有漢字求)。 所以GB18030多出來的漢字使用4bytes編碼。固然,爲了兼容GBK,這個四字節的前兩位顯然不能與 GBK衝突(實操中發現後兩位也並無和GBK衝突)。我國在2000年和2005年分別頒佈的兩次GB18030 編碼,其中2005年的是在2000年基礎上進一步補充。至此,GB18030編碼的中文文件已經有七萬多個漢 字了,甚至包含了少數民族文字。
這圖中展現了前文所述的幾種編碼在編碼完成後,前2個byte的值的範圍(用16進製表示)。每一個byte能夠表 示00到FF(即0至255)。從圖中咱們能夠一目瞭然地看到爲何GB18030能夠兼容GBK,GB2312和ASCII 了。他們幾種編碼之間前兩位沒有重合部分。須要注意的是ASCII只有1byte,因此是沒有第二位的。另外 GB18030在上圖中佔的面積雖然很小,可是它是4bytes編碼,這圖只展現了前兩位。若是後兩位也算上, GB18030的字數要遠多於GBK。另外須要注意的是,因爲GBK兼容GB2312,所以屬於GB2312的藍色區域其 實也能夠算做是GBK的區域。同理GBK的區域理論上也屬於GB18030的區域。上表中只是展現了多出來的部 分。
實際生活中,咱們用到的99%以上的漢字,其實都在GB2312那一塊區域內。至於GB2312每一個編碼對應的到 底是哪一個漢字本文再也不贅述,能夠參考連接(連接地址)查詢。GBK編碼所對應的漢字能夠參考連接 (連接地址)查詢。至於GB18030編碼,因爲字數實在太多太難寫,已經很難在網上找到在線的編碼全表 了。不過通過一番搜尋,仍是找到了我國發布GB18030編碼時的相關文檔(GB18030-2005文檔、 GB18030-2000文檔)。
在實際使用中,GBK編碼已經能夠知足大部分場景了,GB18030編碼中全部漢字都是咱們這輩子都不必定能 見到的文字,這也是平時爲何常常會使用GBK的緣由吧。
表的基本操做
##前提:先選取要操做的數據庫 1)查看已有表 mysql>:show tables; 2)建立表 mysql>:create table 表名(字段1 類型, ..., 字段n 類型); eg>: create table student(name varchar(16), age int); eg>: create table teacher(name varchar(16), age int); 3)查看建立表的sql mysql>:show create table 表名; eg>: show create table student; 4)查看建立表的結構 mysql>:desc 表名; 5)改表結構 # 修改表名 mysql>: alter table 舊錶 rename 新表; # 修改字段名 mysql>: alter table 表名 change 舊字段 新字段 類型(長度); # 修改字段屬性 mysql>: alter table 表名 modify 字段 新類型(長度); 6)刪除表 mysql>: drop table 表名; eg>: drop table teacher;
建立表的完整語法
# 長度和約束在某些狀況下是能夠省略的 mysql>: create table 表名 ( 屬性名1 類型(長度) 約束, ... 屬性名n 類型(長度) 約束 ) engine=引擎 default charset=utf8;
記錄的基本操做
1)查看某個數據庫中的某個表的全部記錄,若是在對應數據庫中,能夠直接查找表 mysql>: select * from [數據庫名.]表名; 注:*表明查詢全部字段 2)給表的全部字段插入數據 mysql>: insert [into] [數據庫名.]表名 values (值1,...,值n); eg:若是給有name和age兩個字段的student表插入數據 1條>:insert into student values ('Bob', 18); 多條>:insert into student values ('張三', 18),('李四', 20); 指定庫>:insert owen.student values ('張三', 18),('李四', 20); 3)根據條件修改指定內容 mysql>: update [數據庫名.]表名 set 字段1=新值1, 字段n=新值n where 字段=舊值; eg:> update student set name='王五', age='100' where name='張三'; 注:i) 能夠只修改部分字段 ii) 沒有條件下,全部記錄都會被更新 eg:> update student set name='呵呵'; 4)根據條件刪除記錄 mysql>: delete from [數據庫名.]表名 where 條件; eg:> delete from student where age<30;
sql函數
函數及描述 NOW():返回當前的日期和時間 CURDATE():返回當前的日期 CURTIME():返回當前的時間 DATE():提取日期或日期/時間表達式的日期部分 EXTRACT():返回日期/時間按的單獨部分 DATE_ADD():給日期添加指定的時間間隔 DATE_SUB():從日期減去指定的時間間隔 DATEDIFF():返回兩個日期之間的天數 DATE_FORMAT():用不一樣的格式顯示日期/時間
mysql支持的數據類型
# mysql數據庫支持存放哪些數據 # 整型 | 浮點型 | 字符型 | 時間類型 | 枚舉類型 | 集合類型
整型
類型 | 大小 | 範圍(有符號) | 範圍(無符號) | 用途 |
---|---|---|---|---|
TINYINT | 1 字節 | (-128,127) | (0,255) | 小整數值 |
SMALLINT | 2 字節 | (-32 768,32 767) | (0,65 535) | 大整數值 |
MEDIUMINT | 3 字節 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整數值 |
INT或INTEGER | 4 字節 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整數值 |
BIGINT | 8 字節 | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 極大整數值 |
'''約束 unsigned:無符號 zerofill:0填充 ''' 3位 1 001 # 建表 mysql>: create table tb1(x tinyint, y smallint, z int(6)); # 插入數據 mysql>: insert into tb1 values(128, 32768, 32768); # 結果:127,32767,32768 # 結論:整型的長度由所佔字節(取值範圍)決定,能夠自定義長度,可是不影響所佔字節(取值範圍) # 全部整型變量的長度通常都省略不寫,不一樣類型所佔字節數不同, 決定所佔空間及存放數據的大小限制 結論>: create table tb1(x tinyint, y smallint, z int); # 整型約束 mysql>: create table tb2(x tinyint unsigned); # 0~255 mysql>: insert into tb2 values(256), (-1); # 255, 0 # 0填充約束 mysql>: create table tb3(x tinyint unsigned zerofill); mysql>: insert into tb3 values(10); # 010 '''寬度 1.不能決定整型存放數據的寬度, 超過寬度能夠存放, 最終由數據類型所佔字節決定 2.若是沒有超過寬度,且有zerofill限制, 會用0填充前置位的不足位 3.沒有必要規定整型的寬度, 默認設置的寬度就爲該整型能存放數據的最大寬度 * '''
浮點型
類型 | 大小 | 範圍(有符號) | 範圍(無符號) | 用途 |
---|---|---|---|---|
FLOAT | 4 字節 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 單精度 浮點數值 |
DOUBLE | 8 字節 | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 雙精度 浮點數值 |
DECIMAL | 對DECIMAL(M,D) ,若是M>D,爲M+2不然爲D+2 | 依賴於M和D的值 | 依賴於M和D的值 | 小數值 |
# 在安全模式下測試浮點型類型 '''類型 float(M, D):4字節,3.4E–38~3.4E+38 double(M, D):8字節,1.7E–308~1.7E+308 decimal(M, D):所在字節M,D大值基礎上+2,其實就是M值+2就是decimal字段所佔字節數,(M, D) => M爲位數,D爲小數位 ''' '''寬度: 限制存儲寬度 (M, D) => M爲位數,D爲小數位,M要大於等於D float(255, 30):精度最低,最經常使用 double(255, 30):精度高,佔位多 decimal(65, 30):字符串存,全精度 ''' # 建表: mysql>: create table tb4 (age float(256, 30)); # Display width out of range for column 'age' (max = 255) mysql>: create table tb5 (age float(255, 31)); # Too big scale 31 specified for column 'age'. Maximum is 30. mysql>: create table tb5 (age float(65, 30)); # 在合理取值範圍 mysql>: create table t12 (x float(255, 30)); mysql>: create table t13 (x double(255, 30)); mysql>: create table t14 (x decimal(65, 30)); # 1.111111164093017600000000000000 mysql>: insert into t12 values(1.11111111111111111119); # 1.111111111111111200000000000000 mysql>: insert into t13 values(1.11111111111111111119); # 1.111111111111111111190000000000 mysql>: insert into t14 values(1.11111111111111111119); # 重點:長度與小數位分析 # 報錯,總長度M必須大於等於小數位D mysql>: create table t14 (x decimal(2, 3)); # 能存儲 -0.9999 mysql>: create table t14 (x decimal(3, 3));
字符串:
數據庫優化 - char效率要高於varchar
類型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字節 | 定長字符串 |
VARCHAR | 0-65535 字節 | 變長字符串 |
TINYBLOB | 0-255字節 | 不超過 255 個字符的二進制字符串 |
TINYTEXT | 0-255字節 | 短文本字符串 |
BLOB | 0-65 535字節 | 二進制形式的長文本數據 |
TEXT | 0-65 535字節 | 長文本數據 |
MEDIUMBLOB | 0-16 777 215字節 | 二進制形式的中等長度文本數據 |
MEDIUMTEXT | 0-16 777 215字節 | 中等長度文本數據 |
LONGBLOB | 0-4 294 967 295字節 | 二進制形式的極大文本數據 |
LONGTEXT | 0-4 294 967 295字節 | 極大文本數據 |
CHAR 和 VARCHAR 類型相似,但它們保存和檢索的方式不一樣。它們的最大長度和是否尾部空格被保留等方面 也不一樣。在存儲或檢索過程當中不進行大小寫轉換。
BINARY 和 VARBINARY 相似於 CHAR 和 VARCHAR,不一樣的是它們包含二進制字符串而不要非二進制字符 串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,而且排序和比較基於列值 字節的數值值。
BLOB 是一個二進制大對象,能夠容納可變數量的數據。有 4 種 BLOB 類型:TINYBLOB、BLOB、 MEDIUMBLOB 和 LONGBLOB。它們區別在於可容納存儲範圍不一樣。
有 4 種 TEXT 類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。對應的這 4 種 BLOB 類型,可存儲的 最大長度不一樣,可根據實際狀況選擇。
'''類型 char:定長 varchar:不定長 ''' '''寬度 限制存儲寬度 char(4):以4個字符存儲定長存儲數據 varchar(4):數據長度決定字符長度,爲可變長度存儲數據 ''' # eg: create table t15 (x char(4), y varchar(4)); insert into t15 values("zero", 'owen'); # '' | "" 都可以表示字符 select x,y from t15; # 正常 insert into t15 values("yanghuhu", 'lxxVSegon'); # 非安全模式數據丟失,能夠存放, 安全模式報錯 select x,y from t15; # 能夠正常顯示丟失後(不完整)的數據 insert into t15 values('a', 'b'); # 驗證數據所在字符長度 # 前提: 安全模式下以空白填充字符 set global sql_mode="strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH"; # 重啓鏈接 select char_length(x), char_length(y) from t15; # a佔4 b佔1 '''重點: 存儲數據的方式 ** => 數據庫優化 char: 必定按規定的寬度存放數據, 以規定寬度讀取數據, 一般更佔空間 varchar: 首先根據數據長度計算所需寬度, 並在數據開始以數據頭方式將寬度信息保存起來, 是一個計算耗時過程, 取先讀取寬度信息,以寬度信息爲依準讀取數據, 一般節省空間 ''' 8: zero egon lxx yanghuhu 8: 4zero4egon3lxx8yanghuhu 注: varchar的數據頭佔1~2字節 規定char|varchar寬度均爲4,用來存放4個字符的數據, char存取更高效,char佔4字符,varchar佔5字符,char更省空間 總結: 數據長度相近的數據提倡用char來存放數據, 數據須要高速存取,以空間換時間, 採用char
時間
每一個時間類型有一個有效值範圍和一個"零"值,當指定不合法的MySQL不能表示的值時使用"零"值。
類型 | 大小 (字節) | 範圍 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 時間值或持續時間 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和時間值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038結束時間是第 2147483647 秒,北京時間 2038-1-19 11:14:07,格林尼治時間 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和時間值,時間戳 |
'''類型 year:yyyy(1901/2155) date:yyyy-MM-dd(1000-01-01/9999-12-31) time:HH:mm:ss datetime:yyyy-MM-dd HH:mm:ss(1000-01-01 00:00:00/9999-12-31 23:59:59) timestamp:yyyy-MM-dd HH:mm:ss(1970-01-01 00:00:00/2038-01-19 ??) ''' # eg: 1 create table t16(my_year year, my_date date, my_time time); insert into t16 values(); # 三個時間類型的默認值均是null insert into t16 values(2156, null, null); # 在時間範圍外,不容許插入該數據 insert into t16 values(1, '2000-01-01 12:00:00', null); # 2001 2000-01-01 null insert into t16 values(2019, '2019-01-08', "15-19-30"); # time報格式錯誤 => 按照時間規定格式存放數據 alter table t16 change my_year myYear year(2); # 時間的寬度修改後仍是採用默認寬度 => 不須要關係寬度 # eg:2 create table t17(my_datetime datetime, my_timestamp timestamp); insert into t17 values(null, null); # 能夠爲空, 不能爲null,賦值null採用默認值current_timestamp insert into t17 values('4000-01-01 12:00:00', '2000-01-01 12:00:00'); # 在各自範圍內能夠插入對應格式的時間數據 # datetime VS timestamp datetime:時間範圍,不依賴當前時區,8字節,能夠爲null timestamp:時間範圍,依賴當前時區,4字節,有默認值CURRENT_TIMESTAMP
二進制數據(_Blob)
1._BLOB和_text存儲方式不一樣,_TEXT以文本方式存儲,英文存儲區分大小寫,而_Blob是以二進制方式存儲,不 分大小寫。
2._BLOB存儲的數據只能總體讀出。
3._TEXT能夠指定字符集,_BLO不用指定字符集。
MYSQL數據類型的長度和範圍
各數據類型及字節長度一覽表:
數據類型 | 字節長度 | 範圍或用法 |
---|---|---|
Bit | 1 | 無符號[0,255],有符號[-128,127],天緣博客備註:BIT和BOOL布爾型都佔用1字節 |
TinyInt | 1 | 整數[0,255] |
SmallInt | 2 | 無符號[0,65535],有符號[-32768,32767] |
MediumInt | 3 | 無符號[0,2^24-1],有符號[-2^23,2^23-1]] |
Int | 4 | 無符號[0,2^32-1],有符號[-2^31,2^31-1] |
BigInt | 8 | 無符號[0,2^64-1],有符號[-2^63 ,2^63 -1] |
Float(M,D) | 4 | 單精度浮點數。天緣博客提醒這裏的D是精度,若是D<=24則爲默認的FLOAT,若是D>24則會自動被轉換爲DOUBLE型。 |
Double(M,D) | 8 | 雙精度浮點。 |
Decimal(M,D) | M+1或M+2 | 未打包的浮點數,用法相似於FLOAT和DOUBLE,天緣博客提醒您若是在ASP中使用到Decimal數據類型,直接從數據庫讀出來的Decimal可能須要先轉換成Float或Double類型後再進行運算。 |
Date | 3 | 以YYYY-MM-DD的格式顯示,好比:2009-07-19 |
Date Time | 8 | 以YYYY-MM-DD HH:MM:SS的格式顯示,好比:2009-07-19 11:22:30 |
TimeStamp | 4 | 以YYYY-MM-DD的格式顯示,好比:2009-07-19 |
Time | 3 | 以HH:MM:SS的格式顯示。好比:11:22:30 |
Year | 1 | 以YYYY的格式顯示。好比:2009 |
Char(M) | M | 定長字符串。 |
VarChar(M) | M | 變長字符串,要求M<=255 |
Binary(M) | M | 相似Char的二進制存儲,特色是插入定長不足補0 |
VarBinary(M) | M | 相似VarChar的變長二進制存儲,特色是定長不補0 |
Tiny Text | Max:255 | 大小寫不敏感 |
Text | Max:64K | 大小寫不敏感 |
Medium Text | Max:16M | 大小寫不敏感 |
Long Text | Max:4G | 大小寫不敏感 |
TinyBlob | Max:255 | 大小寫敏感 |
Blob | Max:64K | 大小寫敏感 |
MediumBlob | Max:16M | 大小寫敏感 |
LongBlob | Max:4G | 大小寫敏感 |
Enum | 1或2 | 最大可達65535個不一樣的枚舉值 |
Set | 可達8 | 最大可達64個不一樣的值 |
Geometry | ||
Point | ||
LineString | ||
Polygon | ||
MultiPoint | ||
MultiLineString | ||
MultiPolygon | ||
GeometryCollection |
使用建議
一、在指定數據類型的時候通常是採用從小原則,好比能用TINY INT的最好就不用INT,能用FLOAT類型的就 不用DOUBLE類型,這樣會對MYSQL在運行效率上提升很大,尤爲是大數據量測試條件下。
二、不須要把數據表設計的太過複雜,功能模塊上區分或許對於後期的維護更爲方便,慎重出現大雜燴數據表
三、數據表和字段的起名字也是一門學問
四、設計數據表結構以前請先想象一下是你的房間,或許結果會更加合理、高效
五、數據庫的最後設計結果必定是效率和可擴展性的折中,偏向任何一方都是欠妥的
選擇數據類型的基本原則
前提:使用適合存儲引擎。
選擇原則:根據選定的存儲引擎,肯定如何選擇合適的數據類型。
下面的選擇方法按存儲引擎分類:
- MyISAM 數據存儲引擎和數據列:MyISAM數據表,最好使用固定長度(CHAR)的數據列代替可變長度(VARCHAR)的數據列。
- MEMORY存儲引擎和數據列:MEMORY數據表目前都使用固定長度的數據行存儲,所以不管使用CHAR或VARCHAR列都沒有關係。二者都是做爲CHAR類型處理的。
- InnoDB 存儲引擎和數據列:建議使用 VARCHAR類型。
對於InnoDB數據表,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列簡單。於是,主要的性能因素是數據行使用的存儲總量。因爲CHAR平均佔用的空間多於VARCHAR,因 此使用VARCHAR來最小化須要處理的數據行的存儲總量和磁盤I/O是比較好的。
下面說一下固定長度數據列與可變長度的數據列。
char與varchar
CHAR和VARCHAR類型相似,但它們保存和檢索的方式不一樣。它們的最大長度和是否尾部空格被保留等方面也不一樣。在存儲或檢索過程當中不進行大小寫轉換。
下面的表顯示了將各類字符串值保存到CHAR(4)和VARCHAR(4)列後的結果,說明了CHAR和VARCHAR之間的差異:
值 | CHAR(4) | 存儲需求 | VARCHAR(4) | 存儲需求 |
---|---|---|---|---|
'' | ' ' | 4個字節 | '' | 1個字節 |
'ab' | 'ab ' | 4個字節 | 'ab ' | 3個字節 |
'abcd' | 'abcd' | 4個字節 | 'abcd' | 5個字節 |
'abcdefgh' | 'abcd' | 4個字節 | 'abcd' | 5個字節 |
請注意上表中最後一行的值只適用不使用嚴格模式時;若是MySQL運行在嚴格模式,超過列長度不的值不保存,而且會出現錯誤。
從CHAR(4)和VARCHAR(4)列檢索的值並不老是相同,由於檢索時從CHAR列刪除了尾部的空格。經過下面的例子說明該差異: mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4)); Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO vc VALUES ('ab ', 'ab '); Query OK, 1 row affected (0.00 sec)
mysql> SELECT CONCAT(v, '+'), CONCAT(c, '+') FROM vc; +----------------+----------------+ | CONCAT(v, '+') | CONCAT(c, '+') | +----------------+----------------+ | ab + | ab+ | +----------------+----------------+ 1 row in set (0.00 sec)
text和blob
在使用text和blob字段類型時要注意如下幾點,以便更好的發揮數據庫的性能。
①BLOB和TEXT值也會引發本身的一些問題,特別是執行了大量的刪除或更新操做的時候。刪除這種值會在數據表中留下很大的"空洞",之後填入這些"空洞"的記錄可能長度不一樣,爲了提升性能,建議按期使用 OPTIMIZE TABLE 功能對這類表進行碎片整理.
②使用合成的(synthetic)索引。合成的索引列在某些時候是有用的。一種辦法是根據其它的列的內容創建一個散列值,並把這個值存儲在單獨的數據列中。接下來你就能夠經過檢索散列值找到數據行了。可是,咱們要注意這種技術只能用於精確匹配的查詢(散列值對於相似<或>=等範圍搜索操做符 是沒有用處的)。咱們能夠使用MD5()函數生成散列值,也能夠使用SHA1()或CRC32(),或者使用本身的應用程序邏輯來計算散列值。請記住數值型散列值能夠很高效率地存儲。一樣,若是散列算法生成的字符串帶有尾部空格,就不要把它們存儲在CHAR或VARCHAR列中,它們會受到尾部空格去除的影響。
合成的散列索引對於那些BLOB或TEXT數據列特別有用。用散列標識符值查找的速度比搜索BLOB列自己的速度快不少。
③在沒必要要的時候避免檢索大型的BLOB或TEXT值。例如,SELECT *查詢就不是很好的想法,除非你可以肯定做爲約束條件的WHERE子句只會找到所須要的數據行。不然,你可能毫無目的地在網絡上傳輸大量的值。這也是 BLOB或TEXT標識符信息存儲在合成的索引列中對咱們有所幫助的例子。你能夠搜索索引列,決定那些須要的數據行,而後從合格的數據行中檢索BLOB或 TEXT值。
④把BLOB或TEXT列分離到單獨的表中。在某些環境中,若是把這些數據列移動到第二張數據表中,可讓你把原數據表中 的數據列轉換爲固定長度的數據行格式,那麼它就是有意義的。這會減小主表中的碎片,使你獲得固定長度數據行的性能優點。它還使你在主數據表上運行 SELECT *查詢的時候不會經過網絡傳輸大量的BLOB或TEXT值。
浮點數與定點數
爲了可以引發你們的重視,在介紹浮點數與定點數之前先讓你們看一個例子: mysql> CREATE TABLE test (c1 float(10,2),c2 decimal(10,2)); Query OK, 0 rows affected (0.29 sec)
mysql> insert into test values(131072.32,131072.32); Query OK, 1 row affected (0.07 sec)
mysql> select * from test; +-----------+-----------+ | c1 | c2 | +-----------+-----------+ | 131072.31 | 131072.32 | +-----------+-----------+ 1 row in set (0.00 sec)
從上面的例子中咱們看到c1列的值由131072.32變成了131072.31,這就是浮點數的不精確性形成的。
在mysql中float、double(或real)是浮點數,decimal(或numberic)是定點數。
浮點數相對於定點數的優勢是在長度必定的狀況下,浮點數可以表示更大的數據範圍;它的缺點是會引發精度問題。在從此關於浮點數和定點數的應用中,你們要記住如下幾點:
- 浮點數存在偏差問題;
- 對貨幣等對精度敏感的數據,應該用定點數表示或存儲;
- 編程中,若是用到浮點數,要特別注意偏差問題,並儘可能避免作浮點數比較;
- 要注意浮點數中一些特殊值的處理。
補充
一、一個漢字佔多少長度與編碼有關:
UTF-8:一個漢字=3個字節
GBK:一個漢字=2個字節
二、varchar(n) 表示 n 個字符,不管漢字和英文,Mysql 都能存入 n 個字符,僅是實際字節長度有所區別
三、MySQL 檢查長度,可用 SQL 語言來查看:
select LENGTH(字段名) from 表名
枚舉與集合
枚舉類型,enum
每一個枚舉值均有一個索引值:
在列說明中列表值所容許的成員值被從 1 開始編號。
通常來講就是單選,在定義枚舉的時候列出全部的可能性;
代碼以下
1. create table type_enum( 2. gender enum('male','remale','serect'), 3. ); 4. insert into type_enum values ('remale');
在處理時,相似字符串型進行操做!
意義在於:
1, 限定值的可能性!
2, 速度快,比普通的字符串速度快!
緣由是枚舉型 是利用 整數進行管理的,可以2個字節進行管理!
每一個值,都是一個整數標識,從第一個選項開始爲1,逐一遞增!
管理時整數的形式,速度比字符串快!
一共有2 個字節,0-65535,所以能夠有 65535個選項能夠使用!、
集合 set 不定想項選
相似於 enum枚舉,在定義時,也須要指定其已有值!
與字符串相比,優點是:
1, 也是採用 整數進行管理的!採用位運算,從第一位開始爲1,逐一x2!
2, 每一個集合類型8個字節,64位,所以能夠表示64個元素!
注意:站在 mysql的角度,儘可能多用枚舉和集合!
擴展:
集合 set 擴展
在建立表時,就指定SET類型的取值範圍。
屬性名 SET('值1','值2','值3'...,'值n')
其中,「屬性名」參數指字段的名稱;「值n」參數表示列表中的第n個值,這些值末尾的空格將會被系統直接刪除。其基本形式與ENUM類型同樣。SET類型的值能夠取列表中的一個元素或者多個元素的組合。取多個元素時,不一樣元素之間用逗號隔開。SET類型的值最多隻能是有64個元素構成的組合,根據成員的不一樣,存儲上也有所不一樣:
1~8成員的集合,佔1個字節。 9~16成員的集合,佔2個字節。 17~24成員的集合,佔3個字節。 25~32成員的集合,佔4個字節。 33~64成員的集合,佔8個字節。
同ENUM類型同樣,列表中的每一個值都有一個順序排列的編號。MySQL中存入的是這個編號,而不是列表中的值。
插入記錄時,SET字段中的元素順序可有可無。存入MySQL數據庫後,數據庫系統會自動按照定義時的順序顯示。若是插入的成員中有重複,則只存儲一次。
枚舉類型,enum擴展
ENUM類型(枚舉類型),與C#的概念同樣,在定義時指定取值範圍。
ENUM類型的值範圍須要在建立表時經過枚舉方式顯式指定,對1~255個成員的枚舉須要1個字節存儲;對於256~65535個成員,須要2個字節存儲。最多能夠有65535個成員,而SET類型最多隻能包含64個成員。二者的取值只能在成員列表中選取。ENUM類型只能從成員中選擇一個,而SET類型能夠選擇多個。
所以,對於多個值中選取一個的,能夠選擇ENUM類型。例如,「性別」字段就能夠定義成ENUM類型,由於只能在「男」和「女」中選其中一個。對於能夠選取多個值的字段,能夠選擇SET類型。例如,「愛好」字段就能夠選擇SET類型,由於可能有多種愛好。
屬性名 ENUM('值1','值2','值3'...'值n')
◆其中,屬性名參數指字段的名稱;「值n」參數表示列表中的第n個值,這些值末尾的空格將會被系統直接刪除。ENUM類型的值只能取列表中的一個元素。其取值列表中最多能有65535個值。列表中的每一個值都有一個順序排列的編號,MySQL中存入的是這個編號,而不是列表中的值。
◆ENUM 有 NOT NULL 屬性,其默認值爲取值列表的第一個元素; ◆ENUM 無 NOT NULL,則ENUM類型將容許插入NULL,而且NULL爲默認值;
CREATE TABLE Test4(Sex ENUM('男','女')); INSERT INTO Test4 VALUES('男'); INSERT INTO Test4 VALUES('爺'); --這行報錯 SELECT * FROM Test4;
ENUM 是一個字符串對象,其值一般選自一個容許值列表中,該列表在表建立時的列規格說明中被明確地列舉。
在下列某些狀況下,值也能夠是空串('') 或 NULL: ◆若是將一個無效值插入一個 ENUM (即,一個不在容許值列表中的字符串),空字符串將做爲一個特殊的錯誤值被插入。事實上,這個字符串有別於一個'普通的'空字符串,由於這個字符串有個數字索引值爲 0。稍後有更詳細描述。 ◆若是一個 ENUM 被聲明爲 NULL,NULL 也是該列的一個合法值,而且該列的缺省值也將爲 NULL 。若是一個 ENUM 被聲明爲 NOT NULL,該列的缺省值將是該列表所容許值的第一個成員。
每一個枚舉值均有一個索引值: ◆在列說明中列表值所容許的成員值被從 1 開始編號。 ◆空字符串錯誤值的索引值爲 0。這就意味着,你能夠使用下面所示的 SELECT 語句找出被賦於無效 ENUM值的記錄行。 mysql> SELECT * FROM tbl_name WHERE enum_col=0; ◆NULL 值的索引值爲 NULL。
例如,指定爲 ENUM('one', 'two', 'three') 的一個列,能夠有下面所顯示的任一值。每一個值的索引值也以下所示:
值 | 索引值 |
---|---|
NULL | NULL |
'' | 0 |
'one' | 1 |
'two' | 2 |
'three' | 3 |
換個枚舉最大能夠有 65535 個成員值。
從 MySQL 3.23.51 開始,當表被建立時,ENUM 值尾部的空格將會自動刪除。
當爲一個 ENUM 列賦值時,字母的大小寫是可有可無的。然而,之後從列中檢索出來的值的大小寫倒是匹配於建立表時所指定的容許值。
若是在一個數字語境中檢索一個ENUM,列值的索引值將被返回。例如,你能夠像這樣使用數字值檢索一個 ENUM 列:
mysql> SELECT enum_col+0 FROM tbl_name;
若是將一個數字存儲到一個 ENUM 中,數字被看成爲一個索引值,而且存儲的值是該索引值所對應的枚舉成員。(可是,這在 LOAD DATA 將不能工做,由於它視全部的輸入均爲字符串。) 在一個 ENUM 字符串中存儲數字是不明智的,由於它可能會打亂思惟。
ENUM 值依照列規格說明中的列表順序進行排序。(換句話說,ENUM 值依照它們的索引號排序。)舉例來講,對於 ENUM('a', 'b') 'a' 排在 'b' 後,可是對於 ENUM('b', 'a') , 'b' 卻排在 'a' 以前。空字符串排在非空字符串前,NULL 值排在其它全部的枚舉值前。爲了防止意想不到的結果,建議依照字母的順序定義 ENUM 列表。也能夠經過使用 GROUP BY CONCAT(col) 來肯定該以字母順序排序而不是以索引值。
若是但願獲得一個 ENUM 列的全部可能值,能夠使用:
SHOW COLUMNS FROM table_name LIKE enum_colum;
SET 與 ENUM 類型的查詢修改操做 SET FOREIGN_KEY_CHECKS=0;
-- Table structure for setenum
DROP TABLE IF EXISTS setenum
; CREATE TABLE setenum
( id
int(11) NOT NULL AUTO_INCREMENT, settype
set('we','周','李','孫','錢','趙') DEFAULT NULL, enumtype
enum('ZZZ','南海','長江','黃河') DEFAULT NULL, PRIMARY KEY (id
) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- Records of setenum
INSERT INTO setenum
VALUES ('1', 'we,周,錢', '南海'); INSERT INTO setenum
VALUES ('2', '錢,趙', '黃河'); INSERT INTO setenum
VALUES ('3', 'we,趙', '南海'); INSERT INTO setenum
VALUES ('4', '李,孫,錢', '長江');
set('we','周','李','孫','錢','趙')=111111=63 enum('ZZZ','南海','長江','黃河')=100=4
以下表所示:
SET類型:低位(右) → 高位(左)
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 |
從右到左排:11111=63
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 0 |
從右到左排:010011=19
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 1 | 1 |
從右到左排:110000=48
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 1 |
從右到左排:100001=33
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
0 | 0 | 1 | 1 | 1 | 0 |
從右到左排:011100=28
ENUM類型
ZZZ | 南海 | 長江 | 黃河 |
---|---|---|---|
1 | 2 | 3 | 4 |
ZZZ | 南海 | 長江 | 黃河 |
1 | 2 | 3 | 4 |
黃河=4=100
ZZZ | 南海 | 長江 | 黃河 |
---|---|---|---|
1 | 2 | 3 | 4 |
長江=3=11
ZZZ | 南海 | 長江 | 黃河 |
---|---|---|---|
1 | 2 | 3 | 4 |
南海=2=10
ZZZ | 南海 | 長江 | 黃河 |
---|---|---|---|
1 | 2 | 3 | 4 |
ZZZ=1=1
mysql> select * from setenum; +----+----------+----------+ | id | settype | enumtype | +----+----------+----------+ | 1 | we,周,錢 | 南海 | | 2 | 錢,趙 | 黃河 | | 3 | we,趙 | 南海 | | 4 | 李,孫,錢 | 長江 | +----+----------+----------+ 4 rows in set
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum; +----------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +----------+-----------+----------------+----------+------------+-----------------+ | we,周,錢 | 19 | 10011 | 南海 | 2 | 10 | | 錢,趙 | 48 | 110000 | 黃河 | 4 | 100 | | we,趙 | 33 | 100001 | 南海 | 2 | 10 | | 李,孫,錢 | 28 | 11100 | 長江 | 3 | 11 | +----------+-----------+----------------+----------+------------+-----------------+ 4 rows in set
mysql> select * from setenum where settype=33; +----+---------+----------+ | id | settype | enumtype | +----+---------+----------+ | 3 | we,趙 | 南海 | +----+---------+----------+ 1 row in set
mysql> select * from setenum where enumtype=2; +----+----------+----------+ | id | settype | enumtype | +----+----------+----------+ | 1 | we,周,錢 | 南海 | | 3 | we,趙 | 南海 | +----+----------+----------+ 2 rows in set
--不支持二進制查詢 mysql> select * from setenum where settype=b'010011'; Empty set
mysql> select * from setenum where settype=b'10011'; Empty set
mysql> select * from setenum where enumtype=b'100'; Empty set
mysql> SELECT * FROM setenum WHERE settype LIKE '%趙%'; +----+---------+----------+ | id | settype | enumtype | +----+---------+----------+ | 2 | 錢,趙 | 黃河 | | 3 | we,趙 | 南海 | +----+---------+----------+ 2 rows in set
--與FIND_IN_SET函數同 mysql> SELECT * FROM setenum WHERE FIND_IN_SET('趙',settype)>0; +----+---------+----------+ | id | settype | enumtype | +----+---------+----------+ | 2 | 錢,趙 | 黃河 | | 3 | we,趙 | 南海 | +----+---------+----------+ 2 rows in set
--當查詢只是集合某個值的一部分時,與FIND_IN_SET函數不一樣 mysql> SELECT * FROM setenum WHERE FIND_IN_SET('e',settype)>0; Empty set
mysql> SELECT * FROM setenum WHERE settype LIKE '%e%'; +----+----------+----------+ | id | settype | enumtype | +----+----------+----------+ | 1 | we,周,錢 | 南海 | | 3 | we,趙 | 南海 | +----+----------+----------+ 2 rows in set
mysql> SELECT * FROM setenum WHERE settype LIKE '趙'; Empty set
mysql> SELECT * FROM setenum WHERE settype = '趙'; Empty set
mysql> SELECT * FROM setenum WHERE settype LIKE 'we,趙'; +----+---------+----------+ | id | settype | enumtype | +----+---------+----------+ | 3 | we,趙 | 南海 | +----+---------+----------+ 1 row in set
mysql> SELECT * FROM setenum WHERE settype = 'we,趙'; +----+---------+----------+ | id | settype | enumtype | +----+---------+----------+ | 3 | we,趙 | 南海 | +----+---------+----------+ 1 row in set
--若是把集合的順序改一下,照樣無效 mysql> SELECT * FROM setenum WHERE settype LIKE '趙,we'; Empty set
mysql> SELECT * FROM setenum WHERE settype = '趙,we'; Empty set
mysql> SELECT * FROM setenum WHERE enumtype LIKE '%海%';
+----+----------+----------+ | id | settype | enumtype | +----+----------+----------+ | 1 | we,周,錢 | 南海 | | 3 | we,趙 | 南海 | +----+----------+----------+ 2 rows in set
mysql> SELECT * FROM setenum WHERE enumtype = '南海'; +----+----------+----------+ | id | settype | enumtype | +----+----------+----------+ | 1 | we,周,錢 | 南海 | | 3 | we,趙 | 南海 | +----+----------+----------+ 2 rows in set
mysql> SELECT * FROM setenum WHERE enumtype = '海'; Empty set
--------------------UPDATE 語法--------------------
set('we','周','李','孫','錢','趙')=111111=63
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +----------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +----------+-----------+----------------+----------+------------+-----------------+ | we,周,錢 | 19 | 10011 | 南海 | 2 | 10 | +----------+-----------+----------------+----------+------------+-----------------+ 1 row in set
mysql> update setenum set settype = 2 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +---------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +---------+-----------+----------------+----------+------------+-----------------+ | 周 | 2 | 10 | 南海 | 2 | 10 | +---------+-----------+----------------+----------+------------+-----------------+ 1 row in set
--修改settype讓其'we'、'周'、'李' 成員爲真 mysql> update setenum set settype =settype|1|4|6 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
--|1|4|6 表示 二進制的OR運算 1 or 100 or 110 = 111 = 7 --實際與 1|6 結果是同樣的:1 or 110 = 111 = 7
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
1 | 1 | 1 | 0 | 0 | 0 |
從右到左排:000111=7
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +----------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +----------+-----------+----------------+----------+------------+-----------------+ | we,周,李 | 7 | 111 | 南海 | 2 | 10 | +----------+-----------+----------------+----------+------------+-----------------+ 1 row in set
--實際與 1|6 結果是同樣的:1 or 110 = 111 = 7 mysql> update setenum set settype =settype|1|6 where id=1; Query OK, 0 rows affected Rows matched: 1 Changed: 0 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +----------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +----------+-----------+----------------+----------+------------+-----------------+ | we,周,李 | 7 | 111 | 南海 | 2 | 10 | +----------+-----------+----------------+----------+------------+-----------------+ 1 row in set
--settype|1|6 的settype 能夠省略,結果同樣 mysql> update setenum set settype = 1|6 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +----------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +----------+-----------+----------------+----------+------------+-----------------+ | we,周,李 | 7 | 111 | 南海 | 2 | 10 | +----------+-----------+----------------+----------+------------+-----------------+ 1 row in set
-- &表示與運算,1 and 110 = 0,注意0與NULL不一樣 mysql> update setenum set settype = 1 & 6 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +---------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +---------+-----------+----------------+----------+------------+-----------------+ | | 0 | 0 | 南海 | 2 | 10 | +---------+-----------+----------------+----------+------------+-----------------+ 1 row in set
-- &表示與運算,~表示反運算,6=110,~6=001,1 and 001 = 1 mysql> update setenum set settype = null where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +---------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +---------+-----------+----------------+----------+------------+-----------------+ | NULL | NULL | NULL | 南海 | 2 | 10 | +---------+-----------+----------------+----------+------------+-----------------+ 1 row in set
mysql> update setenum set settype = 1 & ~6 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +---------+-----------+----------------+----------+------------+-----------------+ | settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) | +---------+-----------+----------------+----------+------------+-----------------+ | we | 1 | 1 | 南海 | 2 | 10 | +---------+-----------+----------------+----------+------------+-----------------+ 1 row in set
-- 5 and ~1 = 101 and ~1 = 101 and 111110 = 100 = 4 mysql> update setenum set settype = null where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
mysql> update setenum set settype = 5 & ~1 where id=1; Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0
we | 周 | 李 | 孫 | 錢 | 趙 |
---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 |
從右到左排:000100=4
mysql> select settype,settype+0,bin(settype+0),enumtype,enumtype+0,bin(enumtype+0) from setenum where id=1; +---------+-----------+----------------+----------+------------+-----------------+
settype | settype+0 | bin(settype+0) | enumtype | enumtype+0 | bin(enumtype+0) |
---|---|---|---|---|---|
+---------+-----------+----------------+----------+------------+-----------------+ | |||||
李 | 4 | 100 | 南海 | 2 | 10 |
---- | ---- | ---- | ---- | ---- | ---- |
+---------+-----------+----------------+----------+------------+-----------------+ | |||||
1 row in set |
枚舉和集合的簡單運用
# 枚舉與集合:爲某一個字段提供選項的 - 枚舉只能單選(1個),集合能夠多選(0-n個) # 建表 # enum、set默認值爲NULL mysql>: create table tc1 (name varchar(20), sex enum('男', '女', '哇塞'), hobbies set('男', '女', '哇塞')); mysql>: insert into tc1 values('ruakei', '哇塞哇塞', '未知'); # enum、set手動設置默認值 '男' 與 '哇塞' mysql>: create table tc2 (name varchar(20), sex enum('男', '女', '哇塞') default '男', hobbies set('男', '女', '哇塞') default '哇塞'); mysql>: insert into tc2 values('ruakei', '哇塞哇塞', '未知'); mysql>: insert into tc2(name) values('ruakei'); # 對sex、hobbies兩個字段賦值錯誤,系統默認用空字符串填充(非安全模式),安全模式拋異常 # 若是對出sex、hobbies兩個字段外的其餘字段進行賦值,這兩個字段會纔有默認值 # 注:對set類型的字段進行賦值,用一個字符串,字符串內部用,將多個選項隔開,且不能添加空格等其餘額外字符 mysql>: insert into tc2 values('ruakei_1', '女', '男,女,哇塞');
約束
sql約束:約束用於限制加入表的數據的類型。是一種限制,它經過對錶的行或列的數據作出限制,來確保表數據的完整性、惟一性能夠在建立表時規定約束(經過 CREATE TABLE 語句),或者在表建立以後也能夠(經過 ALTER TABLE 語句)。
數據類型的屬性
MySQL關鍵字 | 含義 |
---|---|
NULL | 數據列可包含NULL值 |
NOT NULL | 數據列不容許包含NULL值 |
DEFAULT | 默認值 |
PRIMARY KEY | 主鍵 |
AUTO_INCREMENT | 自動遞增,適用於整數類型 |
UNSIGNED | 無符號 |
CHARACTER SET name | 指定一個字符集 |
一、not null 約束:強制列不接受 NULL 值,強制字段始終包含值。這意味着,若是不向字段添加值,就沒法插入新記錄或者更新記錄。 例:create table table_name(id int not null,name varchar(255) not null); # 強制id和name不能爲空 二、unique 約束:惟一標識數據庫表中的每條記錄,確保表中的一列數據沒有相同的值 UNIQUE 和 PRIMARY KEY 約束均爲列或列集合提供了惟一性的保證。 PRIMARY KEY 擁有自動定義的 UNIQUE 約束。 每一個表能夠有多個 UNIQUE 約束,可是每一個表只能有一個 PRIMARY KEY 約束 例:create table時在id列建立unique約束 create table table_name(id int not null,name varchar(255) not null, unique (id)); 例2:爲多個列定義unique create table table_name(id int not null,name varchar(255) not null, constraint uc_personID unique (id,name)) 例3:表已建立狀況下,建立unique約束 alter table table_name add unique(id); 多個:alter table table_name add constraint uc_personid unique(id,name); 例4:撤銷unique alter table table_name drop index uc_personid; 三、PRIMARY KEY 約束:PRIMARY KEY 約束惟一標識數據庫表中的每條記錄。 主鍵必須包含惟一的值。 主鍵列不能包含 NULL 值。 每一個表都應該有一個主鍵,而且每一個表只能有一個主鍵。 primary key = unique + not null 例:create table時在id列建立PRIMARY KEY約束 create table table_name(id int not null,name varchar(255) not null, PRIMARY KEY(id)); 例2:爲多個列定義PRIMARY KEY create table table_name(id int not null,name varchar(255) not null, constraint pk_personID PRIMARY KEY (id,name)) 例3:表已建立狀況下,建立PRIMARY KEY約束 alter table table_name add PRIMARY KEY(id); 多個:alter table table_name add constraint pk_personid PRIMARY KEY(id,name); 例4:撤銷PRIMARY KEY alter table table_name drop index uc_personid; 四、FOREIGN KEY 約束:一個表中的 FOREIGN KEY 指向另外一個表中的 PRIMARY KEY 外鍵 外鍵用來在兩個表數據之間創建連接,它能夠是一列或多列。一個表能夠有一個或多個外鍵 外鍵對應得是參照完整性,一個表得外鍵能夠爲空值,若不爲空值,則每個外鍵值必須等於另外一個表中主鍵得某個值。 FOREIGN KEY 約束用於預防破壞表之間鏈接的動做。 FOREIGN KEY 約束也能防止非法數據插入外鍵列,由於它必須是它指向的那個表中的值之一。 例:create table時在id列建立 FOREIGN KEY 約束 create table table_name1(id int not null,name varchar(255) not null,Id_P int, PRIMARY KEY(id),FOREIGN KEY (Id_P) REFERENCES table_name2(Id_P)); 例2:爲多個列定義 FOREIGN KEY create table table_name1(id int not null,name varchar(255) not null,Id_P int, PRIMARY KEY(id) constraint fk_pertb2 FOREIGN KEY (Id_P) REFERENCES table_name2(Id_P) ) 例3:表已建立狀況下,建立 FOREIGN KEY 約束 alter table table_name add ADD FOREIGN KEY (Id_P) REFERENCES table_name1(Id_P); 多個:alter table table_name add constraint pk_personid PRIMARY KEY(id,name); 例4:撤銷 FOREIGN KEY alter table table_name drop FOREIGN KEY fk_pertb2; 外鍵約束 mysql> create table bookcategory( -> category_id int primary key, -> category varchar(20), -> parent_id int); mysql> create table bookinfo( -> book_id int primary key, -> book_category_id int, -> constraint fk_cid foreign key(book_category_id) references bookcategory(category_id)); 五、CHECK 約束:用於限制列中的值的範圍 若是對單個列定義 CHECK 約束,那麼該列只容許特定的值。 若是對一個表定義 CHECK 約束,那麼此約束會在特定的列中對值進行限制。 例:create table時在id列建立 CHECK 約束 create table table_name(id int not null,name varchar(255) not null,CHECK(id>0)); 例2:爲多個列定義 CHECK 約束 create table table_name(id int not null,name varchar(255) not null, constraint chk_tbname CHECK(id>0 and name='xxx')); 例3:表已建立狀況下,建立 CHECK 約束 alter table table_name ADD constraint chk_tbname CHECK (Id_P>0 AND name='xxx'); 例4:撤銷 CHECK alter table table_name drop constraint chk_tbname; 六、DEFAULT 約束:用於向列中插入默認值 若是沒有規定其餘的值,那麼會將默認值添加到全部的新記錄。 例:create table時在id列建立 DEFAULT 約束,相似 GETDATE() 這樣的函數,DEFAULT 約束也能夠用於插入系統值 create table table_name(id int not null,name varchar(255) not null DEFAULT 'lxq',timedate date DEFAULT GETDATE()); 例2:表已建立狀況下,建立 DEFAULT 約束 alter table table_name alter name set DEFAULT 'lxq2'; 例3:撤銷 DEFAULT alter table table_name ALTER name DROP DEFAULT;
約束條件的簡單運用
""" primary key:主鍵,惟一標識,表都會擁有,不設置爲默認找第一個 不空,惟一 字段,未標識則建立隱藏字段 foreign key:外鍵 unique:惟一性數據, 該條字段的值須要保證惟一,不能重複 auto_increment:自增,只能加給key的int類型字段輔助修飾 not null:不爲空 - 針對一些字段,如註冊時的用戶名,出生人的性別等,這些需求下的字段,只不能設置爲Null,必需要對其賦值 null 可爲空 default:默認值 - 對有默認值意外的字段進行賦值時,有默認值的字段會被賦默認值 unsigned:無符號 - 存儲的數字從0開始 zerofill:0填充 - 存整數時數據長度小於取值範圍長度,會在數字左方用0填充 """ mysql>: create table td1 (x int, y int default 0, z int default 100); #清空表,並清空主鍵自增記錄 truncate table 數據庫.表名; 注: 1.鍵是用來說的io提供存取效率 2.聯合惟一 create table web ( ip char(16), port int, unique(ip,port) ); 3.聯合主鍵 create table web ( ip char(16), port int, primary key(ip,port) ); # eg:1 # 單列惟一 create table t20 ( id int unique ); # 聯合惟一 create table web ( ip char(16), port int, unique(ip,port) ); # 若是聯合兩個字段,兩個字段全相同才相同,不然爲不一樣 insert into web values ('10.10.10.10', 3306), ('10.10.10.10', 3306); # 注: # 1.表默認都有主鍵, 且只能擁有一個主鍵字段(單列主鍵 | 聯合主鍵) # 2.沒有設置主鍵的表, 數據庫系統會自上而下將第一個規定爲unique not null字段自動提高爲primary key主鍵 # 3.若是整個表都沒有unique not null字段且沒有primary key字段, 系統會默認建立一個隱藏字段做爲主鍵 # 4.一般必須手動指定表的主鍵, 通常用id字段, 且id字段通常類型爲int, 由於int類型能夠auto_increment # eg:2 create table t21(id int auto_increment); # 自增約束必須添加給key的字段 # eg:3 create table t21(id int primary key auto_increment); # 自增要結合key,不賦值插入,數據會自動自增, 且自增的結果一直被記錄保留 # eg:4 # 聯合主鍵 create table t22( ip char(16), port int, primary key(ip,port) ); # 若是聯合兩個字段,兩個字段全相同才相同,不然爲不一樣 insert into web values ('10.10.10.10', 3306), ('10.10.10.10', 3306);
表中字段的詳細操做
create table t2( id int primary key auto_increment, x int, y int ); insert into t2(x, y) values(10, 20), (100, 200), (1000, 2000); ''' 1.修改字段信息 alter table 表名 modify 字段名 類型[(寬度) 約束]; alter table t2 modify x bigint default 0; # 模式不一樣, 涉及精度問題 2.修改字段名及信息 alter table 表名 change 舊字段名 新字段名 類型[(寬度) 約束]; alter table t2 change y c char(10) not null; # 模式不一樣, 涉及類型轉換問題 3.添加字段名 # 末尾添加 alter table 表名 add 字段名 類型[(寬度) 約束], ..., add 字段名 類型[(寬度) 約束]; alter table t2 add age int, add gender enum("male", "female", "wasai") default "wasai"; # t頭部添加 alter table 表名 add 字段名 類型[(寬度) 約束] first; # 指定位添加:指定字段後 alter table 表名 add 字段名 類型[(寬度) 約束] after 舊字段名; alter table t2 add y int after x; 4.刪除字段名 alter table 表名 drop 字段名; alter table t2 drop y; '''
擴展
目前關係數據庫有六種範式:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、巴斯-科德範式(BCNF)、第四範式(4NF)和第五範式(5NF,又稱完美範式)。通常說來,數據庫只需知足第三範式(3NF)就好了。下面用畫圖方式簡單介紹下前三範式
三範式
1NF:字段不可分; 2NF:有主鍵,非主鍵字段依賴主鍵; 3NF:非主鍵字段不能相互依賴;
解釋: 1NF:原子性 字段不可再分,不然就不是關係數據庫; 2NF:惟一性 一個表只說明一個事物; 3NF:每列都與主鍵有直接關係,不存在傳遞依賴;
1NF:無重複的列,每一列都是不可分割的基本數據項,同一 列中不能有多個值,即實體中的某個屬性不能有多個值或者不 能有重複的屬性。除去同類型的字段,就是無重複的列 說明:第一範式(1NF)是對關係模式的基本要求,不知足第 一範式(1NF)的數據庫就不是關係數據庫
2NF:屬性徹底依賴於主鍵,第二範式必須先知足第一範式, 要求表中的每一個行必須能夠被惟一地區分。一般爲表加上一個 列,以存儲各個實例的惟一標識PK,非PK的字段須要與整個 PK有直接相關性
3NF:屬性不依賴於其它非主屬性,知足第三範式必須先知足 第二範式。第三範式要求一個數據庫表中不包含已在其它表中 已包含的非主關鍵字信息,非PK的字段間不能有從屬關係
四、BCNF(BC範式)
它構建在第三範式的基礎上,若是關係模型R是第一範式,且每一個屬性都不傳遞依賴於R的候選鍵,那麼稱R爲BCNF的模式。
假設倉庫管理關係表(倉庫號,存儲物品號,管理員號,數量),知足一個管理員只在一個倉庫工做;一個倉庫能夠存儲多種物品,則存在以下關係:
(倉庫號,存儲物品號)——>(管理員號,數量)
(管理員號,存儲物品號)——>(倉庫號,數量)
因此,(倉庫號,存儲物品號)和(管理員號,存儲物品號)都是倉庫管理關係表的候選碼,表中惟一非關鍵字段爲數量,它是符合第三範式的。可是,因爲存在以下決定關係:
(倉庫號)——>(管理員號)
(管理員號)——>(倉庫號)
即存在關鍵字段決定關鍵字段的狀況,所以其不符合BCNF。把倉庫管理關係表分解爲兩個關係表倉庫管理表(倉庫號,管理員號)和倉庫表(倉庫號,存儲物品號,數量),這樣這個數據庫表是符合BCNF的,並消除了刪除異常、插入異常和更新異常。
五、4NF(第四範式)
設R是一個關係模型,D是R上的多值依賴集合。若是D中存在凡多值依賴X->Y時,X必是R的超鍵,那麼稱R是第四範式的模式。
例如,職工表(職工編號,職工孩子姓名,職工選修課程),在這個表中,同一個職工可能會有多個職工孩子姓名,一樣,同一個職工也可能會有多個職工選修課程,即這裏存在着多值事實,不符合第四範式。若是要符合第四範式,只須要將上表分爲兩個表,使它們只有一個多值事實,例如職工表一(職工編號,職工孩子姓名),職工表二(職工編號,職工選修課程),兩個表都只有一個多值事實,因此符合第四範式。
拓展:各範式的關係圖以下所示:
表關係
社會中存儲須要能夠構建成表的數據, 它們造成的表,每每之間存儲某種或某些社會關係,
mysql數據庫創建表結構就是社會中產生的各類數據, 分門別類管理
但mysql創建的(代碼層次的)表之間, 一樣須要處理表與表之間的關係
造成了 一對一|一對多 | 多對多 三種關係
外鍵
1、基本概念
一、MySQL中「鍵」和「索引」的定義相同,因此外鍵和主鍵同樣也是索引的一種。不一樣的是MySQL會自動爲全部表的主鍵進行索引,可是外鍵字段必須由用戶進行明確的索引。用於外鍵關係的字段必須在全部的參照表中進行明確地索引,InnoDB不能自動地建立索引。
二、外鍵能夠是一對一的,一個表的記錄只能與另外一個表的一條記錄鏈接,或者是一對多的,一個表的記錄與另外一個表的多條記錄鏈接。
三、若是須要更好的性能,而且不須要完整性檢查,能夠選擇使用MyISAM表類型,若是想要在MySQL中根據參照完整性來創建表而且但願在此基礎上保持良好的性能,最好選擇表結構爲innoDB類型。
四、外鍵的使用條件
① 兩個表必須是InnoDB表,MyISAM表暫時不支持外鍵
② 外鍵列必須創建了索引,MySQL 4.1.2之後的版本在創建外鍵時會自動建立索引,但若是在較早的版本則須要顯式創建;
③ 外鍵關係的兩個表的列必須是數據類型類似,也就是能夠相互轉換類型的列,好比int和tinyint能夠,而int和char則不能夠;
五、外鍵的好處:能夠使得兩張表關聯,保證數據的一致性和實現一些級聯操做。保持數據一致性,完整性,主要目的是控制存儲在外鍵表中的數據。 使兩張表造成關聯,外鍵只能引用外表中的列的值!能夠使得兩張表關聯,保證數據的一致性和實現一些級聯操做;
2、使用方法
一、建立外鍵的語法:
外鍵的定義語法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
該語法能夠在 CREATE TABLE 和 ALTER TABLE 時使用,若是不指定CONSTRAINT symbol,MYSQL會自動生成一個名字。
ON DELETE、ON UPDATE表示事件觸發限制,可設參數:
① RESTRICT(限制外表中的外鍵改動,默認值)
② CASCADE(跟隨外鍵改動)
③ SET NULL(設空值)
④ SET DEFAULT(設默認值)
⑤ NO ACTION(無動做,默認的)
二、示例
1)建立表1
create table repo_table(
repo_id char(13) not null primary key,
repo_name char(14) not null)
type=innodb;
建立表2
mysql> create table busi_table(
-> busi_id char(13) not null primary key,
-> busi_name char(13) not null,
-> repo_id char(13) not null,
-> foreign key(repo_id) references repo_table(repo_id))
-> type=innodb;
2)插入數據
insert into repo_table values("12","sz"); //success
insert into repo_table values("13","cd"); //success
insert into busi_table values("1003","cd", "13"); //success
insert into busi_table values("1002","sz", "12"); //success
insert into busi_table values("1001","gx", "11"); //failed,提示:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (smb_man
.busi_table
, CONSTRAINT busi_table_ibfk_1
FOREIGN KEY (repo_id
) REFERENCES repo_table
(repo_id
))
3)增長級聯操做
mysql> alter table busi_table
-> add constraint id_check
-> foreign key(repo_id)
-> references repo_table(repo_id)
-> on delete cascade
-> on update cascade;
-----
ENGINE=InnoDB DEFAULT CHARSET=gb2312; //另外一種方法,能夠替換type=innodb;
三、相關操做
外鍵約束(表2)對父表(表1)的含義:
在父表上進行update/delete以更新或刪除在子表中有一條或多條對應匹配行的候選鍵時,父表的行爲取決於:在定義子表的外鍵時指定的on update/on delete子句。
關鍵字 | 含義 |
---|---|
CASCADE | 刪除包含與已刪除鍵值有參照關係的全部記錄 |
SET NULL | 修改包含與已刪除鍵值有參照關係的全部記錄,使用NULL值替換(只能用於已標記爲NOT NULL的字段) |
RESTRICT | 拒絕刪除要求,直到使用刪除鍵值的輔助表被手工刪除,而且沒有參照時(這是默認設置,也是最安全的設置) |
NO ACTION | 啥也不作 |
四、其餘
在外鍵上創建索引:
index repo_id (repo_id),
foreign key(repo_id) references repo_table(repo_id))
外鍵約束使用最多的兩種狀況無外乎:
1)父表更新時子表也更新,父表刪除時若是子表有匹配的項,刪除失敗;
2)父表更新時子表也更新,父表刪除時子表匹配的項也刪除。
前一種狀況,在外鍵定義中,咱們使用ON UPDATE CASCADE ON DELETE RESTRICT;後一種狀況,能夠使用ON UPDATE CASCADE ON DELETE CASCADE。
InnoDB容許你使用ALTER TABLE在一個已經存在的表上增長一個新的外鍵:
ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name, ...) REFERENCES tbl_name (index_col_name,...) [ON DELETE reference_option] [ON UPDATE reference_option]
InnoDB也支持使用ALTER TABLE來刪除外鍵:
ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;
爲何說外鍵能保持數據的一致性、完整性
你想一想,你的圖中的第一章表切割成了表1和表2,表2的學號引用了表1的學號字段做爲外鍵,假設不創建外鍵。僅僅是和表1同樣單純性 地設立一個學號字段。那麼和創建外鍵有什麼差異呢?
比方表1中張三的學號爲20140900001,那麼我在表2中插數據的時候在學號字段插20140900001來記錄張三的成績不也是作到了表 的解耦了嗎?
這裏存在的問題是。在不設置外鍵的狀況下。表2的學號字段和表1的學號字段是沒有關聯的。僅僅是你本身以爲他們有關係而已。數據庫並 不以爲它倆有關係。也就是說,你在表2的學號字段插了一個值(比方20140999999),但是這個值在表1中並無,這個時候,數據庫仍是允 許你插入的,它並不會對插入的數據作關係檢查。然而在設置外鍵的狀況下。你插入表2學號字段的值必須要求在表1的學號字段能找到。 同一時候。假設你要刪除表1的某個學號字段。必須保證表2中沒有引用該字段值的列,不然就無法刪除。
這就是所謂的保持數據的一致性和完整性。你想。如 果表2還引用表1的某個學號,你卻把表1中的這個學號刪了,表2就不知道這個學號相應的學生是哪一個學生。
數據的一致性還包含數據類型的一致性(這 個見如下就知道了)。
外鍵的使用規範
- 從表的字段必須與外鍵類型一樣(如上。分數表 stu 的類型必須和學生表 sid 的類型一樣,比方都是 int(10) 類型)
- 外鍵必須是主表的惟一鍵(如上。學生表 sid 是主鍵,而主鍵是惟一的。因此可以做爲分數表 stu 的外鍵)
- 有關聯的字段(如上,分數表之因此使用學生表的 sid 是因爲二者有關聯,分數表記錄的是學生的分數,而學生可以用 sid 來惟 一標識)
- 避免使用複合鍵(也就是說從表可以同一時候引用多個外表的字段做爲一個外鍵,通常不推薦這樣的作法)
# 做者(author):id,name,sex,age,mobile, detail_id # 做者詳情(author_detail): id,info,address # 一、外鍵的 字段名 能夠自定義(名字隨意),一般命名規範(關聯表_關聯字段) # 二、外鍵要經過 foreign key 語法創建表與表之間的關聯 # 三、foreign key(所在表的外鍵字段) references 關聯表(關聯字段) # eg:foreign key(detail_id) references author_detail(id) # 四、級聯關係 # 級聯更新 on update cascade # 級聯刪除 on delete cascade # 重點:外鍵字段自己能夠惟一或不惟一,可是外鍵關聯的字段必定惟一
多表關係
一對一關係
一對一關係是最好理解的一種關係,在數據庫建表的時候能夠將人表的主鍵放置與身份證表裏面,也能夠將身份證表的主鍵放置於人表裏面
一對多關係
班級是1端,學生是多端,結合面向對象的思想,1端是父親,多端是兒子,因此多端具備1端的屬性,也就是說多端裏面應該放置1端的主鍵,那麼學生表裏面應該放置班級表裏面的主鍵
多對多關係
對於多對多關係,須要轉換成1對多關係,那麼就須要一張中間表來轉換,這張中間表裏面須要存放學生表裏面的主鍵和課程表裏面的主鍵,此時學生與中間表示1對多關係,課程與中間表是1對多關係,學生與課程是多對多關係
''' 一對一:丈夫-妻子,用戶-身份證,做者-做者詳情 建表規則: 未存放外鍵的表被依賴,稱之爲左表;存放外鍵的表示依賴表,稱之爲右表;先操做左邊再操做右表 # 一對一:外鍵在任何一方均可以,此時外鍵要設置 惟一鍵 一對多:部門-員工,班級-學生,書-出版社 建表規則: 先創建主表,再創建從表,在從表中設置主表的惟一字段(一般爲主鍵)做爲外鍵,外鍵必須放在多的一方,此時外鍵值不惟一 多對多:老師-班級,課程-學生,出版社-做者 建表規則: 必定要建立第三張表(關係表),每個外鍵值不惟一,看能夠多個外鍵創建聯合惟一,必定要建立第三張表(關係表),每個外 鍵值不惟一,看能夠多個外鍵創建聯合惟一 '''
一對一:無級聯關係
# 做者詳情(author_detail): id,info,address create table author_detail( id int primary key auto_increment, info varchar(256), address varchar(256) ); # 做者表id,name,sex,age,mobile, detail_id create table author( id int primary key auto_increment, name varchar(64) not null, mobile char(11) unique not null, sex enum('男', '女') default '男', age int default 0, detail_id int unique not null, foreign key(detail_id) references author_detail(id) ); # 必須先建立被關聯表數據,有關聯表外鍵關聯的記錄後,關聯表才能夠建立數據 mysql>: insert into author_detail(info,address) values('Tom_info','Tom_address'); mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 1); mysql>: insert into author_detail(info,address) values('Bob_info','Bob_address'); mysql>: insert into author(name,mobile,detail_id) values('Bob','15666882233', 2); # 修改關聯表 author mysql>: insert into author_detail(info,address) values('Tom_info_sup','Tom_address_sup'); mysql>: update author set detail_id=3 where detail_id=2; # 有未被其餘數據關聯的數據,就能夠修改 # 刪除關聯表 author mysql>: delete from author where detail_id=3; # 直接刪除 # 修改被關聯表 author_detail mysql>: update author_detail set id=10 where id=1; # 沒法修改 # 刪除被關聯表 author_detail mysql>: delete from author_detail where id=1; # 沒法刪除 # 沒有級聯關係下: # 增長:先增長被關聯表記錄,再增長關聯表記錄 # 刪除:先刪除關聯表記錄,再刪除被關聯表記錄 # 更新:關聯與被關聯表都沒法完成 關聯的外鍵和主鍵 數據更新 - (若是被關聯表記錄沒有被綁定,能夠修改)
一對一:有級聯關係
mysql>: drop table author; mysql>: drop table author_detail; # 做者詳情(author_detail): id,info,address create table author_detail( id int primary key auto_increment, info varchar(256), address varchar(256) ); # 做者表id,name,sex,age,mobile, detail_id create table author( id int primary key auto_increment, name varchar(64) not null, mobile char(11) unique not null, sex enum('男', '女') default '男', age int default 0, detail_id int unique not null, foreign key(detail_id) references author_detail(id) on update cascade on delete cascade ); # 必須先建立被關聯表數據,有關聯表外鍵關聯的記錄後,關聯表才能夠建立數據 mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 1); # 錯誤 mysql>: insert into author_detail(info,address) values('Tom_info','Tom_address'); mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 1); mysql>: insert into author_detail(info,address) values('Bob_info','Bob_address'); mysql>: insert into author(name,mobile,detail_id) values('Bob','15666882233', 2); # 修改關聯表 author mysql>: update author set detail_id=3 where detail_id=2; # 失敗,3詳情不存在 mysql>: update author set detail_id=1 where detail_id=2; # 失敗,1詳情已被關聯 mysql>: insert into author_detail(info,address) values('Tom_info_sup','Tom_address_sup'); mysql>: update author set detail_id=3 where detail_id=2; # 有未被其餘數據關聯的數據,就能夠修改 # 刪除關聯表 author mysql>: delete from author where detail_id=3; # 直接刪除 # 修改被關聯表 author_detail mysql>: update author_detail set id=10 where id=1; # 級聯修改,同步關係關聯表外鍵 # 刪除被關聯表 author_detail mysql>: delete from author where detail_id=10; # 能夠刪除對被關聯表無影響 mysql>: insert into author(name,mobile,detail_id) values('Tom','13344556677', 10); mysql>: delete from author_detail where id=10; # 能夠刪除,將關聯表的記錄級聯刪除掉
一對多
# 一對多:外鍵必須放在多的一方,此時外鍵值不惟一 # 出版社(publish): id,name,address,phone create table publish( id int primary key auto_increment, name varchar(64), address varchar(256), phone char(20) ); # 書(book):id,name,price,publish_id, author_id create table book( id int primary key auto_increment, name varchar(64) not null, price decimal(5, 2) default 0, publish_id int, # 一對多的外鍵不能設置惟一 foreign key(publish_id) references publish(id) on update cascade on delete cascade ); # 增:先增長被關聯表(publish)的數據,再增長關聯表(book)的數據 mysql>: insert into publish(name, address, phone) values ('人民出版社', '北京', '010-110'), ('西交大出版社', '西安', '010-119'), ('老男孩出版社', '上海', '010-120'); mysql>: insert into book(name, price, publish_id) values ('西遊記', 6.66, 1), ('東遊記', 8.66, 1), ('python從入門到入土', 2.66, 2), ('輪程序員修養之道', 3.66, 3), ('好好活着', 88.88, 3); # 沒有被關聯的字段,插入依舊錯誤 mysql>: insert into book(name, price, publish_id) values ('打臉之道', 0.3, 4); # 失敗 # 更新:直接更新被關聯表的(publish) 主鍵,關聯表(book) 外鍵 會級聯更新 mysql>: update publish set id=10 where id=1; # 更新:直接更新關聯表的(book) 外鍵,修改的值對應被關聯表(publish) 主鍵 若是存在,能夠更新成功,反之失敗 mysql>: update book set publish_id=2 where id=4; # 成功 mysql>: update book set publish_id=1 where id=4; # 失敗 # 刪: # 刪被關聯表,關聯表會被級聯刪除 mysql>: delete from publish where id = 2; # 刪關聯表,被關聯表不會發生變化 mysql>: delete from book where publish_id = 3;
# 假設:書與做者也是 一對多 關係,一個做者能夠出版多本書 create table book( id int primary key auto_increment, name varchar(64) not null, price decimal(5, 2) default 0, publish_id int, # 一對多的外鍵不能設置惟一 foreign key(publish_id) references publish(id) on update cascade on delete cascade # 創建與做者 一對多 的外鍵關聯 author_id int, foreign key(author_id) references author(id) on update cascade on delete cascade );
多對多
# 多對多:必定要建立第三張表(關係表),每個外鍵值不惟一,看能夠多個外鍵創建聯合惟一 mysql>: drop table author; mysql>: drop table author_detail; mysql>: drop table book; mysql>: drop table publish; # 做者(author):id, name, age create table author( id int primary key auto_increment, name varchar(64), age int unsigned default 0 ); # 出版社(publish):id, name, address create table publish( id int primary key auto_increment, name varchar(64), address varchar(256) ); # 做者與出版社關係表:id, author_id, publish_id create table author_publish( id int primary key auto_increment, # 關係表必定有多個外鍵,關聯着多張表 # 關聯做者表 author_id int, foreign key(author_id) references author(id) on update cascade on delete cascade, # 關聯出版社表 publish_id int, foreign key(publish_id) references publish(id) on update cascade on delete cascade, # 創建兩個字段的聯合惟一 unique(author_id, publish_id) ); # 注:關係表 關聯着 做者 和 出版社 兩張表,在表結構上 做者 與 出版社 兩表鍵沒有任何關係 # 增:兩張被關聯表,沒有先後關係,但關係表必須在兩個表都提供數據後才能進行 關係匹配 mysql>: insert into author(name, age) values('ruakei', 67),('engo', 76),('Lxx', 3); mysql>: insert into publish(name, address) values('老男孩出版社', '上海'),('小女孩出版社', '北京'); # 操做關係表: mysql>: insert into author_publish(author_id, publish_id) values(1,1),(1,2),(2,1),(2,2),(3,1); # 關係表操做:增、刪、改,只要兩張被關係表有提供對應的操做數據,均可以操做成功,且對兩張被關係表沒有影響 # 操做兩張被關係表: # 增:不會影響關係表 mysql>: insert into publish(name, address) values('西交大出版社', '西安'); # 改:關係表都會級聯更新 mysql>: update publish set id=10 where id=1; # 刪:關係表都會級聯刪除 mysql>: delete from author where name='ruakei';
單表查詢
""" 增: insert [into] [數據庫名.]表名[(字段1[, ..., 字段n])] values (數據1[, ..., 數據n])[, ..., (數據1[, ..., 數據n])]; 刪: delete from [數據庫名.]表名 [條件]; 改: updata [數據庫名.]表名 set 字段1=值1[, ..., 字段n=值n] [條件]; 查: select [distinct] 字段1 [[as] 別名1],...,字段n [[as] 別名n] from [數據庫名.]表名 [條件]; """ # 條件:from、where、group by、having、distinct、order by、limit => 層層篩選後的結果 # 注:一條查詢語句,能夠擁有多種篩選條件,條件的順序必須按照上方順序進行逐步篩選,distinct稍有特殊(書寫位置),條件的種類能夠不全 # 能夠缺失,但不能亂序
去重:distinct
mysql>: create table t1( id int, x int, y int ); mysql>: insert into t1 values(1, 1, 1), (2, 1, 2), (3, 2, 2), (4, 2, 2); mysql>: select distinct * from t1; # 所有數據 mysql>: select distinct x, y from t1; # 結果 1,1 1,2 2,2 mysql>: select distinct y from t1; # 結果 1 2 # 總結:distinct對參與查詢的全部字段,總體去重(所查的所有字段的值都相同,才認爲是重複數據)
數據準備
CREATE TABLE `emp` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `gender` enum('男','女','未知') NULL DEFAULT '未知', `age` int(0) NULL DEFAULT 0, `salary` float NULL DEFAULT 0, `area` varchar(20) NULL DEFAULT '中國', `port` varchar(20) DEFAULT '未知', `dep` varchar(20), PRIMARY KEY (`id`) ); INSERT INTO `emp` VALUES (1, 'yangsir', '男', 42, 10.5, '上海', '浦東', '教職部'), (2, 'engo', '男', 38, 9.4, '山東', '濟南', '教學部'), (3, 'jerry', '女', 30, 3.0, '江蘇', '張家港', '教學部'), (4, 'tank', '女', 28, 2.4, '廣州', '廣東', '教學部'), (5, 'jiboy', '男', 28, 2.4, '江蘇', '蘇州', '教學部'), (6, 'zero', '男', 18, 8.8, '中國', '黃浦', '諮詢部'), (7, 'owen', '男', 18, 8.8, '安徽', '宣城', '教學部'), (8, 'jason', '男', 28, 9.8, '安徽', '巢湖', '教學部'), (9, 'ying', '女', 36, 1.2, '安徽', '蕪湖', '諮詢部'), (10, 'kevin', '男', 36, 5.8, '山東', '濟南', '教學部'), (11, 'monkey', '女', 28, 1.2, '山東', '青島', '教職部'), (12, 'san', '男', 30, 9.0, '上海', '浦東', '諮詢部'), (13, 'san1', '男', 30, 6.0, '上海', '浦東', '諮詢部'), (14, 'san2', '男', 30, 6.0, '上海', '浦西', '教學部'), (15, 'ruakei', '女', 67, 2.501, '上海', '陸家嘴', '教學部');
經常使用函數
""" 拼接:concat() | concat_ws() 大小寫:upper() | lower() 浮點型操做:ceil() | floor() | round() 整型:能夠直接運算 """ mysql>: select name,area,port from emp; mysql>: select name as 姓名, concat(area,'-',port) 地址 from emp; # 上海-浦東 mysql>: select name as 姓名, concat_ws('-',area,port,dep) 信息 from emp; # 上海-浦東-教職部 mysql>: select upper(name) 姓名大寫,lower(name) 姓名小寫 from emp; mysql>: select id,salary,ceil(salary)上薪資,floor(salary)下薪資,round(salary)入薪資 from emp; mysql>: select name 姓名, age 舊年齡, age+1 新年齡 from emp;
條件:where
# 多條件協調操做導入:where 奇數 [group by 部門 having 平均薪資] order by [平均]薪資 limit 1 mysql>: select * from emp where id<5 limit 1; # 正常 mysql>: select * from emp limit 1 where id<5; # 異常,條件亂序 # 判斷規則 """ 比較符合:> | < | >= | <= | = | != 區間符合:between 開始 and 結束 | in(自定義容器) 邏輯符合:and | or | not 類似符合:like _|% 正則符合:regexp 正則語法 """ mysql>: select * from emp where salary>5; mysql>: select * from emp where id%2=0; mysql>: select * from emp where salary between 6 and 9; mysql>: select * from emp where id in(1, 3, 7, 20); # _o 某o | __o 某某o | _o% 某o* (*是0~n個任意字符) | %o% *o* mysql>: select * from emp where name like '%o%'; mysql>: select * from emp where name like '_o%'; mysql>: select * from emp where name like '___o%'; # sql只支持部分正則語法 mysql>: select * from emp where name regexp '.*\d'; # 不支持\d表明數字,認爲\d就是普通字符串 mysql>: select * from emp where name regexp '.*[0-9]'; # 支持[]語法
分組與篩選:group by | having
where與having
# 表象:在沒有分組的狀況下,where與having結果相同 # 重點:having能夠對 聚合結果 進行篩選 mysql>: select * from emp where salary > 5; mysql>: select * from emp having salary > 5; mysql>: select * from emp where id in (5, 10, 15, 20); mysql>: select * from emp having id in (5, 10, 15, 20);
聚合函數
""" max():最大值 min():最小值 avg():平均值 sum():和 count():記數 group_concat():組內字段拼接,用來查看組內其餘字段 """
分組查詢 group by
# 修改my.ini配置重啓mysql服務 sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION # 在sql_mode沒有 ONLY_FULL_GROUP_BY 限制下,能夠執行,但結果沒有意義 # 有 ONLY_FULL_GROUP_BY 限制,報錯 mysql>: select * from emp group by dep; # 分組後,表中數據考慮範圍就不是 單條記錄,由於每一個分組都包含了多條記錄,參照分組字段,對每一個分組中的 多條記錄 統一處理 # eg: 按部門分組,每一個部門都有哪些人、最高的薪資、最低的薪資、平均薪資、組裏一共有多少人 # 將多條數據統一處理,這種方式就叫 聚合 # 每一個部門都有哪些人、最高的薪資、最低的薪資、平均薪資 都稱之爲 聚合結果 - 聚合函數操做的結果 # 注:參與分組的字段,也歸於 聚合結果 mysql>: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep; # 總結:分組後,查詢條件只能爲 分組字段 和 聚合函數操做的聚合結果
分組後的having
mysql>: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep; # 最低薪資小於2 mysql>: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep having min(salary)<2; # having能夠對 聚合結果 再進行篩選,where不能夠
排序
排序規則
# order by 主排序字段 [asc|desc], 次排序字段1 [asc|desc], ...次排序字段n [asc|desc]
未分組狀態下
mysql>: select * from emp; # 按年齡升序 mysql>: select * from emp order by age asc; # 按薪資降序 mysql>: select * from emp order by salary desc; # 按薪資降序,若是相同,再按年齡降序 mysql>: select * from emp order by salary desc, age desc; # 按齡降序,若是相同,再按薪資降序 mysql>: select * from emp order by age desc, salary desc;
分組狀態下
mysql>: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep; # 最高薪資降序 mysql: select dep 部門, group_concat(name) 成員, max(salary) 最高薪資, min(salary) 最低薪資, avg(salary) 平均薪資, sum(salary) 總薪資, count(gender) 人數 from emp group by dep order by 最高薪資 desc;
限制 limit
# 語法:limit 條數 | limit 偏移量,條數 mysql>: select name, salary from emp where salary<8 order by salary desc limit 1; mysql>: select * from emp limit 5,3; # 先偏移5條知足條件的記錄,再查詢3條
連表查詢
鏈接
# 鏈接:將有聯繫的多張表經過關聯(有聯繫就行,不必定是外鍵)字段,進行鏈接,形參一張大表 # 連表查詢:在大表的基礎上進行查詢,就稱之爲連表查詢 # 將表與表創建鏈接的方式有四種:內鏈接、左鏈接、右鏈接、全鏈接
一對多數據準備
mysql>: create database db3; mysql>: use db3; mysql>: create table dep( id int primary key auto_increment, name varchar(16), work varchar(16) ); create table emp( id int primary key auto_increment, name varchar(16), salary float, dep_id int ); insert into dep values(1, '市場部', '銷售'), (2, '教學部', '授課'), (3, '管理部', '開車'); insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1),('yingjie', 1.2, 0);
笛卡爾積
# 笛卡爾積: 集合 X{a, b} * Y{o, p, q} => Z{{a, o}, {a, p}, {a, q}, {b, o}, {b, p}, {b, q}} mysql>: select * from emp, dep; # 總結:是兩張表 記錄的全部排列組合,數據沒有利用價值
內鏈接
# 關鍵字:inner join on # 語法:from A表 inner join B表 on A表.關聯字段=B表.關聯字段 mysql>: select emp.id,emp.name,salary,dep.name,work from emp inner join dep on emp.dep_id = dep.id order by emp.id; # 總結:只保留兩個表有關聯的數據
左鏈接
# 關鍵字:left join on # 語法:from 左表 left join 右表 on 左表.關聯字段=右表.關聯字段 mysql>: select emp.id,emp.name,salary,dep.name,work from emp left join dep on emp.dep_id = dep.id order by emp.id; # 總結:保留左表的所有數據,右表有對應數據直接連表顯示,沒有對應關係空填充
右鏈接
# 關鍵字:right join on # 語法:from A表 right join B表 on A表.關聯字段=B表關聯字段 mysql>: select emp.id,emp.name,salary,dep.name,work from emp right join dep on emp.dep_id = dep.id order by emp.id; # 總結:保留右表的所有數據,左表有對應數據直接連表顯示,沒有對應關係空填充
左右能夠相互轉化
mysql>: select emp.id,emp.name,salary,dep.name,work from emp right join dep on emp.dep_id = dep.id order by emp.id; mysql>: select emp.id,emp.name,salary,dep.name,work from dep left join emp on emp.dep_id = dep.id order by emp.id; # 總結:更換一下左右表的位置,相對應更換左右鏈接關鍵字,結果相同
全鏈接
mysql>: select emp.id,emp.name,salary,dep.name,work from emp left join dep on emp.dep_id = dep.id union select emp.id,emp.name,salary,dep.name,work from emp right join dep on emp.dep_id = dep.id order by id; # 總結:左表右表數據都被保留,彼此有對應關係正常顯示,彼此沒有對應關係均空填充對方
一對一與一對多狀況一致
# 建立一對一 做者與做者詳情 表 create table author( id int, name varchar(64), detail_id int ); create table author_detail( id int, phone varchar(11) ); # 填充數據 insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0); insert into author_detail values(1, '13344556677'), (2, '14466779988'), (3, '12344332255'); # 內連 select author.id,name,phone from author join author_detail on author.detail_id = author_detail.id order by author.id; # 全連 select author.id,name,phone from author left join author_detail on author.detail_id = author_detail.id union select author.id,name,phone from author right join author_detail on author.detail_id = author_detail.id order by id;
多對多:兩表兩表創建鏈接
# 在一對一基礎上,創建 做者與書 的多對多關係關係 # 利用以前的做者表 create table author( id int, name varchar(64), detail_id int ); insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0); # 建立新的書表 create table book( id int, name varchar(64), price decimal(5,2) ); insert into book values(1, 'python', 3.66), (2, 'Linux', 2.66), (3, 'Go', 4.66); # 建立 做者與書 的關係表 create table author_book( id int, author_id int, book_id int ); # 數據:author-book:1-1,2 2-2,3 3-1,3 insert into author_book values(1,1,1),(2,1,2),(3,2,2),(4,2,3),(5,3,1),(6,3,3); # 將有關聯的表一一創建鏈接,查詢因此本身所需字段 select book.name, book.price, author.name, author_detail.phone from book join author_book on book.id = author_book.book_id join author on author_book.author_id = author.id left join author_detail on author.detail_id = author_detail.id;