一 : 主鍵
primary key
,主要的鍵. 一張表只能有一個字段可以使用對應的鍵, 用來唯一的約束該字段里面的數據, 不能重復: 這種稱之為主鍵.一張表只能有最多一個主鍵
操作
-
增加主鍵
(1) : 在創建表的時候,直接在字段之后,跟primary key 關鍵字(主鍵本身不允許為空)
優點
: 非常的直接
缺點
: 只能使用一個字段作作為主鍵
create table my_pri1(
name varchar(20) not null comment '姓名',
number char(10) primary key comment '學號: stu + 0000, 不能重復'
)charset utf8;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| number | char(10) | NO | PRI | NULL | |
+--------+-------------+------+-----+---------+-------+
(2) : 在創建表的時候,在所有字段之后,使用primary key(主鍵字段列表)來創建主鍵(如果有多個字段為主鍵,可以是復合主鍵)
-- 復合主鍵
create table my_pri2(
number char(10) comment '學號: stu + 0000',
course char(10) comment '課程代碼: 3901 + 0000',
score tinyint unsigned default 60 comment '成績',
-- 增加主鍵限制: 學號和課程號應該是個對應的,具有唯一性
primary key(number,course)
)charset utf8;
+--------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| number | char(10) | NO | PRI | NULL | |
| course | char(10) | NO | PRI | NULL | |
| score | tinyint(3) unsigned | YES | | 60 | |
+--------+---------------------+------+-----+---------+-------+
(3) : 當表已經創建好之后,額外追加主鍵,可以通過修改表字段屬性,也可以直接追加,Alter table
表名add primary key
(字段列表);
注意
: 表中字段對應的數據本身是獨立的(不重復)
create table my_pri3(
course char(10) not null comment '課程編號: 3901 + 0000',
name varchar(10) not null comment '課程名字'
);
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| course | char(10) | NO | | NULL | |
| name | varchar(10) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
alter table my_pri3 modify course char(10) primary key comment '課程編號: 3901 + 0000';
或者
alter table my_pri3 add primary key(course);(追加主鍵主要用這個)
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| course | char(10) | NO | PRI | NULL | |
| name | varchar(10) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
-
主鍵約束
主鍵對應的字段中的數據不允許重復,一旦重復,數據操作失敗(增/改)
mysql> select * from my_pri1;
+--------+-----------+
| name | number |
+--------+-----------+
| 雪芙 | class0001 |
| 思思 | class0002 |
+--------+-----------+
-- 主鍵沖突(重復)
insert into my_pri1 values('美美','class0002'); -- 不可以: 主鍵沖突
ERROR 1062 (23000): Duplicate entry 'class0002' for key 'PRIMARY'
-
更新與刪除主鍵
沒有辦法更新主鍵,主鍵必須先刪除再增加.
mysql> desc my_pri1;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| number | char(10) | NO | PRI | NULL | |
+--------+-------------+------+-----+---------+-------+
刪除主鍵
Alter table 表名 drop primary key
alter table my_pri3 drop primary key;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| number | char(10) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
二 : 主鍵分類
在實際創建表的過程中, 很少使用真實業務數據作為主鍵字段(業務主鍵,如學號,課程號); 大部分的時候是使用邏輯性的字段(字段沒有業務含義
,值是什么都沒有關系
), 將這種字段主鍵稱之為邏輯主鍵
Create table my_student(
Id int primary key auto_increment comment ‘邏輯主鍵: 自增長’,?-- 邏輯主鍵
Number char(10) not null comment ‘學號’,
Name varchar(10) not null
)
三 : 自動增長
自增長
: 當對應的字段,不給值,或者說給默認值,或者給NULL的時候, 會自動的被系統觸發, 系統會從當前字段中已有的最大值再進行+1操作,得到一個新的在不同的字段.
自增長通常是跟主鍵搭配
( 1 )新增自增長
auto_increment
① : 任何一個字段要做自增長必須前提是本身是一個索引(key一欄有值)
mysql> create table my_auto(
-> id int auto_increment comment '自動增長',
-> name varchar(10) not null
-> )charset utf8;
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
② : 自動增長字段必須是數字(整形)
mysql> create table my_auto(
-> id varchar(1) primary key auto_increment comment '自動增長',
-> name varchar(10) not null
-> )charset utf8;
ERROR 1063 (42000): Incorrect column specifier for column 'id'
③ : 一張表最多只能有一個自增長
-- 自增長
mysql> create table my_auto(
-> id int primary key auto_increment comment '自動增長',
-> name varchar(10) not null
-> )charset utf8;
Query OK, 0 rows affected (0.03 sec)
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
( 2 )自增長使用
當自增長被給定的值為NULL或者默認值的時候會觸發自動增長.
insert into my_auto(name) values('雪芙');
insert into my_auto values(null,'思思');
insert into my_auto values(default,'彩彩');
+----+--------+
| id | name |
+----+--------+
| 1 | 雪芙 |
| 2 | 思思 |
| 3 | 彩彩 |
+----+--------+
自增長如果對應的字段輸入了值,那么自增長失效,但是下一次還是能夠正確的自增長(從最大值+1)
insert into my_auto(name) values('雪芙');
insert into my_auto values(null,'思思');
insert into my_auto values(default,'彩彩');
+----+--------+
| id | name |
+----+--------+
| 1 | 雪芙 |
| 2 | 思思 |
| 3 | 彩彩 |
| 6 | 美美 |
| 7 | 想想 |
+----+--------+
如何確定下一次是什么自增長,可以通過查看表創建語句看到
mysql> show create table my_auto;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| my_auto | CREATE TABLE `my_auto` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自動增長',
`name` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
( 3 )修改自增長
自增長如果是涉及到字段改變,必須先刪除自增長,后增加(一張表只能有一個自增長)
修改當前自增長已經存在的值 : 修改只能比當前已有的自增長的最大值大,不能小(小了不生效)
Alter
table 表名 auto_increment = 值;
向下修改(小),但是不生效
alter table my_auto auto_increment = 4; -- 向下修改(小)
向上修改(大),生效
alter table my_auto auto_increment = 10; -- 向上修改
---------------------------------------------------------+
| my_auto | CREATE TABLE `my_auto` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自動增長',
`name` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
( 4 )修改自增長步長
為什么自增長是從1開始,為什么每次都是自增1呢.
所有系統的變現(如字符集,校對集)都是由系統內部的變量進行控制的.
查看自增長對應的變量 : show variables like 'auto_increment%';
-- 查看自增長變量
show variables like 'auto_increment%';
auto_increment_incremen
: 步長
auto_increment_offset
: 起始值
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
可以修改變量實現不同的效果,修改是對整個數據修改,而不是單張表;
set auto_increment_increment = 5; 一次自增5
set auto_increment_increment = 5;
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 5 |
| auto_increment_offset | 1 |
+--------------------------+-------+
+----+--------+
| id | name |
+----+--------+
| 1 | 雪芙 |
| 2 | 思思 |
| 3 | 彩彩 |
| 6 | 美美 |
| 7 | 想想 |
| 11 | 勁勁 |
| 16 | 辰辰 |
+----+--------+
( 5 )刪除自增長
自增長是字段的一個屬性,可以通過modify來進行修改(保證字段沒有auto_increment即可)
Alter table 表名 modify 字段類型;
錯誤 : 主鍵理論是單獨存在,有主鍵的時候,千萬不要再加主鍵
alter table my_auto modify id int primary key;
ERROR 1068 (42000): Multiple primary key defined
正確 :
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
alter table my_auto modify id int;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(10) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
四 : 唯一鍵
一張表往往有很多字段需要具有唯一性,數據不能重復: 但是一張表中只能有一個主鍵: 唯一鍵(unique key)就可以解決表中有多個字段需要唯一性約束的問題.
唯一鍵的本質與主鍵差不多: 唯一鍵默認的允許自動為空,而且可以多個為空(空字段不參與唯一性比較)
( 1 )增加唯一鍵
-
在創建表的時候,字段之后直接跟unique/unique key
create table my_unique1(
number char(10) unique comment '學號: 唯一,允許為空',
name varchar(20) not null
)charset utf8;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| number | char(10) | YES | UNI | NULL | |
| name | varchar(20) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
-
在所有的字段之后增加unique key (字段列表); 復合唯一鍵
create table my_unique2(
number char(10) not null comment '學號',
name varchar(20) not null,
-- 增加唯一鍵
unique key(number)
)charset utf8;
之所以會顯示PRI : 剛好是一個不為空的唯一鍵(主鍵性質一樣) : 原因是因為該表沒有主鍵
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| number | char(10) | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
+--------+-------------+------+-----+---------+-------+
-
在創建表之后增加為一鍵
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| number | char(10) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
-- 追加唯一鍵
alter table my_unique3 add unique key(number);
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| number | char(10) | NO | UNI | NULL | |
| name | varchar(20) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
( 2 )唯一鍵約束
唯一鍵與主鍵本質相同 : 唯一的區別就是唯一鍵默認允許為空,而且多個為空.
insert into my_unique1 values(null,'美美'),('class0001','彩彩'),(null,'娜娜');
+-----------+--------+
| number | name |
+-----------+--------+
| NULL | 美美 |
| class0001 | 彩彩 |
| NULL | 娜娜 |
+-----------+--------+
添加重復元素報錯
insert into my_unique1 values('class0001','思思');
ERROR 1062 (23000): Duplicate entry 'class0001' for key 'number'
注
: 如果唯一鍵也不允許為空那么唯一鍵與主鍵的約束作用是一致的.
( 3 )更新/刪除唯一鍵
更新唯一鍵 : 先刪除后增(唯一鍵可以有多個 : 可以不刪除)
刪除唯一鍵
Alter table 表名 drop unique key; -- 錯誤: 唯一鍵有多個
Alter table 表名 drop index 索引名字; -- 唯一鍵默認的使用字段名作為索引名字
alter table my_unique3 drop index number;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| number | char(10) | NO | | NULL | |
| name | varchar(20) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
五 : 索引
幾乎所有的索引都是建立在字段之上.
索引
: 系統根據某種算法,將已有的數據(未來可能新增的數據)單獨建立一個文件,文件能夠實現快速匹配數據,并且能夠快速的找到對應表中的記錄.
索引的意義
1.提升查詢數據的效率
2.約束數據的有效性( 唯一性等)
增加索引的前提條件: 索引本身會產生索引文件(有時候有可能比數據文件還大) ,會非常耗費磁盤空間.
如果某個字段需要作為查詢的條件經常使用, 那么可以使用索引(一定會想辦法增加);
如果某個字段需要進行數據的有效性約束, 也可能使用索引(主鍵,唯一鍵)
Mysql中提供了多種索引
- 主鍵索引: primary key
- 唯一索引: unique key
- 全文索引: fulltext index
- 普通索引: index
全文索引: 針對文章內部的關鍵字進行索引
全文索引最大的問題: 在于如何確定關鍵字
英文很容易: 英文單詞與單詞之間有空格
中文很難: 沒有空格, 而且中文可以各種隨意組合(分詞: sphinx)
六 : 范式
Normal Format
: 是一種離散數學中的知識, 是為了解決一種數據的存儲與優化的問題: 保存數據的存儲之后, 凡是能夠通過關系尋找出來的數據,堅決不再重復存儲: 終極目標是為了減少數據的冗余.
范式
: 是一種分層結構的規范, 分為六層: 每一次層都比上一層更加嚴格: 若要滿足下一層范式,前提是滿足上一層范式.
六層范式
: 1NF,2NF,3NF...6NF, 1NF是最底層,要求最低;6NF最高層,最嚴格.
Mysql屬于關系型數據庫: 有空間浪費: 也是致力于節省存儲空間: 與范式所有解決的問題不謀而合: 在設計數據庫的時候, 會利用到范式來指導設計.
但是數據庫不單是要解決空間問題,要保證效率問題: 范式只為解決空間問題, 所以數據庫的設計又不可能完全按照范式的要求實現: 一般情況下,只有前三種范式需要滿足.
范式在數據庫的設計當中是有指導意義: 但是不是強制規范.
( 1 ) 1NF
第一范式
: 在設計表存儲數據的時候, 如果表中設計的字段存儲的數據,在取出來使用之前還需要額外的處理(拆分),那么說表的設計不滿足第一范式: 第一范式要求字段的數據具有原子性: 不可再分.
講師代課表
上表設計不存在問題,但是如果需求是將數據查出來之后,要求顯示一個老師從什么時候開始上課,到什么時候節課: 需要將代課時間進行拆分: 不符合1NF, 數據不具有原子性, 可以再拆分.
解決方案 : 將代課時間拆分成兩個字段就解決問題
( 2 )2NF
第二范式
: 在數據表設計的過程中,如果有復合主鍵(多字段主鍵), 且表中有字段并不是由整個主鍵來確定, 而是依賴主鍵中的某個字段(主鍵的部分): 存在字段依賴主鍵的部分的問題, 稱之為部分依賴: 第二范式就是要解決表設計不允許出現部分依賴.
講師帶課表
以上表中: 因為講師沒有辦法作為獨立主鍵, 需要結合班級才能作為主鍵(復合主鍵: 一個老師在一個班永遠只帶一個階段的課): 代課時間,開始和結束字段都與當前的代課主鍵(講師和班級): 但是性別并不依賴班級, 教室不依賴講師: 性別只依賴講師, 教室只依賴班級: 出現了性別和教室依賴主鍵中的一部分: 部分依賴.不符合第二范式.
解決 :
解決方案1: 可以將性別與講師單獨成表, 班級與教室也單獨成表.
解決方案2: 取消復合主鍵, 使用邏輯主鍵
( 3 )3NF
要滿足第三范式,必須滿足第二范式.
第三范式: 理論上講,應該一張表中的所有字段都應該直接依賴主鍵(邏輯主鍵: 代表的是業務主鍵), 如果表設計中存在一個字段, 并不直接依賴主鍵,而是通過某個非主鍵字段依賴,最終實現依賴主鍵: 把這種不是直接依賴主鍵,而是依賴非主鍵字段的依賴關系稱之為傳遞依賴. 第三范式就是要解決傳遞依賴的問題.
講師帶課表
以上設計方案中: 性別依賴講師存在, 講師依賴主鍵; 教室依賴班級,班級依賴主鍵: 性別和教室都存在傳遞依賴.
解決方案 :
將存在傳遞依賴的字段,以及依賴的字段本身單獨取出,形成一個單獨的表, 然后在需要對應的信息的時候, 使用對應的實體表的主鍵加進來.
講師代課表
講師表
班級表
從表面來看講師表
與班級表
也會有傳遞依賴,但是邏輯主鍵只是業務主鍵的一個替代,永遠不要看邏輯主鍵,要看真正所代表的主鍵
所以 講師表:
ID = 講師?, 班級表
中: ID = 班級
( 4 )逆規范化
有時候, 在設計表的時候,如果一張表中有幾個字段是需要從另外的表中去獲取信息. 理論上講, 的確可以獲取到想要的數據, 但是就是效率低一點. 會刻意的在某些表中,不去保存另外表的主鍵(邏輯主鍵), 而是直接保存想要的數據信息: 這樣一來,在查詢數據的時候, 一張表可以直接提供數據, 而不需要多表查詢(效率低), 但是會導致數據冗余增加.
講師代課信息表
逆規規范化
: 磁盤利用率與效率的對抗
七 : 數據高級操作
( 1 )主鍵沖突
在數據插入的時候, 假設主鍵對應的值已經存在: 插入一定會失敗!
當主鍵存在沖突的時候(Duplicate key),可以選擇性的進行處理: 更新和替換
+---------+------+
| name | room |
+---------+------+
| PHP0810 | B203 |
| PHP0710 | B203 |
+---------+------+
插入重復數據
insert into my_class values('PHP0810','B205');
ERROR 1062 (23000): Duplicate entry 'PHP0810' for key 'PRIMARY'
解決主鍵沖突 :
-- 主鍵沖突: 更新
insert into my_class values('PHP0810','B205')
-- 沖突處理
on duplicate key update
-- 更新教室
room = 'B205';
+---------+------+
| name | room |
+---------+------+
| PHP0710 | B203 |
| PHP0810 | B205 |
( 2 )主鍵沖突 : 替換
Replace into 表名 [(字段列表:包含主鍵)] values(值列表);
replace into my_class values('PHP0710','A203');
+---------+------+
| name | room |
+---------+------+
| PHP0710 | A203 |
| PHP0810 | B205 |
+---------+------+
( 3 )蠕蟲復制
從已有的數據中去獲取數據,然后將數據又進行新增操作: 數據成倍的增加.
表創建高級操作: 從已有表創建新表(復制表結構)
Create table 表名 like 數據庫.表名;
+--------+--------+
| name | money |
+--------+--------+
| 思思 | 123.23 |
| 美美 | 234.55 |
mysql> create table my_copy like my_teacher;
Query OK, 0 rows affected (0.04 sec)
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| name | varchar(20) | NO | | NULL | |
| money | decimal(10,2) | NO | | NULL | |
+-------+---------------+------+-----+---------+-------+
蠕蟲復制: 先查出數據, 然后將查出的數據新增一遍
Insert into 表名[(字段列表)] select 字段列表/* from 數據表名;
mysql> insert into my_copy select * from my_copy;
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into my_copy select * from my_copy;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into my_copy select * from my_copy;
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0
+--------+--------+
| name | money |
+--------+--------+
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
+--------+--------+
蠕蟲復制的意義
- 從已有表拷貝數據到新表中
- 可以迅速的讓表中的數據膨脹到一定的數量級: 測試表的壓力以及效率
( 4 )更新數據
Update 表名 set 字段 = 值 [where條件];
高級新增語法
Update 表名 set 字段 = 值 [where條件] [limit 更新數量];
mysql> update my_copy set name = '可可' where name = '美美' limit 3;
Query OK, 3 rows affected (0.00 sec)
+--------+--------+
| name | money |
+--------+--------+
| 思思 | 123.23 |
| 可可 | 234.55 |
| 思思 | 123.23 |
| 可可 | 234.55 |
| 思思 | 123.23 |
| 可可 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
+--------+--------+
( 5 )刪除數據
與更新類似: 可以通過limit來限制數量
Delete from 表名 [where條件] [limit 數量];
mysql> delete from my_copy where name = '思思' limit 5;
Query OK, 5 rows affected (0.00 sec)
+--------+--------+
| name | money |
+--------+--------+
| 可可 | 234.55 |
| 可可 | 234.55 |
| 可可 | 234.55 |
| 美美 | 234.55 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
| 思思 | 123.23 |
| 美美 | 234.55 |
+--------+--------+
刪除
: 如果表中存在主鍵自增長,那么當刪除之后, 自增長不會還原
數據的刪除是不會改變表結構, 只能刪除表后重建表
Truncate 表名;?-- 先刪除改變,后新增改變
+----+--------+
| id | name |
+----+--------+
| 1 | 雪芙 |
| 2 | 思思 |
| 3 | 彩彩 |
| 6 | 美美 |
| 7 | 想想 |
| 11 | 勁勁 |
| 16 | 辰辰 |
+----+--------+
-- 清空表: 重置自增長
truncate my_auto;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| my_auto | CREATE TABLE `my_auto` (
`id` int(11) NOT NULL,
`name` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
( 6 )查詢數據
基本語法
Select 字段列表/* from 表名 [where條件];
完整語法
Select [select選項] 字段列表[字段別名]/* from 數據源 [where條件子句] [group by子句] [having子句] [order by子句] [limit 子句];
Select選項: select對查出來的結果的處理方式
All: 默認的,保留所有的結果
Distinct: 去重, 查出來的結果,將重復給去除(所有字段都相同)
select distinct * from my_auto;
字段別名
字段別名: 當數據進行查詢出來的時候, 有時候名字并一定就滿足需求(多表查詢的時候, 會有同名字段). 需要對字段名進行重命名: 別名
語法
字段名 [as] 別名;
數據源
數據源: 數據的來源, 關系型數據庫的來源都是數據表: 本質上只要保證數據類似二維表,最終都可以作為數據源.
數據源分為多種: 單表數據源, 多表數據源, 查詢語句
單表數據源: select * from 表名;
多表數據源: select* from 表名1,表名2...;
從一張表中取出一條記錄,去另外一張表中匹配所有記錄,而且全部保留:(記錄數和字段數),將這種結果成為: 笛卡爾積(交叉連接): 笛卡爾積沒什么卵用, 所以應該盡量避免.子查詢: 數據的來源是一條查詢語句(查詢語句的結果是二維表)
Select * from (select 語句) as 表名;
( 7 )Where子句
Where子句: 用來判斷數據,篩選數據.
Where子句返回結果: 0或者1, 0代表false,1代表true.
判斷條件:
比較運算符:>
,<
, >=
,<=
,!=
,<>
,=
, like
, between
and
,in/not in
邏輯運算符: &&(and), ||(or), !(not)
Where原理:
where是唯一一個直接從磁盤獲取數據的時候就開始判斷的條件: 從磁盤取出一條記錄, 開始進行where判斷: 判斷的結果如果成立保存到內存;如果失敗直接放棄.
( 8 )Group by子句
Group by:分組的意思, 根據某個字段進行分組(相同的放一組,不同的分到不同的組)
+----+-----------+--------+------+--------+
| id | number | name | sex | height |
+----+-----------+--------+------+--------+
| 1 | class0001 | 思思 | 男 | 184 |
| 2 | class0002 | 可可 | 男 | 182 |
| 3 | class0003 | 娜娜 | 女 | 156 |
| 4 | class0004 | 美美 | 男 | 172 |
| 5 | class0005 | 彩彩 | 男 | 166 |
+----+-----------+--------+------+--------+
基本語法 : gruop by 字段名;
select * from my_student group by sex;
分組的意思: 是為了統計數據(按組統計: 按分組字段進行數據統計)
SQL提供了一系列統計函數
- Count(): 統計分組后的記錄數: 每一組有多少記錄
- Max():?統計每組中最大的值
- Min(): 統計最小值
- Avg(): 統計平均值
- Sum(): 統計和
mysql> select sex,count(*),max(height),min(height) from my_student group by sex;
+------+----------+-------------+-------------+
| sex | count(*) | max(height) | min(height) |
+------+----------+-------------+-------------+
| 女 | 1 | 156 | 156 |
| 男 | 4 | 184 | 166 |
+------+----------+-------------+-------------+
Count函數: 里面可以使用兩種參數: *代表統計記錄,字段名代表統計對應的字段(NULL不統計)
Group by 字段 [asc|desc];?-- 對分組的結果然后合并之后的整個結果進行排序
按照男,女 校對集順序
多字段分組 : 先根據一個字段進行分組,然后對分組后的結果再次按照其他字段進行分組
alter table my_student add c_id int;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> update my_student set c_id = ceil(random()*3);
+----+-----------+--------+------+--------+------+
| id | number | name | sex | height | c_id |
+----+-----------+--------+------+--------+------+
| 1 | class0001 | 思思 | 男 | 184 | 3 |
| 2 | class0002 | 可可 | 男 | 182 | 1 |
| 3 | class0003 | 娜娜 | 女 | 156 | 1 |
| 4 | class0004 | 美美 | 男 | 172 | 3 |
| 5 | class0005 | 彩彩 | 男 | 166 | 3 |
+----+-----------+--------+------+--------+------+
多字段分組,先按班級份,再按性別分
mysql> select c_id,sex,count(*),group_concat(name) from my_student group by c_id,sex; -- 多字段排序
group_concat
: 可以對分組的結果中的某個字段進行字符串連接(保留該組所有的某個字段):
+------+------+----------+----------------------+
| c_id | sex | count(*) | group_concat(name) |
+------+------+----------+----------------------+
| 1 | 女 | 1 | 娜娜 |
| 1 | 男 | 1 | 可可 |
| 3 | 男 | 3 | 思思,美美,彩彩 |
+------+------+----------+----------------------+
回溯統計 : with rollup
: 任何一個分組后都會有一個小組, 最后都需要向上級分組進行匯報統計: 根據當前分組的字段. 這就是回溯統計: 回溯統計的時候會將分組字段置空.
select c_id,count(*) from my_student group by c_id with rollup;
+------+----------+
| c_id | count(*) |
+------+----------+
| 1 | 2 |
| 3 | 3 |
| NULL | 5 |
+------+----------+
多字段回溯 : 考慮第一層分組會有此回溯: 第二次分組要看第一次分組的組數, 組數是多少,回溯就是多少,然后加上第一層回溯即可.
+------+------+----------+------------------------------------+
| c_id | sex | count(*) | group_concat(name) |
+------+------+----------+------------------------------------+
| 1 | 女 | 1 | 娜娜 |
| 1 | 男 | 1 | 可可 |
| 1 | NULL | 2 | 娜娜,可可 |
| 3 | 男 | 3 | 思思,美美,彩彩 |
| 3 | NULL | 3 | 思思,美美,彩彩 |
| NULL | NULL | 5 | 娜娜,可可,思思,美美,彩彩 |
+------+------+----------+------------------------------------+
( 9 )Having子句
Having子句: 與where子句一樣: 進行條件判斷的.
Where是針對磁盤數據進行判斷: 進入到內存之后,會進行分組操作: 分組結果就需要having來處理.
Having能做where能做的幾乎所有事情, 但是where卻不能做having能做的很多事情.
① : 分組統計的結果或者說統計函數都只有having能夠使用.
select c_id,count(*) from my_student group by c_id having count(*) >= 2;
+------+----------+
| c_id | count(*) |
+------+----------+
| 1 | 2 |
| 3 | 3 |
+------+----------+
② Having能夠使用字段別名: where不能: where是從磁盤取數據,而名字只可能是字段名: 別名是在字段進入到內存后才會產生.
select c_id,count(*) as total from my_student group by c_id having total >= 2;
+------+-------+
| c_id | total |
+------+-------+
| 1 | 2 |
| 3 | 3 |
+------+-------+
報錯
select c_id,count(*) as total from my_student where total >= 2 group by c_id ;
ERROR 1054 (42S22): Unknown column 'total' in 'where clause'
( 10 )Order by 子句
Order by: 排序, 根據某個字段進行升序或者降序排序, 依賴校對集.
Order by 字段名 [asc|desc]; -- asc是升序(默認的),desc是降序
select * from my_student order by c_id;
+----+-----------+--------+------+--------+------+
| id | number | name | sex | height | c_id |
+----+-----------+--------+------+--------+------+
| 2 | class0002 | 可可 | 男 | 182 | 1 |
| 3 | class0003 | 娜娜 | 女 | 156 | 1 |
| 1 | class0001 | 思思 | 男 | 184 | 3 |
| 4 | class0004 | 美美 | 男 | 172 | 3 |
| 5 | class0005 | 彩彩 | 男 | 166 | 3 |
+----+-----------+--------+------+--------+------+
排序可以進行多字段排序: 先根據某個字段進行排序, 然后排序好的內部,再按照某個數據進行再次排序:
-- 多字段排序: 先班級排序,后性別排序
select * from my_student order by c_id, sex desc;
+----+-----------+--------+------+--------+------+
| id | number | name | sex | height | c_id |
+----+-----------+--------+------+--------+------+
| 2 | class0002 | 可可 | 男 | 182 | 1 |
| 3 | class0003 | 娜娜 | 女 | 156 | 1 |
| 1 | class0001 | 思思 | 男 | 184 | 3 |
| 4 | class0004 | 美美 | 男 | 172 | 3 |
| 5 | class0005 | 彩彩 | 男 | 166 | 3 |
+----+-----------+--------+------+--------+------+
( 11 )Limit子句
Limit
子句是一種限制結果的語句: 限制數量.
Limi
t有兩種使用方式
- 只用來限制長度(數據量): limit 數據量
select * from my_student limit 2;
+----+-----------+--------+------+--------+------+
| id | number | name | sex | height | c_id |
+----+-----------+--------+------+--------+------+
| 1 | class0001 | 思思 | 男 | 184 | 3 |
| 2 | class0002 | 可可 | 男 | 182 | 1 |
+----+-----------+--------+------+--------+------+
- 限制起始位置,限制數量: limit 起始位置,長度
select * from my_student limit 0,2; -- 記錄數是從0開始編號
+----+-----------+--------+------+--------+------+
| id | number | name | sex | height | c_id |
+----+-----------+--------+------+--------+------+
| 1 | class0001 | 思思 | 男 | 184 | 3 |
| 2 | class0002 | 可可 | 男 | 182 | 1 |
+----+-----------+--------+------+--------+------+
Limit主要用來實現數據的分頁: 為用戶節省時間,提交服務器的響應效率, 減少資源的浪費.
對于用戶來講
: 可以點擊的分頁按鈕: 1,2,3,4
對于服務器來講
: 根據用戶選擇的頁碼來獲取不同的數據: limit offset,length;
Length
: 每頁顯示的數據量: 基本不變
Offset
: offset = (頁碼 - 1) * 每頁顯示量