mysql基礎-02
1.2 資料型別
MySQL中的資料型別是強型別,規定是什麼型別,就得輸入什麼樣的值
1.2.1 數值型
1、 整型
整形 | 佔用位元組數 | 範圍 |
---|---|---|
tinyint | 1 | -128~127 |
smallint | 2 | -32768~32767 |
mediumint | 3 | -8388608~8388607 |
int | 4 | -2147483648~2147483647 |
bigint | 8 | -9223372036854775808~9223372036854775807 |
選擇的範圍儘可能小,這樣範圍越小佔用資源越少
mysql> create table stu1( -> id tinyint, # 範圍要儘可能小,範圍越小,佔用空間越少 -> name varchar(20) -> ); Query OK, 0 rows affected (0.02 sec) -- 超出範圍會報錯 mysql> insert into stu1 values (128,'tom'); -- 128 超出了 ERROR 1264 (22003): Out of range value for column 'id' at row 1
無符號整形(unsigned) 無符號整形就是沒有負數,無符號整數表示範圍是整數的兩倍
mysql> create table stu2(
-> id tinyint unsigned # 無符號整數
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into stu2 values (128);
Query OK, 1 row affected (0.00 sec)
整形支援顯示寬度,顯示寬頻是最小的顯示位數,如int(11)表示整形最少用11位表示,如果不夠位數用0填充。顯示寬度預設不起作用,必須結合zerofill才起作用。
mysql> create table stu4( -> id int(5), -> num int(5) zerofill # 新增前導0,int(5)顯示寬頻是5 -> ); Query OK, 0 rows affected (0.05 sec) mysql> insert into stu4 values (12,12);-- 如果插入的值的順序和個數與表字段的順序個數一致,插入的欄位名可以省略 Query OK, 1 row affected (0.00 sec) mysql> select * from stu4;-- 查詢所有欄位的值 +------+-------+ | id | num | +------+-------+ | 12 | 00012 | +------+-------+ 1 row in set (0.00 sec)
小結:
1、範圍要儘可能小,範圍越小,佔用空間越少
2、無符號整數是整數的兩倍
3、整形支援顯示寬度,顯示寬頻是最小的顯示位數,必須結合zerofill才起作用
2、浮點型
浮點型 | 佔用位元組數 | 範圍 |
---|---|---|
float(單精度型) | 4 | -3.4E+38~3.4E+38 |
double(雙精度型) | 8 | -1.8E+308~1.8E+308 |
浮點型的宣告:float(M,D) double(M,D)
M:總位數 D:小數位數
例題
mysql> create table stu5(
-> num1 float(5,2), -- 浮點數
-> num2 double(6,1) -- 雙精度數
-> );
Query OK, 0 rows affected (0.05 sec)
mysql> insert into stu5 values (3.1415,12.96);
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu5;
+------+------+
| num1 | num2 |
+------+------+
| 3.14 | 13.0 |
+------+------+
1 row in set (0.00 sec)
MySQL浮點數支援科學計數法
mysql> create table stu6(
-> num float # 不指定位數,預設是小數點後面6位 double預設是17位
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> insert into stu6 values (5E2),(6E-2); # 插入科學計數法
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from stu6;
+------+
| num |
+------+
| 500 |
| 0.06 |
+------+
2 rows in set (0.00 sec)
浮點數精度會丟失
mysql> insert into stu6 values(99.999999999);
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu6;
+------+
| num |
+------+
| 100 |
+------+
小結:
1、浮點數有單精度和雙精度
2、浮點數支援科學計數法
3、浮點數精度會丟失
3、小數(定點數)
原理:將M整數部分和D小數部分分開儲存
語法:
decimal(M,D) -- M:總位數;D:小數位數
例題:
mysql> create table stu8(
-> num decimal(20,9) # 存放定點數
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> insert into stu8 values(12.999999999);
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu8;
+--------------+
| num |
+--------------+
| 12.999999999 |
+--------------+
1 row in set (0.00 sec)
小結:
1、decimal是變長的,大致是每9個數字用4個位元組儲存,整數和小數分開計算。M最大是65,D最大是30,預設是(10,2)。
2、定點和浮點都支援無符號、顯示寬度0填充。
1.2.2 字元型
在資料庫中沒有字串概念,只有字元,所以資料庫中只能用單引號
資料型別 | 描述 |
---|---|
char | 定長字元,最大可以到255 |
varchar | 可變長度字元,最大可以到65535 |
tinytext | 2^8^–1 =255 |
text | 2^16^–1 =65535 |
mediumtext | 2^24^–1 |
longtext | 2^32^–1 |
char(4):存放4個字元,中英文一樣。
varchar(L)實現變長機制,需要額外的空間來記錄資料真實的長度。
L的理論長度是65535,但事實上達不到,因為有的字元是多位元組字元,所以L達不到65535。
text系列的型別在表中儲存的是地址,佔用大小大約10個位元組
一個記錄的所有欄位的總長度也不能超過65535個位元組。
小結:
1、char是定長,var是變長
2、char最大值是255,varchar最大值是65535,具體要看字元編碼
3、text系列在表中儲存的是地址
4、一條記錄的總長度不能超過65535
1.2.3 列舉(enum)
從集合中選擇一個值作為資料(單選)
mysql> create table stu12(
-> name varchar(20),
-> sex enum('男','女','保密') # 列舉
-> );
Query OK, 0 rows affected (0.06 sec)
-- 插入的列舉值只能是列舉中提供的選項,如果要給sex欄位賦值,只能是男、女、保密、或者對應數字
mysql> insert into stu12 values ('tom','男');
Query OK, 1 row affected (0.00 sec)
-- 報錯,只能插入男、女、保密
mysql> insert into stu12 values ('tom','不告訴你');
ERROR 1265 (01000): Data truncated for column 'sex' at row 1
列舉值是通過整形數字來管理的,第一個值是1,第二個值是2,以此類推,列舉值在資料庫儲存的是整形數字。
mysql> insert into stu12 values ('berry',2); -- 插入數字,按照順序,2代表女
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu12;
+-------+------+
| name | sex |
+-------+------+
| tom | 男 |
| berry | 女 |
+-------+------+
-- WHERE字句用於篩選資料,提取滿足條件的記錄。WHERE字句的基本用法:SELECT * from 表名 WHERE 條件語句;
mysql> select * from stu12 where sex=2; -- 2表示第二個列舉值
+-------+------+
| name | sex |
+-------+------+
| berry | 女 |
+-------+------+
1 row in set (0.00 sec)
列舉優點:
(1)、限制值
(2)、節省空間
(3)、執行速度快(整形比字串執行速度快)
思考:已知列舉佔用兩個位元組,所以最多可以有多少個列舉值?
答:2位元組=16位,2^16^=65536,範圍是(0-65535),由於列舉從1開始,所以列舉值最多有65535個
1.2.4 集合(set)
從集合中選擇一些值作為資料(多選)
mysql> create table stu13(
-> name varchar(20),
-> hobby set('爬山','讀書','游泳','燙頭') -- 集合
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> insert into stu13 values ('tom','爬山');
mysql> insert into stu13 values ('Berry','爬山,游泳');
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu13 values ('Berry','游泳,爬山'); -- 插入的順序不一樣,但顯示的順序一樣
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu13;
+-------+-----------+
| name | hobby |
+-------+-----------+
| tom | 爬山 |
| Berry | 爬山,游泳 |
| Berry | 爬山,游泳 |
+-------+-----------+
3 rows in set (0.00 sec)
集合和列舉一樣,也為每個集合元素分配一個固定值,分配方式是從前往後按2的0、1、2、…次方,轉換成二進位制後只有一位是1,其他都是0。
'爬山','讀書','游泳','燙頭'
1 2 4 8
mysql> select hobby+0 from stu13;
+---------+
| hobby+0 |
+---------+
| 1 |
| 5 |
| 5 |
+---------+
mysql> insert into stu13 values ('rose',15);
Query OK, 1 row affected (0.00 sec)
已知集合型別佔8個位元組,那麼集合中最多有多少選項
答:有64個選項。
1.2.5 日期時間型
資料型別 | 描述 |
---|---|
datetime | 日期時間,佔用8個位元組 |
date | 日期 佔用3個位元組 |
time | 時間 佔用3個位元組 |
year | 年份,佔用1個位元組 |
timestamp | 時間戳,佔用4個位元組 |
1、datetime和date
datetime格式:年-月-日 小時:分鐘:秒。支援的範圍是'1000-01-01 00:00:00'到'9999-12-31
23:59:59'。
mysql> create table stu14(
-> t1 datetime, -- 日期時間
-> t2 date -- 日期
-> );
Query OK, 0 rows affected (0.05 sec)
-- 插入測試資料
mysql> insert into stu14 values ('2019-01-15 12:12:12','2019-01-15 12:12:12');
Query OK, 1 row affected, 1 warning (0.00 sec)
-- 查詢
mysql> select * from stu14;
+---------------------+------------+
| t1 | t2 |
+---------------------+------------+
| 2019-01-15 12:12:12 | 2019-01-15 |
+---------------------+------------+
1 row in set (0.00 sec)
2、timestamp(時間戳)
datetime型別和timestamp型別表現上是一樣的,他們的區別在於:
datetime從1000到9999,而timestamp從1970年~2038年(原因在於timestamp佔用4個位元組,和整形的範圍一樣,2038年01月19日11:14:07以後的秒數就超過了4個位元組的長度)
mysql> create table stu15(
-> t1 timestamp
-> );
Query OK, 0 rows affected (0.06 sec)
mysql> insert into stu15 values ('2038-01-19 11:14:07');
Query OK, 1 row affected (0.00 sec)
3、year
只能表示1901~2155之間的年份,因為只佔用1個位元組,只能表示255個數
mysql> create table stu16(
-> y1 year
-> );
Query OK, 0 rows affected (0.08 sec)
mysql> insert into stu16 values (2155);
Query OK, 1 row affected (0.00 sec)
4、time
可以表示時間,也可以表示時間間隔。範圍是:-838:59:59~838:59:59
mysql> create table stu17(
-> t1 time
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into stu17 values ('12:12:12');
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu17 values ('212:12:12');
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu17 values ('-212:12:12');
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu17 values ('839:00:00'); -- 報錯
ERROR 1292 (22007): Incorrect time value: '839:00:00' for column 't1' at row 1
-- time支援以天的方式來表示時間間隔
mysql> insert into stu17 values ('10 10:25:25'); -- 10天10小時25分25秒
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu17;
+------------+
| t1 |
+------------+
| 12:12:12 |
| 212:12:12 |
| -212:12:12 |
| 250:25:25 |
+------------+
4 rows in set (0.00 sec)
1.2.6 Boolean
MySQL不支援布林型,true和false在資料庫中對應的是1和0
mysql> create table stu18(
-> flag boolean
-> );
Query OK, 0 rows affected (0.05 sec)
mysql> desc stu18;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| flag | tinyint(1) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into stu18 values (true),(false);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from stu18;
+------+
| flag |
+------+
| 1 |
| 0 |
+------+
2 rows in set (0.00 sec
小結:
boolean型在MySQL中對應的是tinyint。
1.2.6 練習題
電話號碼一般使用什麼資料型別儲存? varchar
手機號碼用什麼資料型別 char
性別一般使用什麼資料型別儲存? char tinyint enum
年齡資訊一般使用什麼資料型別儲存? tinyint
照片資訊一般使用什麼資料型別儲存? binary
薪水一般使用什麼資料型別儲存? decimal
1.3 列屬性
1.3.1 是否為空(null|not null)
null表示欄位值可以為null
not null欄位值不能為空
練習
學員姓名允許為空嗎? not null
家庭地址允許為空嗎? not null
電子郵件資訊允許為空嗎? null
考試成績允許為空嗎? null
1.3.2 預設值(default)
如果一個欄位沒有插入值,可以預設插入一個指定的值
mysql> create table stu19(
-> name varchar(20) not null default '姓名不詳',
-> addr varchar(50) not null default '地址不詳'
-> );
Query OK, 0 rows affected (0.05 sec)
mysql> insert into stu19(name) values ('tom');
Query OK, 1 row affected (0.00 sec)
mysql> insert into stu19 values (default,default);
Query OK, 1 row affected (0.00 sec)
mysql> select * from stu19;
+----------+----------+
| name | addr |
+----------+----------+
| tom | 地址不詳 |
| 姓名不詳 | 地址不詳 |
+----------+----------+
2 rows in set (0.00 sec)
小結:
default關鍵字用來插入預設值
1.3.3 自動增長(auto_increment)
欄位值從1開始,每次遞增1,自動增長的值就不會有重複,適合用來生成唯一的id。在MySQL中只要是自動增長列必須是主鍵
1.3.4 主鍵(primary key)
主鍵概念:唯一標識表中的記錄的一個或一組列稱為主鍵。如一張表格的序號標識
特點:
1、不能重複、不能為空
2、一個表只能有一個主鍵。
作用:
1、保證資料完整性
2、加快查詢速度
選擇主鍵的原則
最少性:儘量選擇單個鍵作為主鍵
穩定性:儘量選擇數值更新少的列作為主鍵
比如:學號,姓名、地址 這三個欄位都不重複,選哪個做主鍵
選學號,因為學號最穩定
練習
-- 建立主鍵方法一
mysql> create table stu20(
-> id int auto_increment primary key,-- primary key 主鍵
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.04 sec)
-- 建立主鍵方法二
mysql> create table stu21(
-> id int auto_increment,
-> name varchar(20),
-> primary key(id)
-> );
Query OK, 0 rows affected (0.02 sec)
組合鍵
mysql> create table stu22(
-> classname varchar(20),
-> stuname varchar(20),
-> primary key(classname,stuname) -- 建立組合鍵
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> desc stu22;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| classname | varchar(20) | NO | PRI | | |
| stuname | varchar(20) | NO | PRI | | |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
通過更改表新增主鍵
mysql> create table stu23(
-> id int,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.05 sec)
-- 新增主鍵
mysql> alter table stu23 add primary key(id);
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
刪除主鍵
mysql> alter table stu23 drop primary key;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
插入資料
mysql> create table stu25(
-> id tinyint unsigned auto_increment primary key,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.05 sec)
-- 插入資料
mysql> insert into stu25 values (3,'tom'); -- 可以直接插入數字
Query OK, 1 row affected (0.06 sec)
-- 自動增長列可以插入null,讓列的值自動遞增
mysql> insert into stu25 values (null,'berry');
Query OK, 1 row affected (0.00 sec)
小結:
1、只要是auto_increment必須是主鍵,但是主鍵不一定是auto_increment
2、主鍵特點是不能重複不能為空
3、一個表只能有一個主鍵,但是一個主鍵可以有多個欄位組成
4、自動增長列通過插入null值讓其遞增
5、自動增長列的資料被刪除,預設不再重複使用。truncate table刪除資料後,再次插入從1開始
練習
在主鍵列輸入的數值,允許為空嗎? 不可以
一個表可以有多個主鍵嗎? 不可以
在一個學校資料庫中,如果一個學校內允許重名的學員,但是一個班級內不允許學員重名,可以組合班級和姓名兩個欄位一起來作為主鍵嗎? 對
標識列(自動增長列)允許為字元資料型別嗎? 不允許
一個自動增長列中,插入3行,刪除2行,插入3行,刪除2行,插入3行,刪除2行,再次插入是多少? 10
1.3.5 唯一鍵(unique)
鍵 | 區別 |
---|---|
主鍵 | 1、不能重複,不能為空 2、一個表只能有一個主鍵 |
唯一鍵 | 1、不能重刻,可以為空 2、一個表可以有多個唯一鍵 |
例題
-- 建立表的時候建立唯一鍵
mysql> create table stu26(
-> id int auto_increment primary key,
-> name varchar(20) unique -- 唯一鍵
-> );
Query OK, 0 rows affected (0.05 sec)
-- 方法二
mysql> create table stu27(
-> id int primary key,
-> name varchar(20),
-> unique(name)
-> );
Query OK, 0 rows affected (0.05 sec)
多學一招:
unique 或 unique key 是一樣的
通過修改表新增唯一鍵
-- 將name設為唯一鍵
mysql> alter table stu28 add unique(name);
-- 將name,addr設為唯一鍵
mysql> alter table stu28 add unique(name),add unique(addr);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc stu28;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | UNI | NULL | |
| addr | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)
通過show create table 檢視唯一鍵的名字
通過唯一鍵的名字刪除唯一鍵
mysql> alter table stu28 drop index name;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
1.3.6 備註(comment)
說明性文字
mysql> create table stu29(
-> id int primary key comment '學號',
-> name varchar(20) not null comment '姓名'
-> );
Query OK, 0 rows affected (0.03 sec)
注意:備註屬於SQL程式碼的一部分
1.4 SQL註釋
單行註釋
-- 單行註釋
# 單行註釋
多行註釋 /* */
1.5 資料完整性
1.5.1 資料完整性包括
1、實體完整性
1、主鍵約束
2、唯一約束
3、標識列
2、 域完整性
1、資料型別約束
2、非空約束
3、預設值約束
3、 引用完整性
外來鍵約束
4、 自定義完整性
1、儲存過程
2、觸發器
1.5.2 主表和從表
- 主表中沒有的記錄,從表不允許插入
- 從表中有的記錄,主表中不允許刪除
- 刪除主表前,先刪子表
1.5.3 外來鍵(foreign key)
外來鍵:從表中的公共欄位
-- 建立表的時候新增外來鍵
create table stuinfo(
id tinyint primary key,
name varchar(20)
)engine=innodb;
create table stuscore(
sid tinyint primary key,
score tinyint unsigned,
foreign key(sid) references stuinfo(id) -- 建立外來鍵
)engine=innodb;
-- 通過修改表的時候新增外來鍵
語法:alter table 從表 add foreign key(公共欄位) references 主表(公共欄位)
drop table if exists stuinfo;-- 因為上面已經建立了相同的表,所以在這裡刪除了重新建立
create table stuinfo(
id tinyint primary key,
name varchar(20)
)engine=innodb;
drop table if exists stuscore;
create table stuscore(
sid tinyint primary key,
score tinyint unsigned
)engine=innodb;
alter table stuscore add foreign key (sid) references stuinfo(id)
刪除外來鍵
通過外來鍵的名字刪除外來鍵(首先要顯示出外來鍵的名字,如下:)
-- 刪除外來鍵
mysql> alter table stuscore drop foreign key `stuscore_ibfk_1`;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
小結:
1、只有innodb才能支援外來鍵
2、公共欄位的名字可以不一樣,但是資料型別要一樣
1.5.4 三種外來鍵操作(這一小節看視訊筆記好)
1、 嚴格限制(參見主表和從表)
2、 置空操作(set null):如果主表記錄刪除,或關聯欄位更新,則從表外來鍵欄位被設定為null。
3、 級聯操作(cascade):如果主表記錄刪除,則從表記錄也被刪除。主表更新,從表外來鍵欄位也更新。
語法:foreign key (外來鍵欄位) references 主表名 (關聯欄位) [主表記錄刪除時的動作] [主表記錄更新時的動作]。
一般說刪除時置空,更新時級聯。
drop table if exists stuinfo;
create table stuinfo(
id tinyint primary key comment '學號,主鍵',
name varchar(20) comment '姓名'
)engine=innodb;
drop table if exists stuscore;
create table stuscore(
id int auto_increment primary key comment '主鍵',
sid tinyint comment '學號,外來鍵',
score tinyint unsigned comment '成績',
foreign key(sid) references stuinfo(id) on delete set null on update cascade
-- on delete set null:當主表記錄刪除時 (從表外來鍵欄位)置空
-- on update cascade: 主表記錄更新時 從表級聯(級聯就能實現主表更新,從表也跟著更新)
)engine=innodb;
小結:
置空、級聯操作中外來鍵不能是從表的主鍵
1.6 補充
phpstudy中MySQL預設不是嚴格模式,將MySQL設定成嚴格模式
開啟my.ini,在sql-mode的值中,新增STRICT_TRANS_TABLES
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES"
測試:然而非嚴格模式下,沒有設定字元編碼,輸入中文,能夠執行,但是顯示不出來或者顯示為亂碼
單詞
medium:中等的
small:小
tiny:微小
big:大