typora-copy-images-to: 效果圖
思考:MySQL數(shù)據(jù)庫的基本存儲(chǔ)單元是表中的字段,MySQL數(shù)據(jù)庫需要高效、安全的維護(hù)數(shù)據(jù)请契,并且保證數(shù)據(jù)的有效性,是如何實(shí)現(xiàn)的呢夏醉?
引入:作為數(shù)據(jù)想要保證操作效率爽锥,就需要事先知道如何管理;想要保證有效性畔柔,就需要讓數(shù)據(jù)能夠有一些規(guī)范氯夷。在MySQL中,通過字段類型和字段屬性來完成這兩個(gè)目的
- 字段類型:限定數(shù)據(jù)的規(guī)范格式
- 字段屬性:在字段類型基礎(chǔ)上更細(xì)致規(guī)范數(shù)據(jù)
總結(jié):MySQL中字段擁有字段類型和字段屬性靶擦,類型是大致規(guī)范數(shù)據(jù)格式腮考,保證數(shù)據(jù)的管理和操作效率;字段屬性在類型之上再進(jìn)行細(xì)分規(guī)范玄捕,從而保證數(shù)據(jù)的有效性踩蔚。
一官卡、MySQL數(shù)據(jù)庫字段類型
思考:MySQL數(shù)據(jù)庫作為一種高效率存儲(chǔ)和管理數(shù)據(jù)的工具隙姿,是如何保證數(shù)據(jù)的管理效率的呢?
引入:數(shù)據(jù)的管理效率最好的一種手段就是讓數(shù)據(jù)變得精確熙参,而讓數(shù)據(jù)變精確的方式就是給數(shù)據(jù)一種明確的格式赌结,從而在進(jìn)行數(shù)據(jù)的存取時(shí)捞蛋,可以按照設(shè)定的格式來進(jìn)行快速操作。因此柬姚,MySQL對(duì)于數(shù)據(jù)表中的字段進(jìn)行了類型規(guī)范拟杉。
1.MySQL字段(列)類型【掌握】
定義:MySQL字段類型是MySQL為了更加有效的數(shù)據(jù)管理而對(duì)表中字段的數(shù)據(jù)本身進(jìn)行了類型限定,是在創(chuàng)建表的時(shí)候量承,就進(jìn)行了相應(yīng)的字段規(guī)范搬设。
- MySQL中根據(jù)業(yè)務(wù)的需求穴店,將數(shù)據(jù)類型分成了四大類:
- 整數(shù)類型:存儲(chǔ)整數(shù)數(shù)據(jù)
- 小數(shù)類型:存儲(chǔ)浮點(diǎn)型數(shù)據(jù)
- 時(shí)間日期型:存儲(chǔ)時(shí)間日期型數(shù)據(jù)
- 字符串型:存儲(chǔ)字符數(shù)據(jù)
總結(jié)
- MySQL為了提升數(shù)據(jù)存取效率,規(guī)定了數(shù)據(jù)表中的字段必須指定數(shù)據(jù)類型
- 字段類型一旦確定拿穴,就只能存儲(chǔ)相應(yīng)類型的數(shù)據(jù)
思考:在PHP中整型就是一個(gè)使用8個(gè)字節(jié)存儲(chǔ)的具體數(shù)字泣洞,MySQL中是否一樣呢?
引入:MySQL是用來持續(xù)(長期)存儲(chǔ)數(shù)據(jù)的默色,意味著數(shù)據(jù)一旦規(guī)定格式就要分配指定長度的磁盤空間來存儲(chǔ)數(shù)據(jù)球凰,這些磁盤空間不能用來做其他任何存儲(chǔ)。這就意味著數(shù)據(jù)即使不需要那么多空間來存儲(chǔ)腿宰,也需要對(duì)應(yīng)的開銷呕诉。為了提升磁盤空間利用率,MySQL根據(jù)業(yè)務(wù)需求對(duì)整型進(jìn)行了再次細(xì)分吃度。
2. 整數(shù)類型【掌握】
定義:整數(shù)類型甩挫,就是使用整型規(guī)范的字段里,只能存儲(chǔ)相應(yīng)的整數(shù)數(shù)據(jù)椿每。MySQL為了提升磁盤利用率伊者,根據(jù)具體業(yè)務(wù)需求對(duì)整型進(jìn)行了5類細(xì)分:迷你整型(tinyint),短整型(smallint)间护,中整型(mediumint)亦渗,標(biāo)準(zhǔn)整型(int)和大整型(bigint)
- 迷你整型:tinyint,只用一個(gè)字節(jié)存儲(chǔ)汁尺,存儲(chǔ)范圍是-128~127
mysql> create table my_tinyint(
-> id tinyint
-> )charset utf8;
Query OK, 0 rows affected (0.83 sec)
- 短整型:smallint央碟,用2個(gè)字節(jié)存儲(chǔ)
mysql> create table my_smallint(
-> id smallint
-> )charset utf8;
Query OK, 0 rows affected (0.40 sec)
- 中整型:mediumint,使用3個(gè)字節(jié)存儲(chǔ)
mysql> create table my_mediumint(
-> id mediumint
-> )charset utf8;
Query OK, 0 rows affected (0.35 sec)
- 標(biāo)準(zhǔn)整型:int均函,使用4個(gè)字節(jié)存儲(chǔ)
mysql> create table my_int(
-> id int
-> )charset utf8;
Query OK, 0 rows affected (0.66 sec)
- 大整型:bigint亿虽,使用8個(gè)字節(jié)存儲(chǔ)
mysql> create table my_bigint(
-> id bigint
-> )charset utf8;
Query OK, 0 rows affected (0.32 sec)
- MySQL中默認(rèn)都是有符號(hào)類型,即支持負(fù)數(shù)苞也,如果某些數(shù)據(jù)不需要負(fù)數(shù)洛勉,那么可以使用unsignd標(biāo)志無符號(hào)類型
mysql> create table my_unsigned(
-> id1 tinyint,
-> id2 tinyint unsigned #明確當(dāng)前雖然也是迷你整型,但是屬于無符號(hào)
-> )charset utf8;
Query OK, 0 rows affected (0.70 sec)
總結(jié)
- MySQL中為了保證磁盤空間的有效利用如迟,給整型提供了5中類型
- MySQL中數(shù)值默認(rèn)是有符號(hào)類型收毫,如果想要使用無符號(hào)類型應(yīng)該使用unsigned關(guān)鍵字修飾
- 具體業(yè)務(wù)可以根據(jù)具體需求預(yù)判需要的數(shù)據(jù)類型,在保證空間能夠完全滿足數(shù)據(jù)的情況下殷勘,最大化的節(jié)省磁盤空間
思考:MySQL中所有的整型在類型顯示的時(shí)候此再,都在括號(hào)后有一個(gè)數(shù)字,這個(gè)數(shù)字到底代表什么含義呢玲销?
引入:在MySQL中输拇,數(shù)值后的括號(hào)內(nèi)數(shù)組代表數(shù)字的顯示寬度,即表示數(shù)字最長能夠顯示多少個(gè)寬度贤斜。
3. 顯示寬度【了解】
定義:顯示寬度策吠,即對(duì)應(yīng)整型數(shù)據(jù)類型在表中最多能夠顯示的寬度逛裤,通常顯示的最大數(shù)所占領(lǐng)的寬度。
- MySQL中顯示寬度是根據(jù)整型所能表示的最大值的數(shù)字個(gè)數(shù)以及是否有符號(hào)
mysql> desc my_unsigned;
+-------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| id1 | tinyint(4) | YES | | NULL | | #4個(gè)寬度是因?yàn)?127
| id2 | tinyint(3) unsigned | YES | | NULL | | #3個(gè)寬度是因?yàn)?~255
+-------+---------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
- 數(shù)字的顯示寬度可以在實(shí)際創(chuàng)建表的時(shí)候來根據(jù)需求設(shè)定
mysql> create table my_wide(
-> id1 tinyint,
-> id2 tinyint(2)
-> )charset utf8;
Query OK, 0 rows affected (0.65 sec)
- 顯示寬度不會(huì)改變數(shù)據(jù)類型所能表示的大泻锬ā:即數(shù)據(jù)長度超過顯示寬度带族,數(shù)據(jù)依然有效
mysql> desc my_wide;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id1 | tinyint(4) | YES | | NULL | |
| id2 | tinyint(2) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.05 sec)
mysql> insert into my_wide values(-128,-128);
Query OK, 1 row affected (0.48 sec)
- 顯示寬度的目的不是用來限定數(shù)據(jù),而是用來配合==zerofill==實(shí)現(xiàn)數(shù)據(jù)不足寬度時(shí)用前導(dǎo)0補(bǔ)充至指定寬度:filed 字段類型(顯示寬度) zerofill;
mysql> create table my_wide1(
-> id1 tinyint(2) zerofill,
-> id2 tinyint(2) unsigned zerofill
-> )charset utf8;
Query OK, 0 rows affected (0.69 sec)
注意:zerofill要求數(shù)據(jù)必須為unsigned蟀给,如果不是默認(rèn)也會(huì)自動(dòng)轉(zhuǎn)變成unsigned
mysql> desc my_wide1;
+-------+------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------------------+------+-----+---------+-------+
| id1 | tinyint(2) unsigned zerofill | YES | | NULL | |
| id2 | tinyint(2) unsigned zerofill | YES | | NULL | |
+-------+------------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
在有zerofill前導(dǎo)0屬性后蝙砌,數(shù)據(jù)不足顯示寬度的時(shí)候會(huì)自動(dòng)進(jìn)行前導(dǎo)0補(bǔ)充
mysql> insert into my_wide1 values(127,1);
Query OK, 1 row affected (0.44 sec)
mysql> select * from my_wide1;
+------+------+
| id1 | id2 |
+------+------+
| 127 | 01 |
+------+------+
1 row in set (0.04 sec)
總結(jié)
- 數(shù)值類型(整型)Type欄里括號(hào)內(nèi)部的數(shù)字表示顯示寬度
- 顯示寬度默認(rèn)表示的是數(shù)據(jù)類型能表示的最大值對(duì)應(yīng)的寬度
- 可以通過設(shè)定實(shí)現(xiàn)顯示寬度的設(shè)定
- 設(shè)置的顯示寬度不會(huì)影響對(duì)應(yīng)類型本身表示的數(shù)值大小
- 設(shè)置寬度通常是配合zerofill來實(shí)現(xiàn)前導(dǎo)0補(bǔ)充
- 除非數(shù)據(jù)本身要增加前導(dǎo)0,一般不會(huì)刻意去修改和使用顯示寬度
思考:并非所有的業(yè)務(wù)對(duì)應(yīng)的都是整型數(shù)據(jù)跋理,如果碰到小數(shù)點(diǎn)的時(shí)候該如何存儲(chǔ)呢拍霜?
引入:小數(shù)在數(shù)據(jù)庫中是非常常見的一種數(shù)據(jù),MySQL中對(duì)這類數(shù)據(jù)規(guī)定為小數(shù)類型薪介。
4. 小數(shù)類型【掌握】
定義:小數(shù)類型,即數(shù)據(jù)最終的表示是帶有小數(shù)點(diǎn)方式越驻,而小數(shù)部分在數(shù)據(jù)庫中涉及到精確性的問題汁政,MySQL為了保證數(shù)據(jù)的精確性,將小數(shù)類型有拆分為浮點(diǎn)型和定點(diǎn)型小數(shù)缀旁。
- 浮點(diǎn)型:即一種不能確保精確度的小數(shù)類型记劈,在MySQL中有float和double兩種
- float:單精度類型,使用4個(gè)字節(jié)存儲(chǔ)數(shù)據(jù)并巍,有效精度7~8位
- double:雙精度類型目木,使用8個(gè)字節(jié)存儲(chǔ)數(shù)據(jù),能夠存儲(chǔ)的數(shù)據(jù)比float更大懊渡,有效精度為15~16位
mysql> create table my_float(
-> f1 float,
-> f2 double
-> )charset utf8;
Query OK, 0 rows affected (0.70 sec)
- 浮點(diǎn)型數(shù)據(jù)會(huì)雖然能表示很大的數(shù)據(jù)刽射,但是有丟失精度的可能:超過精度部分進(jìn)行四舍五入
mysql> insert into my_float values(9999999999,9999999999);
Query OK, 1 row affected (0.42 sec)
mysql> select * from my_float;
+-------------+------------+
| f1 | f2 |
+-------------+------------+
| 10000000000 | 9999999999 |
+-------------+------------+
1 row in set (0.04 sec)
- 浮點(diǎn)型可以指定整數(shù)部分和小數(shù)部分的位數(shù):float/double(總長度,小數(shù)部分長度);
mysql> create table my_float1(
-> f1 float(10,2),
-> f2 float(10,4)
-> )charset utf8;
Query OK, 0 rows affected (0.35 sec)
- 這個(gè)時(shí)候數(shù)據(jù)就不能超過指定的數(shù)據(jù)的大小:小數(shù)部分超過指定范圍會(huì)進(jìn)行四舍五入(精度范圍內(nèi))剃执,而整數(shù)部分長度則不允許超過
mysql> insert into my_float1 values(999999.9999,888888.8888),(99.9999,88.88888);
Query OK, 2 rows affected (0.06 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from my_float1;
+------------+-------------+
| f1 | f2 |
+------------+-------------+
| 1000000.00 | 888888.8750 | #超過精度范圍誓禁,精度外出現(xiàn)無效數(shù)據(jù)
| 100.00 | 88.8889 | #有效精度內(nèi),四舍五入
+------------+-------------+
2 rows in set (0.00 sec)
- 如果整數(shù)部分超出指定長度肾档,則會(huì)報(bào)錯(cuò)
mysql> desc my_float1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| f1 | float(10,2) | YES | | NULL | |
| f2 | float(10,4) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into my_float1 values(99999999.99,99999999.9999);
ERROR 1264 (22003): Out of range value for column 'f2' at row 1
# 錯(cuò)誤:給定的值超過了f2所能表示的范圍
注意:如果是因?yàn)檫M(jìn)位超過整數(shù)部分長度摹恰,系統(tǒng)默認(rèn)允許
mysql> desc my_float1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| f1 | float(10,2) | YES | | NULL | |
| f2 | float(10,4) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into my_float1 values(99999999.99,999999.9999);
Query OK, 1 row affected (0.52 sec)
mysql> select * from my_float1;
+--------------+--------------+
| f1 | f2 |
+--------------+--------------+
| 1000000.00 | 888888.8750 |
| 100.00 | 88.8889 |
| 100000000.00 | 1000000.0000 |
+--------------+--------------+
3 rows in set (0.00 sec)
- 定點(diǎn)型:decimal,是一種可以確保精確不丟失的小時(shí)類型怒见,本質(zhì)是因?yàn)閐ecimal不是使用固定字節(jié)存儲(chǔ)俗慈,而是根據(jù)數(shù)據(jù)的大小來自適應(yīng)字節(jié)長度。大致是每9個(gè)數(shù)字使用4個(gè)字節(jié)存儲(chǔ)遣耍。
mysql> create table my_decimal(
-> d1 decimal, #默認(rèn)整數(shù)長度10位闺阱,小數(shù)部分0位
-> d2 decimal(10,2) #整數(shù)長度8,小數(shù)部分2位
-> )charset utf8;
Query OK, 0 rows affected (0.68 sec)
- 定點(diǎn)型數(shù)據(jù)不會(huì)丟失精度(小數(shù)部分超過會(huì)自動(dòng)截取舵变,截取方式是四舍五入)馏颂,整數(shù)部分超過長度都會(huì)操作失敗
mysql> desc my_decimal;
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| d1 | decimal(10,0) | YES | | NULL | |
| d2 | decimal(10,2) | YES | | NULL | |
+-------+---------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into my_decimal values(99999999,99999999.98999); #小數(shù)部分超長
Query OK, 1 row affected, 1 warning (0.07 sec) #依然執(zhí)行成功
mysql> show warnings;
+-------+------+-----------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------+
| Note | 1265 | Data truncated for column 'd2' at row 1 | #數(shù)據(jù)超過范圍
+-------+------+-----------------------------------------+
1 row in set (0.00 sec)
注意:定點(diǎn)型即便是因?yàn)檫M(jìn)位導(dǎo)致整數(shù)部分超過指定長度示血,也不允許數(shù)據(jù)插入
mysql> insert into my_decimal values(99999999,99999999.99999); #進(jìn)位導(dǎo)致整數(shù)部分達(dá)到9位
ERROR 1264 (22003): Out of range value for column 'd2' at row 1
總結(jié)
- MySQL中對(duì)應(yīng)小數(shù)提供了兩種存儲(chǔ)方式:浮點(diǎn)型和定點(diǎn)型
- 浮點(diǎn)型適合存儲(chǔ)數(shù)據(jù)較大但是不要求精度的數(shù)據(jù),定點(diǎn)型存儲(chǔ)需要保證精度的數(shù)據(jù)
- 一般大型數(shù)據(jù)使用浮點(diǎn)型救拉,具體小數(shù)使用定點(diǎn)型
思考:平常在開發(fā)時(shí)經(jīng)常需要記錄用戶的操作時(shí)間信息难审,那么這類信息在數(shù)據(jù)庫中是怎么存儲(chǔ)的呢?
引入:時(shí)間日期數(shù)據(jù)也算是開發(fā)中非常常用的一類數(shù)據(jù)亿絮,因此MySQL中也專門提供了時(shí)間日期類型來幫助數(shù)據(jù)存儲(chǔ)告喊。并且根據(jù)實(shí)際業(yè)務(wù)需求,也將時(shí)間日期細(xì)分了好幾類派昧。
5.時(shí)間日期類型【了解】
定義:時(shí)間日期類型是MySQL為了方便用戶時(shí)間日期而設(shè)定的類型黔姜,MySQL將時(shí)間日期類型細(xì)分成了5種類型:時(shí)間日期(datetime),日期(date)蒂萎,時(shí)間(time)秆吵,時(shí)間戳(timestamp),年(year)
- 年year:使用1個(gè)字節(jié)來存儲(chǔ)年份五慈,可以使用year和year(4)來實(shí)現(xiàn)纳寂,表示的范圍是1901~2155
mysql> create table my_year(
-> y1 year,
-> y2 year(4)
-> )charset utf8;
Query OK, 0 rows affected (0.71 sec)
year只能表示1901到2155年,而且MySQL的year支持兩種方式插入數(shù)據(jù):2位年和4位年
mysql> insert into my_year values(1916,2020),(69,70);
Query OK, 2 rows affected (0.14 sec)
Records: 2 Duplicates: 0 Warnings: 0
注意:MySQL中year字段類型使用2位數(shù)字插入時(shí)泻拦,在69以前是追加2000毙芜,70以后是追加1900
- 時(shí)間戳timestamp:從格林威治時(shí)間開始的時(shí)間
mysql> create table my_timestamp(
-> t timestamp
-> )charset utf8;
Query OK, 0 rows affected (0.75 sec)
不同于PHP中時(shí)間戳是秒數(shù),MySQL中的timestamp是YYYY-MM-DD HH:II:SS年月日時(shí)分秒格式争拐,數(shù)據(jù)插入可以使用YYYY-MM-DD HH:II:SS 或者 YYYYMMDDHHIISS方式
mysql> insert into my_timestamp values('2022-12-12 12:12:12'),('20231212121212');
Query OK, 2 rows affected (0.08 sec)
Records: 2 Duplicates: 0 Warnings: 0
注意:MySQL中timestamp字段是有默認(rèn)當(dāng)前時(shí)間的腋粥,而且只要所在記錄被修改,那么該字段就會(huì)自動(dòng)更新(可以用作記錄記錄最后更新時(shí)間)
- 時(shí)間段time:表示一個(gè)時(shí)間點(diǎn)或者一個(gè)時(shí)間段
mysql> create table my_time(
-> t1 time,
-> t2 time
-> )charset utf8;
Query OK, 0 rows affected (0.39 sec)
MySQL中的time類型數(shù)據(jù)架曹,可以直接插入時(shí)間格式(HH:II:SS)也可以是非時(shí)間格式(日期 HH:II:SS/HHH:II:SS)隘冲,且還可以使用負(fù)號(hào)“-”(HHH表示的范圍是-850到850)
mysql> insert into my_time values('12:12:12','123:12:12'),('4 12:12:12','-3 12:12:12');
Query OK, 2 rows affected (0.45 sec)
Records: 2 Duplicates: 0 Warnings: 0
- 日期date:具體日期,格式為YYYY-MM-DD绑雄,表示范圍為1000-01-01到9999-12-31
mysql> create table my_date(
-> d1 date
-> )charset utf8;
Query OK, 0 rows affected (0.54 sec)
- 時(shí)間日期datetime:表示具體日期時(shí)間对嚼,表示范圍為1000-01-01 00:00:00到9999-12-31 23:59:59
mysql> create table my_datatime(
-> dt datetime
-> )charset utf8;
Query OK, 0 rows affected (0.68 sec)
總結(jié)
- MySQL中時(shí)間日期類型分為5類:year年,時(shí)間time绳慎,日期date纵竖,時(shí)間戳timestamp和時(shí)間日期datetime
- 時(shí)間日期類型的設(shè)定是符合當(dāng)時(shí)年代SQL編程需求的
- 隨著服務(wù)器端語言地位上升,以及服務(wù)器端語言對(duì)于時(shí)間日期的靈活處理杏愤,MySQL的時(shí)間日期類型使用量大為減少靡砌,取而代之的是使用真正的時(shí)間戳整型秒數(shù)
思考:每一種類型在MySQL中都會(huì)因?yàn)閿?shù)據(jù)顆粒度或者業(yè)務(wù)情形而被拆分,作為最常見的數(shù)據(jù)字符串珊楼,MySQL又是如何存儲(chǔ)的呢通殃?
引入:作為最常見的一種數(shù)據(jù)類型,MySQL對(duì)字符串同樣進(jìn)行了多維度拆分。拆分的邏輯就是字符串格式画舌、字符串長短和字符串長度是否固定堕担。
6.字符串類型【掌握】
定義:字符串類型是MySQL為了存儲(chǔ)不同類型的字符串,并且考慮到存儲(chǔ)空間利用率以及數(shù)據(jù)訪問效率而進(jìn)行分拆管理的類型曲聂。MySQL字符串類型分為五種:定長字符串(char)霹购,變長字符串(varchar),文本字符串(text/blob)朋腋,枚舉字符串(enum)和集合字符串(set)
- 定長字符串char:語法char(L)齐疙,即事先確認(rèn)數(shù)據(jù)的存儲(chǔ)長度L字符數(shù),然后存儲(chǔ)的實(shí)際數(shù)據(jù)不能超過指定長度旭咽,L字符數(shù)不超過255
mysql> create table my_char(
-> id char(18)
-> )charset utf8;
Query OK, 0 rows affected (0.40 sec)
定長字符串應(yīng)用場景是確定某項(xiàng)數(shù)據(jù)的長度都是某個(gè)固定字符數(shù)贞奋,如身份證號(hào)碼
mysql> insert into my_char values('51031019001010101X');
Query OK, 1 row affected (0.29 sec)
- 變長字符串varchar:語法varchar(L),即實(shí)現(xiàn)確認(rèn)數(shù)據(jù)可能出現(xiàn)的最大長度L字符數(shù)穷绵,存儲(chǔ)的實(shí)際數(shù)據(jù)不能超過指定長度轿塔,L字符數(shù)理論值為65535
mysql> create table my_varchar(
-> name varchar(5)
-> )charset utf8;
Query OK, 0 rows affected (0.46 sec)
變長字符串應(yīng)用場景是某個(gè)數(shù)據(jù)長度可變,但是有最長區(qū)間字符數(shù)
mysql> insert into my_varchar values('迪麗熱巴');
Query OK, 1 row affected (0.09 sec)
mysql> insert into my_varchar values('張三');
Query OK, 1 row affected (0.13 sec)
- char與varchar對(duì)比
- char和varchar都是指定長度存儲(chǔ)字符串?dāng)?shù)據(jù)
- char存儲(chǔ)是數(shù)據(jù)長度差不多的字段仲墨,varchar是數(shù)據(jù)長度有差距的字段
- char占據(jù)的實(shí)際存儲(chǔ)空間是由L和字符集共同確定勾缭,即L * 字符集對(duì)應(yīng)字節(jié)數(shù)(數(shù)據(jù)不夠的時(shí)候會(huì)使用空格填充,有空間浪費(fèi))宗收;varchar是根據(jù)實(shí)際存儲(chǔ)的數(shù)據(jù)計(jì)算存儲(chǔ)空間,即實(shí)際存儲(chǔ)字符 * 字符集對(duì)應(yīng)字節(jié)數(shù)
- varchar因?yàn)楦鶕?jù)數(shù)據(jù)長度來確定實(shí)際占用空間亚兄,因此需要一個(gè)額外的空間存儲(chǔ)數(shù)據(jù)長度混稽,規(guī)則是256個(gè)字符以內(nèi)需要1個(gè)字節(jié),超過256需要2個(gè)字節(jié)
- 理論上來講审胚,雖然char可以存儲(chǔ)255個(gè)字符匈勋,varchar可以達(dá)到65535個(gè)字符,但是實(shí)際上固定長度數(shù)據(jù)并不多見膳叨,因此varchar的使用比char要常見的多
注意:varchar的理論長度是65535個(gè)字符洽洁,但是因?yàn)镸ySQL規(guī)定記錄長度(所有字段占用的空間)不能超過65535個(gè)字節(jié),因而且varchar還需要額外1~2個(gè)字節(jié)存儲(chǔ)數(shù)據(jù)長度菲嘴,所以永遠(yuǎn)達(dá)不到理論值饿自。另外,字符還涉及到字符集問題龄坪,如GBK占用2個(gè)字節(jié)存儲(chǔ)一個(gè)漢字昭雌,UTF-8占用3個(gè)字節(jié)存儲(chǔ)一個(gè)漢字,所以對(duì)應(yīng)的實(shí)際存儲(chǔ)長度也會(huì)相應(yīng)的縮短(GBK不能超過32767健田,UTF-8不能超過21845)烛卧。
- 文本字符串text/blob:語法text/blob,是指存儲(chǔ)較大的數(shù)據(jù)(通常是超過varchar的范圍)妓局,其中text表示字符文本总放,而blob表示二進(jìn)制文本呈宇。text和blob都有四種方式存儲(chǔ),而且都是自適應(yīng)(不需要判定長度去選擇哪種)
- TINYTEXT 可變長度局雄,最多 255 個(gè)字符
- TEXT 可變長度甥啄,最多 65535 個(gè)字符
- MEDIUMTEXT 可變長度,最多 16777215(2^24 - 1)個(gè)字符
- LONGTEXT 可變長度哎榴,最多 4294967295(2^32 - 1)(4G)個(gè)字符
- TINYBLOB可變長度型豁,最多255個(gè)字節(jié)
- BLOB可變長度,最多65535個(gè)字節(jié)
- MEDIUMTEXT可變長度尚蝌,最多 16777215(2^24 - 1)個(gè)字節(jié)
- LONGBLOB可變長度迎变,最多 4294967295(2^32 - 1)(4G)個(gè)字節(jié)
mysql> create table my_text(
-> t1 text, #通常指定text即可
-> b1 blob
-> )charset utf8;
Query OK, 0 rows affected (0.75 sec)
注意:text本身的數(shù)據(jù)不占用記錄長度,所以能夠存儲(chǔ)較大數(shù)據(jù)
- varchar飘言、text和blob對(duì)比
- 三者都是變長存儲(chǔ)數(shù)據(jù)
- varchar和text是存儲(chǔ)字符衣形,而blob存儲(chǔ)的是字節(jié)
- varchar存儲(chǔ)收MySQL記錄長度限制(達(dá)不到理論值),text和blob不受限制
- varchar需要事先指定長度且數(shù)據(jù)不能超過長度姿鸿,text和blob會(huì)自動(dòng)根據(jù)數(shù)據(jù)調(diào)整長度
- 枚舉enum:語法enum(數(shù)據(jù)1,數(shù)據(jù)2...數(shù)據(jù)N)谆吴,使用1~2個(gè)字節(jié)存儲(chǔ),最多可以在enum中設(shè)定65535個(gè)數(shù)據(jù)苛预,是一種提前規(guī)范可能出現(xiàn)的數(shù)據(jù)的字符串句狼。允許設(shè)計(jì)人員將字段可能出現(xiàn)的數(shù)據(jù)羅列出來,然后在數(shù)據(jù)錄入時(shí)只能選擇列表數(shù)據(jù)中的某一個(gè)具體數(shù)據(jù)
mysql> create table my_enum(
-> gender enum('男','女','保密')
-> )charset utf8;
Query OK, 0 rows affected (0.68 sec)
枚舉字段類似于單選框热某,設(shè)定的值在實(shí)際的選擇時(shí)只能選擇其中任意一個(gè)
mysql> insert into my_enum values('女');
Query OK, 1 row affected (0.43 sec)
注意:枚舉是使用12個(gè)字節(jié)存儲(chǔ)數(shù)據(jù)腻菇,但是實(shí)際上可以看出數(shù)據(jù)本身是字符串,那么12個(gè)字節(jié)根本不夠存儲(chǔ)昔馋。enum的存儲(chǔ)原理是建立枚舉數(shù)據(jù)與數(shù)值之間的映射表
枚舉數(shù)據(jù) | 映射值 |
---|---|
數(shù)據(jù)1 | 1 |
數(shù)據(jù)2 | 2 |
... | ... |
數(shù)據(jù)N | N(小于65535) |
所以筹吐,在實(shí)際存儲(chǔ)的時(shí)候,字段中本質(zhì)存儲(chǔ)的是映射值數(shù)字秘遏,這也就能解釋為什么能夠利用2個(gè)字節(jié)達(dá)到65535個(gè)數(shù)據(jù)列表了丘薛。可以使用select 枚舉字段 + 0 from 枚舉字段表邦危;來檢驗(yàn)字段是否是數(shù)值(+運(yùn)算會(huì)自動(dòng)類型轉(zhuǎn)換)
mysql> select gender,gender + 0 from my_enum;
+--------+------------+
| gender | gender + 0 |
+--------+------------+
| 女 | 2 |
+--------+------------+
1 row in set (0.44 sec)
正是因?yàn)閑num存儲(chǔ)的本身是實(shí)際是數(shù)值映射洋侨,因此在進(jìn)行數(shù)據(jù)插入的時(shí)候,可以直接使用對(duì)應(yīng)的映射關(guān)系的數(shù)值來進(jìn)行數(shù)據(jù)插入
mysql> insert into my_enum values(3);
Query OK, 1 row affected (0.08 sec)
- 集合set:語法set(數(shù)據(jù)1,數(shù)據(jù)2...數(shù)據(jù)N)倦蚪,使用1~8個(gè)字節(jié)存儲(chǔ)凰兑,最多可以在set中設(shè)置64個(gè)數(shù)據(jù),也是一種提前規(guī)范可能出現(xiàn)的數(shù)據(jù)的字符串审丘。允許設(shè)計(jì)人員將字段可能出現(xiàn)的數(shù)據(jù)羅列出來吏够,然后在數(shù)據(jù)錄入時(shí)可以選擇列表數(shù)據(jù)中的某一個(gè)或者多個(gè)具體數(shù)據(jù)
mysql> create table my_set(
-> ball_hobby set('籃球','足球','羽毛球','乒乓球','保齡球','桌球','橄欖球','網(wǎng)球')
-> )charset utf8;
Query OK, 0 rows affected (0.34 sec)
枚舉字段類似于多選框,設(shè)定的值在實(shí)際選擇的時(shí)候可以任選多個(gè):使用一個(gè)字符串,中間用逗號(hào)分隔
mysql> insert into my_set values('籃球,桌球,網(wǎng)球');
Query OK, 1 row affected (0.08 sec)
注意:集合set是使用1~8個(gè)字節(jié)存儲(chǔ)數(shù)據(jù)锅知,具體使用空間是系統(tǒng)自動(dòng)通過計(jì)算set中元素的個(gè)數(shù)來設(shè)定播急,每滿8個(gè)元素使用一個(gè)位存儲(chǔ)。set中數(shù)據(jù)與字節(jié)的映射關(guān)系是:具體位上的數(shù)據(jù)對(duì)應(yīng)一個(gè)字節(jié)中的比特位
集合數(shù)據(jù) | 映射位 |
---|---|
籃球 | 00000001 |
足球 | 00000010 |
... | ... |
網(wǎng)球 | 10000000 |
所以售睹,在實(shí)際存儲(chǔ)的時(shí)候桩警,字段中存儲(chǔ)的本質(zhì)是選中的數(shù)據(jù)組成對(duì)應(yīng)的字節(jié)數(shù)值轉(zhuǎn)換的十進(jìn)制數(shù)值。如上述存儲(chǔ)選中的是籃球昌妹、桌球和網(wǎng)球捶枢,分別對(duì)應(yīng)的是一個(gè)字節(jié)中的第1位、6位和8位飞崖,那么被選中位為1烂叔,未被選中位為0,結(jié)果為:10000101固歪,然后倒置過來10100001蒜鸡,再轉(zhuǎn)換成十進(jìn)制為:1 * 2 ^ 7 + 1 * 2 ^ 5 + 1 * 2 ^ 0 = 128 + 32 + 1 = 161
mysql> select ball_hobby,ball_hobby + 0 from my_set;
+----------------+----------------+
| ball_hobby | ball_hobby + 0 |
+----------------+----------------+
| 籃球,桌球,網(wǎng)球 | 161 |
+----------------+----------------+
1 row in set (0.00 sec)
同樣的,因?yàn)榧蠈?shí)際存儲(chǔ)的是數(shù)值牢裳,那么在進(jìn)行數(shù)據(jù)插入的時(shí)候逢防,也可以使用數(shù)值進(jìn)行代替
mysql> insert into my_set values(255); #表示一個(gè)字節(jié)全選
Query OK, 1 row affected (0.42 sec)
總結(jié):
- MySQL在字符串存儲(chǔ)的時(shí)候提供了多種選擇:char,varchar蒲讯,text/blob忘朝,enum和set
- char比較浪費(fèi)空間,但是查詢效率最快
- varchar比text/blob效率高判帮,能用varchar的地方不用text局嘁,但是要考慮varchar的實(shí)際范圍
- 二進(jìn)制數(shù)據(jù)存儲(chǔ)必須使用blob(通常涉及blob的是文件信息,而文件信息實(shí)際開發(fā)中更多使用varchar保存文件名字和路徑脊另,而文件存儲(chǔ)到某個(gè)文件夾中)
- 數(shù)據(jù)列表可以使用enum和set實(shí)現(xiàn)导狡,enum代表單選框约巷,set代表多選框
- enum和set本身可以規(guī)范數(shù)據(jù)偎痛,保證字段不會(huì)出現(xiàn)規(guī)定數(shù)據(jù)以外的其他數(shù)據(jù)
- enum和set創(chuàng)建過程中會(huì)建立映射關(guān)系,因此字段實(shí)際存儲(chǔ)使用映射數(shù)值
- enum和set對(duì)應(yīng)的字段可以用數(shù)值進(jìn)行數(shù)據(jù)插入(強(qiáng)烈不建議)
二独郎、MySQL字段屬性
思考:字段類型規(guī)范了表中字段對(duì)應(yīng)的數(shù)據(jù)的基本格式踩麦,但是有些數(shù)據(jù)還有一些特殊的性質(zhì),如不能為空之類的氓癌,這塊MySQL能不能實(shí)現(xiàn)呢谓谦?
引入:MySQL為了方便用戶進(jìn)行數(shù)據(jù)管理規(guī)范,在除了使用字段類型進(jìn)行數(shù)據(jù)限定以外贪婉,還額外增加了一些屬性來讓數(shù)據(jù)變得更加規(guī)范和安全反粥。
1.MySQL字段屬性【掌握】
定義:MySQL字段屬性,即在字段類型限定的基礎(chǔ)之上,使用一些額外的屬性命令對(duì)數(shù)據(jù)加以限定才顿,確保數(shù)據(jù)的有效性和安全性
- 在MySQL中莫湘,給字段增加了額外的幾種屬性
- NULL/NOT NULL:數(shù)據(jù)為空或者不能為空
- default:默認(rèn)值設(shè)定
- primary key:主鍵唯一性(索引)
- auto_increment:自動(dòng)增長
- unique key:數(shù)據(jù)唯一性(索引)
- comment:字段描述
總結(jié):所有的字段類型都是主動(dòng)或者被動(dòng)的帶有一些字段屬性的,在實(shí)際開發(fā)中需要了解每一種屬性的特點(diǎn)郑气,從而能夠根據(jù)需求來選擇性的設(shè)定某些屬性的值幅垮。
思考:在PHP中我們知道,數(shù)據(jù)很多時(shí)候是不允許用戶直接設(shè)置空Null的尾组,因?yàn)檫@樣的數(shù)據(jù)對(duì)于系統(tǒng)而言沒有任何意義忙芒,那MySQL中知否也需要考慮這樣的數(shù)據(jù)呢?
引入:MySQL作為數(shù)據(jù)庫是專門負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和管理的讳侨,數(shù)據(jù)對(duì)于企業(yè)而言是非常重要的呵萨,尤其是在大數(shù)據(jù)分析和數(shù)據(jù)挖掘時(shí)代,因此MySQL中對(duì)重要數(shù)據(jù)通常都需要進(jìn)行非空設(shè)定爷耀。
2.NULL/NOT NULL屬性【掌握】
定義:NULL/NOT NULL甘桑,即對(duì)數(shù)據(jù)進(jìn)行空或者非空設(shè)定,默認(rèn)字段是允許為空的歹叮,但是如果數(shù)據(jù)都為空跑杭,那么這樣的數(shù)據(jù)就沒什么價(jià)值,因此大部分的時(shí)候需要使用NOT NULL來進(jìn)行數(shù)據(jù)限定
- 允許為空:默認(rèn)情況下咆耿,不對(duì)字段類型進(jìn)行任何屬性控制的話德谅,基本都是允許為空的
mysql> create table my_null1(
-> id int,
-> name varchar(10),
-> price decimal(8,2),
-> deal_date date
-> )charset utf8;
Query OK, 0 rows affected (0.70 sec)
mysql> desc my_null1;
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(10) | YES | | NULL | |
| price | decimal(8,2) | YES | | NULL | |
| deal_date | date | YES | | NULL | |
+-----------+--------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
- 不允許為空:絕大部分情況下,數(shù)據(jù)為空沒有意義萨螺,因此我們?cè)谶M(jìn)行字段設(shè)置的時(shí)候窄做,都需要通過not Null來限定數(shù)據(jù)不能為空
mysql> create table my_null2(
-> id int not null,
-> name varchar(10) not null,
-> price decimal(8,2) not null,
-> deal_date date not null
-> )charset utf8;
Query OK, 0 rows affected (0.28 sec)
- NOT NULL不允許為空的字段在進(jìn)行數(shù)據(jù)插入的時(shí)候,就不能插入NULL數(shù)據(jù)慰技,或者在進(jìn)行數(shù)據(jù)插入時(shí)跳過相關(guān)字段(不考慮設(shè)定默認(rèn)值的情況)
mysql> insert into my_null1 values(null,null,null,null); #my_null1表允許所有字段為空
Query OK, 1 row affected (0.09 sec)
mysql> insert into my_null2 values(null,null,null,null); #my_null2表所有字段都不允許為空
ERROR 1048 (23000): Column 'id' cannot be null #錯(cuò)誤:提示id字段不能為空
總結(jié):因?yàn)閿?shù)據(jù)為空NULL就意味著數(shù)據(jù)沒有價(jià)值椭盏,因此在實(shí)際開發(fā)中,通常都會(huì)指定字段屬性not null來保證數(shù)據(jù)的有效性和價(jià)值
思考:當(dāng)用戶需要提交很多數(shù)據(jù)的時(shí)候吻商,有些不重要的數(shù)據(jù)用戶可以選擇性不填掏颊,這些數(shù)據(jù)通常不夠重要或者價(jià)值不大,那么這種情況下艾帐,我們?cè)诮M織SQL指令插入數(shù)據(jù)的時(shí)候乌叶,還是要對(duì)所有字段進(jìn)行補(bǔ)充操作嗎?
引入:當(dāng)某些數(shù)據(jù)如果不是特別重要柒爸,或者可以歸類為某些常用的信息的時(shí)候准浴,MySQL提供了一種方式可以讓開發(fā)者在不操作的情況下也會(huì)有數(shù)據(jù),那就是默認(rèn)值捎稚。
3.Default屬性【掌握】
定義:default默認(rèn)值乐横,就是當(dāng)用戶在進(jìn)行數(shù)據(jù)操作的時(shí)候求橄,可以通過強(qiáng)制或者不操作某個(gè)字段,而某個(gè)字段依然可以按照設(shè)定的規(guī)則那樣得到相應(yīng)的數(shù)據(jù)葡公。
- 每個(gè)字段本身都有默認(rèn)值谈撒,在不指定的情況下默認(rèn)值通常都是NULL
mysql> desc my_null2;
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | varchar(10) | NO | | NULL | |
| price | decimal(8,2) | NO | | NULL | |
| deal_date | date | NO | | NULL | |
+-----------+--------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
#雖然該表設(shè)定所有字段都不能為空,但是其默認(rèn)值Default依然是NULL
- 默認(rèn)值的設(shè)定就是在某個(gè)可能出現(xiàn)某個(gè)固定數(shù)據(jù)的字段后使用default 默認(rèn)值 來實(shí)現(xiàn)
mysql> create table my_default(
-> id int not null,
-> gender enum('男','女','保密') default '保密'
-> )charset utf8;
Query OK, 0 rows affected (0.68 sec)
- 一旦設(shè)定了默認(rèn)值之后匾南,那么該字段進(jìn)行數(shù)據(jù)插入的時(shí)候啃匿,就可以不用特別指定數(shù)據(jù),系統(tǒng)會(huì)自動(dòng)填充蛆楞。但是當(dāng)字段有數(shù)據(jù)插入的時(shí)候溯乒,默認(rèn)值不會(huì)生效。
mysql> insert into my_default values(1,'男'); #指定數(shù)據(jù)豹爹,不會(huì)觸發(fā)默認(rèn)值
Query OK, 1 row affected (0.09 sec)
mysql> insert into my_default (id) values(2); #默認(rèn)值字段不給數(shù)據(jù)裆悄,系統(tǒng)自動(dòng)調(diào)用默認(rèn)值
Query OK, 1 row affected (0.08 sec)
- 數(shù)據(jù)在有了默認(rèn)值的時(shí)候,有的時(shí)候一條SQL指令可能會(huì)因?yàn)橄胗媚硞€(gè)默認(rèn)值而不得不指定字段列表臂聋,這種操作將會(huì)非常麻煩且容易出錯(cuò)光稼,因此也可以在進(jìn)行數(shù)據(jù)插入的值部分時(shí),使用Default關(guān)鍵字強(qiáng)制使用默認(rèn)值
mysql> insert into my_default values(3,default);
Query OK, 1 row affected (0.43 sec)
總結(jié)
- default 值;可以設(shè)定某個(gè)字段常見數(shù)據(jù)的默認(rèn)值孩等,從而不需要開發(fā)者每次都去組織數(shù)據(jù)
- default關(guān)鍵字可以用在數(shù)據(jù)插入insert語句的值列表中艾君,強(qiáng)制觸發(fā)默認(rèn)值
- 一般情況下,不設(shè)定默認(rèn)值時(shí)肄方,字段的默認(rèn)值通常都是NULL
思考:數(shù)據(jù)在進(jìn)入數(shù)據(jù)庫之后冰垄,更多的操作是查詢操作。在查詢操作的時(shí)候权她,怎么能夠從那么多數(shù)據(jù)中快速的取出一條目標(biāo)數(shù)據(jù)呢虹茶?
引入:想要達(dá)到數(shù)據(jù)的快速獲取,就需要對(duì)數(shù)據(jù)建立一個(gè)索引(目錄)關(guān)系隅要,通過關(guān)系進(jìn)行數(shù)據(jù)獲取就會(huì)效率很高蝴罪。而索引關(guān)系的建立最有效率的一種方式,就是讓每條記錄本身具有唯一性步清。因此要门,MySQL中有一種能夠讓某個(gè)字段數(shù)據(jù)保證唯一的方式,叫做主鍵尼啡。
4.primary key屬性【掌握】
定義:primary key也叫主鍵暂衡,是一種有效保障所設(shè)定字段所有數(shù)據(jù)具有唯一性的屬性询微,也是最高效的一種數(shù)據(jù)表目錄崖瞭。
- 主鍵可以通過在具體字段后使用primary key關(guān)鍵字實(shí)現(xiàn)
mysql> create table my_primary1(
-> id char(18) primary key,
-> name varchar(10) not null,
-> age tinyint unsigned not null
-> )charset utf8;
Query OK, 0 rows affected (0.72 sec)
- 主鍵字段對(duì)應(yīng)的數(shù)據(jù)不允許重復(fù)
mysql> insert into my_primary1 values('510310199910101010','Jim',18);
Query OK, 1 row affected (0.43 sec)
mysql> insert into my_primary1 values('510310199910101010','Tom',20);
ERROR 1062 (23000): Duplicate entry '510310199910101010' for key 'PRIMARY' #錯(cuò)誤:id字段重復(fù)
- 主鍵字段默認(rèn)不能為空
mysql> desc my_primary1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | char(18) | NO | PRI | NULL | | #PRI表示primary key,Null字段自動(dòng)為NO
| name | varchar(10) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
- 主鍵的創(chuàng)建也可以通過在所有字段后使用primary key(主鍵字段名)來設(shè)定
mysql> create table my_primary2(
-> id char(18),
-> name varchar(10) not null,
-> age tinyint unsigned not null,
-> primary key(id)
-> )charset utf8;
Query OK, 0 rows affected (0.66 sec)
- 主鍵可以是復(fù)合主鍵撑毛,即由多個(gè)字段共同組成一個(gè)主鍵书聚,復(fù)合主鍵是通過在表所有字段后使用primary key(字段1,字段2...)組成唧领,通常最多主鍵由兩個(gè)字段組成
mysql> create table my_primary3(
-> id char(18),
-> name varchar(10),
-> age tinyint unsigned not null,
-> primary key(id,name)
-> )charset utf8;
Query OK, 0 rows affected (0.75 sec)
- 主鍵刪除:如果一張表中已經(jīng)設(shè)定主鍵,且不再需要主鍵了雌续,那么可以通過修改表實(shí)現(xiàn):alter table 表名 drop primary key;
mysql> alter table my_primary3 drop primary key;
Query OK, 0 rows affected (1.25 sec)
Records: 0 Duplicates: 0 Warnings: 0
- 追加主鍵:如果一張表設(shè)計(jì)之初沒有主鍵斩个,但是后期為了查詢效率追加主鍵,也可以通過修改表實(shí)現(xiàn):alter table 表名 add primary key(主鍵字段列表);(可以是復(fù)合主鍵)
mysql> alter table my_primary3 add primary key(id);
Query OK, 0 rows affected (1.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
注意:追加主鍵的字段要求對(duì)應(yīng)字段的數(shù)據(jù)必須是唯一的且不能有NULL數(shù)據(jù)
- 邏輯主鍵:通常在進(jìn)行表設(shè)計(jì)的時(shí)候驯杜,主鍵是為了保障數(shù)據(jù)的唯一性受啥,而且主鍵的更重要的使用方式是為了方便數(shù)據(jù)的高效查詢。所以在創(chuàng)建主鍵的時(shí)候鸽心,通常不是針對(duì)具體的業(yè)務(wù)數(shù)據(jù)來設(shè)定主鍵滚局,而是設(shè)定一個(gè)對(duì)應(yīng)的無實(shí)際業(yè)務(wù)含義的字段(數(shù)字),這種主鍵稱之為邏輯主鍵
mysql> create table my_primary4(
-> id int primary key,
-> id_card char(18) not null,
-> name varchar(10) not null,
-> age tinyint unsigned not null
-> )charset utf8;
Query OK, 0 rows affected (0.65 sec)
總結(jié)
- 主鍵是一種保證表中數(shù)據(jù)具有唯一性的手段
- 主鍵的方式可以在字段后跟primary key關(guān)鍵字顽频,或者在所有字段后使用primary key(字段名)藤肢,抑或在創(chuàng)建表后使用修改表結(jié)構(gòu)alter table 表名 add primary key(字段名)實(shí)現(xiàn)
- 主鍵通常是使用邏輯主鍵實(shí)現(xiàn)
- 主鍵會(huì)自動(dòng)讓對(duì)應(yīng)字段的數(shù)據(jù)不能為空(NOT NULL)
- 主鍵的作用不僅僅是讓數(shù)據(jù)保證唯一性,還會(huì)讓表的查詢效率提升(通過主鍵條件查詢)
- 一張表只能有一個(gè)主鍵(除非是復(fù)合主鍵)
思考:使用邏輯主鍵后糯景,對(duì)應(yīng)的字段數(shù)據(jù)是整數(shù)嘁圈,這個(gè)數(shù)據(jù)每次都需要開發(fā)人員自己去實(shí)現(xiàn),尤其是想保證數(shù)據(jù)是連續(xù)的情況下蟀淮,還要在數(shù)據(jù)插入前先查看或者獲取最大的主鍵最住,這樣操作不是很麻煩嗎?
引入:如果說邏輯主鍵每次進(jìn)行數(shù)據(jù)插入操作的時(shí)候怠惶,需要提前進(jìn)行數(shù)據(jù)獲取温学,那么操作的確會(huì)變得非常繁瑣。針對(duì)邏輯主鍵這一特點(diǎn)甚疟,MySQL提供了一種機(jī)制仗岖,能夠讓系統(tǒng)自動(dòng)創(chuàng)建有序數(shù)據(jù)來實(shí)現(xiàn)填充,這就是自增長屬性览妖。
5.auto_increment屬性【掌握】
定義:auto_increment自增長轧拄,是針對(duì)某些特定情況下的==整數(shù)==,通過設(shè)定auto_increment屬性讽膏,在進(jìn)行數(shù)據(jù)插入操作的時(shí)候檩电,無需手動(dòng)指定其值,系統(tǒng)會(huì)自動(dòng)找到當(dāng)前最大的值然后+1實(shí)現(xiàn)府树。
- 自增長必須搭配==整數(shù)類型==且對(duì)應(yīng)字段必須存在==索引==(就是Key字段必須有值)俐末,所以通常自增長是配邏輯主鍵
mysql> create table my_auto(
-> id int primary key auto_increment,
-> name varchar(10) not null,
-> age tinyint unsigned not null
-> )charset utf8;
Query OK, 0 rows affected (0.31 sec)
- 當(dāng)字段有自增長屬性后,可以在進(jìn)行數(shù)據(jù)插入的時(shí)候奄侠,使用null替代對(duì)應(yīng)字段(或者不指定相應(yīng)字段)
mysql> insert into my_auto values(null,'Lily',19);
Query OK, 1 row affected (0.41 sec)
- 自增長設(shè)定后卓箫,默認(rèn)是從1開始自增的
mysql> insert into my_auto values(null,'Lily',19);
Query OK, 1 row affected (0.41 sec)
mysql> select * from my_auto;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | Lily | 19 |
+----+------+-----+
1 row in set (0.00 sec)
- 一張表只能擁有一個(gè)自增長字段,自增長字段綁定后會(huì)出現(xiàn)在表選項(xiàng)中垄潮,可以通過show create table 表名查看
mysql> show create table my_auto\G
*************************** 1. row ***************************
Table: my_auto
Create Table: CREATE TABLE `my_auto` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`age` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
1 row in set (0.05 sec)
# AUTO_INCREMENT=2表示下一個(gè)值自動(dòng)填充的話就是2
- 自增長也可以被手動(dòng)數(shù)據(jù)填充:即插入數(shù)據(jù)時(shí)明確指定自增長字段數(shù)據(jù)
mysql> insert into my_auto values(10,'Han',20);
Query OK, 1 row affected (0.44 sec)
注意:自增長是根據(jù)表中已有的最大值自動(dòng)加1操作烹卒,因此當(dāng)手動(dòng)插入數(shù)據(jù)偏大時(shí)闷盔,系統(tǒng)下次自動(dòng)操作的值也是從目前最大的值+1
mysql> insert into my_auto values(null,'Lilei',21);
Query OK, 1 row affected (0.43 sec)
mysql> select * from my_auto;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | Lily | 19 |
| 10 | Han | 20 |
| 11 | Lilei | 21 |
+----+-------+-----+
3 rows in set (0.00 sec)
- 自增長可以通過后期表字段進(jìn)行維護(hù):增刪改
mysql> alter table 表名 modify 字段名 字段類型 [字段屬性] auto_increment; #新增操作
#假設(shè)原有表中id為主鍵,沒有自增長(邏輯主鍵)
alter table my_auto modify id int auto_increment;
mysql> alter table 表名 modify 字段名 字段類型 [字段屬性]; #清除自增長
#假設(shè)原有ID有自動(dòng)增長屬性
alter table my_auto modify id int;
mysql> altr table 表名 auto_increment = 新值; #修改自增長下個(gè)值(只能大于當(dāng)前最大的)
alter table my_auto auto_increment = 5; #改小不行
alter table my_auto auto_increment = 15; #改大可以
- MySQL中自增長的控制:起始值和步長(每次變化多少),都是在MySQL系統(tǒng)中通過變量控制的旅急,可以通過show variables like ‘a(chǎn)uto_increment%';查看
mysql> show variables like 'auto_increment%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set, 1 warning (0.52 sec)
注意:該值可以通過set 變量名 = 新值;改變逢勾,只是通常不會(huì)去改變
總結(jié)
- auto_increment能夠使得字段會(huì)自動(dòng)增加值,而不需要手動(dòng)操作
- auto_increment必須匹配整型字段以及字段本身必須是索引(通常是邏輯主鍵)
- auto_increment的觸發(fā)可以通過NULL來實(shí)現(xiàn)
- auto_increment的初始值是1藐吮,步長也是1(MySQL變量控制)
- auto_increment可以在后期通過表選項(xiàng)修改值
- auto_increment一張表中只能設(shè)定一個(gè)字段
思考:一張表最多有一個(gè)主鍵溺拱,而且主鍵通常還是邏輯主機(jī)與業(yè)務(wù)數(shù)據(jù)無關(guān),那么如果還有其他字段也需要保證數(shù)據(jù)的唯一性谣辞,難道就沒有其他辦法了嗎盟迟?
引入:在實(shí)際開發(fā)工作中,有些內(nèi)容是需要唯一保障的潦闲,如用戶登錄名攒菠、聯(lián)系方式和郵箱等,這些都需要數(shù)據(jù)唯一性保證安全歉闰。主鍵作為一個(gè)一張表只能有一個(gè)的情況下辖众,顯然滿足不了數(shù)據(jù)這塊的要求。因此MySQL提供了另外一種不限量的唯一控制和敬,那就是唯一鍵凹炸。
6.unique key屬性【掌握】
定義:unique key唯一鍵,和primary key主鍵類似昼弟,目的就是保障對(duì)應(yīng)字段的所有數(shù)據(jù)具有唯一性
- 在字段后使用unique關(guān)鍵字描述字段
mysql> create table my_unique1(
-> id int primary key auto_increment,
-> username varchar(20) unique,
-> email varchar(50) not null
-> )charset utf8;
Query OK, 0 rows affected (0.75 sec)
- unqiue唯一鍵的效果就是當(dāng)數(shù)據(jù)插入重復(fù)的時(shí)候會(huì)報(bào)錯(cuò)
mysql> insert into my_unique1 values(null,'username1','user1@qq.com');
Query OK, 1 row affected (0.42 sec)
mysql> insert into my_unique1 values(null,'username1','user2@qq.com');
ERROR 1062 (23000): Duplicate entry 'username1' for key 'username' #錯(cuò)誤:username1已經(jīng)存在
- unique唯一鍵不會(huì)像主鍵一樣強(qiáng)勢啤它,默認(rèn)允許字段為空,且NULL數(shù)據(jù)不存在重復(fù)問題
mysql> desc my_unique1;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment | #主鍵不允許為NULL
| username | varchar(20) | YES | UNI | NULL | | #唯一鍵允許字段為NULL
| email | varchar(50) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> insert into my_unique1 values(null,null,'user2@qq.com'),(null,null,'user3@qq.com');
Query OK, 2 rows affected (0.43 sec)
Records: 2 Duplicates: 0 Warnings: 0
- unique唯一鍵允許一張表中多個(gè)字段使用
mysql> create table my_unique2(
-> id int primary key auto_increment,
-> username varchar(20) unique,
-> email varchar(50) unique
-> )charset utf8;
Query OK, 0 rows affected (0.76 sec)
- unique也可以在所有字段后使用unique key(字段名列表)一樣設(shè)置唯一鍵舱痘,多個(gè)字段也可以組成復(fù)合唯一鍵
mysql> create table my_unique3(
-> id int primary key auto_increment,
-> username varchar(20) not null,
-> email varchar(50) not null,
-> unique key `username_index` (username), #`username_index`為指定的名字
-> unique key(email) #默認(rèn)名字就是字段本身
-> )charset utf8;
Query OK, 0 rows affected (0.43 sec)
#復(fù)合唯一鍵
mysql> create table my_unique4(
-> id int primary key auto_increment,
-> username varchar(20) not null,
-> email varchar(50) not null,
-> unique key `username_email` (username,email)
-> )charset utf8;
Query OK, 0 rows affected (0.04 sec)
- 唯一鍵刪除:unique唯一鍵不像primary key那樣可以直接刪除变骡,因?yàn)閡nique key一張表可以有多個(gè),系統(tǒng)不清楚刪除誰芭逝。unique key在表中被當(dāng)做一個(gè)普通索引塌碌,因此刪除方式為:alter table 表名 drop index 唯一鍵對(duì)應(yīng)的索引名字
mysql> alter table my_unique3 drop index username_index;
Query OK, 0 rows affected (0.29 sec)
Records: 0 Duplicates: 0 Warnings: 0
- 唯一鍵修改:唯一鍵沒有提供修改方式,可以通過先刪除唯一鍵旬盯,然后再增加唯一鍵
- 唯一鍵增加:alter table 表名 add unique (字段列表)台妆;
mysql> alter table my_unique3 add unique(username);
Query OK, 0 rows affected (0.29 sec)
Records: 0 Duplicates: 0 Warnings: 0
總結(jié)
- 唯一鍵可以通過字段后unique、所有字段后unique key [名字] (字段列表)胖翰、alter table 表名 add unique(字段列表)三種方式實(shí)現(xiàn)
- 唯一鍵的效果是能夠讓對(duì)應(yīng)字段數(shù)據(jù)保證唯一性
- 唯一鍵允許字段為NULL接剩,且不把NULL作為唯一數(shù)據(jù)判定(如果確定數(shù)據(jù)不需要為空應(yīng)該使用NOT NULL屬性)
- 唯一鍵的刪除沒有特殊性,使用普通索引刪除方式alter table 表名 drop index 唯一鍵名字; (名字默認(rèn)是字段名)
- 唯一鍵可以在表中使用多次(也可以是復(fù)合唯一鍵)
思考:進(jìn)入企業(yè)后有部分情況是別人已經(jīng)開發(fā)好的系統(tǒng)萨咳,那么考慮到一些個(gè)人英文能力問題懊缺,有的人設(shè)計(jì)的表可能字段表示的內(nèi)容不是很清晰,這種時(shí)候應(yīng)該怎么辦呢某弦?
引入:表字段的設(shè)計(jì)通常是見名知意桐汤,這是行業(yè)的規(guī)矩。但是不乏有人在設(shè)計(jì)表的時(shí)候比較隨意靶壮,導(dǎo)致要使用該表的人就比較痛苦怔毛。為了解決這一問題,MySQL建議在字段后增加對(duì)應(yīng)的字段描述腾降,以說明字段的數(shù)據(jù)內(nèi)容拣度。
7.comment屬性【了解】
定義:comment說明的意思,意在給字段增加相應(yīng)的==文字描述==螃壤,更清晰的表達(dá)設(shè)計(jì)者的意圖抗果。字段的描述不會(huì)對(duì)字段或者數(shù)據(jù)本身產(chǎn)生任何影響,只是方便開發(fā)者進(jìn)行查閱码荔。
- 在字段后使用comment '描述說明'
mysql> create table my_comment(
-> id int primary key auto_increment comment '邏輯主鍵',
-> username varchar(10) not null unique comment '用戶名不能為空且唯一',
-> age tinyint unsigned not null comment '年齡不為空月洛,區(qū)間為0-255'
-> )charset utf8;
Query OK, 0 rows affected (0.74 sec)
- 字段說明不會(huì)在其他任何地方看到内列,只能通過查看表創(chuàng)建語句查看
mysql> show create table my_comment\G
*************************** 1. row ***************************
Table: my_comment
Create Table: CREATE TABLE `my_comment` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '邏輯主鍵',
`username` varchar(10) NOT NULL COMMENT '用戶名不能為空且唯一',
`age` tinyint(3) unsigned NOT NULL COMMENT '年齡不為空,區(qū)間為0-255',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
總結(jié):字段說明是為了方便開發(fā)者閱讀設(shè)計(jì)者的想法逮光,以及明確字段索要表示的內(nèi)容。作為一名優(yōu)秀的開發(fā)者墩划,應(yīng)當(dāng)在盡量增加字段說明以便于團(tuán)隊(duì)協(xié)作開發(fā)涕刚。