Python學習之旅—Mysql數據庫之數據類型和約束
前言
本篇博客我們主要專註於解決Mysql數據庫中的數據類型和約束,將重點聚焦於字符類型,日期類型,集合類型和主鍵和unique等知識點,希望各位可以好好掌握今天的知識點。
一.整數類型
#整數類型:TINYINT SMALLINT MEDIUMINT INT BIGINT
#作用:存儲年齡,等級,id,各種號碼等
#ps:默認都是有符號的
關於整數類型,我們需要關註一點,即整形的寬度指的是顯示寬度,而不是存儲寬度
我們來看看如下的例子:
create table t1(id int(1));
insert into t1 values(256111);
select * from t1;
create table t2(id int(20));
insert into t2 values(256111);
select * from t2;
create table t3(id int(20) zerofill);
insert into t3 values(256111);
select * from t3;
mysql> create table t4(id int);
Query OK, 0 rows affected (0.46 sec)
mysql> desc t4;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.02 sec)
mysql> insert into t4 values(1111111111111111111111111111111111111111111);
Query OK, 1 row affected, 2 warnings (0.17 sec)
mysql> select * from t4;
+------------+
| id |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)
mysql> create table t5(id int unsigned);
Query OK, 0 rows affected (0.45 sec)
mysql> desc t5;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
1 row in set (0.01 sec)
mysql> insert into t5 values(11111111111111111111111111111111111111111);
Query OK, 1 row affected, 2 warnings (0.05 sec)
mysql> select * from t5;
+------------+
| id |
+------------+
| 4294967295 |
+------------+
1 row in set (0.00 sec)
二.浮點數類型
浮點類型主要分為三種:FLOAT,DOUBLE,DECIMAL;其主要用來標識體重,薪資,價格等屬性
mysql> create table t6(weight float(256,56) unsigned);
ERROR 1425 (42000): Too big scale 56 specified for column ‘weight‘. Maximum is 30.
mysql> create table t6(weight float(256,30) unsigned);
ERROR 1439 (42000): Display width out of range for column ‘weight‘ (max = 255)
mysql> create table t6(weight float(255,30) unsigned);
Query OK, 0 rows affected (0.37 sec)
mysql> desc t6;
+--------+------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------------+------+-----+---------+-------+
| weight | float(255,30) unsigned | YES | | NULL | |
+--------+------------------------+------+-----+---------+-------+
1 row in set (0.01 sec)
mysql> create table t7(weight double(256,33) unsigned);
ERROR 1425 (42000): Too big scale 33 specified for column ‘weight‘. Maximum is 30
mysql> create table t7(weight double(256,30) unsigned);
ERROR 1439 (42000): Display width out of range for column ‘weight‘ (max = 255)
mysql> create table t7(weight double(255,30) unsigned);
Query OK, 0 rows affected (0.36 sec)
mysql> create table t8(weight decimal(66,33) unsigned);
ERROR 1425 (42000): Too big scale 33 specified for column ‘weight‘. Maximum is 30.
mysql> create table t8(weight decimal(66,30) unsigned);
ERROR 1426 (42000): Too big precision 66 specified for column ‘weight‘. Maximum is 65.
mysql> create table t8(weight decimal(65,30) unsigned);
Query OK, 0 rows affected (0.39 sec)
三.日期類型
日期類型主要分為如下五種:
DATE:2017-11-11 出生年月日
TIME:10:14:11 上課時間
DATETIME:2017-11-11 10:14:11 註冊時間,文章發布時間,員工入職時間
TIMESTAMP:2017-11-11 10:14:11
YEAR :1970 出生年
我們來驗證下:
CREATE DATABASE day47;
use day47;
create table t10(
born_date DATE,
class_time TIME,
reg_time DATETIME,
born_year YEAR
);
INSERT INTO t10 VALUES
(‘1999-11-11‘, ‘08:30:00‘, ‘2017-03-01 11:11:11‘, 1992);==============================================
下面我們來看看datetime與timestamp的區別:
create table t11(
x datetime,
y timestamp
);
desc t11;
mysql> desc t11;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-----------------------------+
| x | datetime | YES | | NULL | |
| y | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+-----------+------+-----+-------------------+-----------------------------+
2 rows in set (0.01 sec)
從上面的信息可知,timestamp默認是不能傳空,其默認值是當前的時間戳;而datetime是可以傳空的。
我們來驗證下:
mysql> insert into t11 values(null,null);
Query OK, 1 row affected (0.04 sec)
mysql> select * from t11;
+------+---------------------+
| x | y |
+------+---------------------+
| NULL | 2017-10-23 10:25:07 |
+------+---------------------+
1 row in set (0.00 sec)
從上面的信息可知,當我們為timestamp傳遞空值時,其默認值是當前的時間。
實際使用我們使用的還是datetime.
四.字符類型
char類型:
範圍:0-255
特點:
定長,簡單粗暴,浪費空間(待存儲的數據長度<寬度限制),存取速度快
varchar類型:
範圍:0-21844
特點:
變長,精準,節省空間(待存儲的數據長度<寬度限制),存取速度慢
註意:如果我們需要存儲的是定長的字段,推薦使用char,例如IP地址;而且當我們使用where條件進行過濾時,由於它的存取速度比較
快,所以更加適合使用where條件來過濾。如果是一些不定常的字段,而且不會使用到where條件進行過濾時,推薦使用varchar(),例如
關於某件商品的評價等等。
五.枚舉與集合類型
枚舉與集合類型往往對應這樣的需求,例如某些字段的值是固定的幾個,例如性別,男或者女,此時我們就可以將性別這個字段設定
為枚舉類型;使用enum關鍵字修飾;再例如,用戶的字段屬性可能有多個值,其他用戶屬性可以從這幾個值中選取幾個作為自己的值。
例如以用戶權限表為例子,管理員具有查看學生,修改學生表,創建學生記錄的功能,而班主任只能查看學生記錄,此時如果需要定義具體的
權限,我們就可以將權限描述字段定義為一個集合即可。
create table t18(
id int,
name char(10),
sex enum(‘male‘,‘female‘,‘None‘) # 表示只能從集合中取一個值
);
# 修改表的結構,表示不能傳遞空,默認是male
alter table t18 modify sex enum(‘male‘,‘female‘,‘None‘) not null default ‘male‘;
insert into t18 values(1,‘egon‘,‘xxxxx‘);
insert into t18(id,name) values(1,‘egon‘);
下面我們來關註下set集合:表示多選,例如下面的例子中我為hobbies設置值時,可以從裏面選擇多個值進行組合。
create table t19(
id int,
name char(10),
hobbies set(‘music‘,‘read‘,‘basketball‘,‘football‘,‘eat‘,‘sleep‘)
);
insert into t19 values(1,‘egon‘,‘music,read,eat‘);
六.字段的約束
KEY:
primay key 主鍵,一個表中只能有一個主鍵,主鍵的意思就是非空且唯一
unique 定義該字段的值唯一
【001】我們設置一個整形字段直接自增,會報錯:提示只能有一個自增長的字段,要麽是unique key,要麽是primary key
mysql> create table t20(id int auto_increment,name char(10));
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
create table t20(id int primary key auto_increment,name char(10));
create table t21(id int not null unique auto_increment,name char(10));
比較t20和t21這兩張表,我們發現primary key和not null unique是等同的
【002】下面我們來驗證下,一張表中是否可以建立多個主鍵
create table t22(
id int primary key,
name char(10)
);
create table t23(
id int,
name char(10),
constraint pri_id primary key(id) # 在字段定義完畢後,再來限制它為主鍵,這裏pri_id給約束起一個名字
);
上面的方式也可以像如下的方式這樣寫(實際中我們還是直接在定義字段的時候就指定主鍵)
create table t24(
id int,
name char(10),
primary key(id)
);
下面我們演示直接加入unique key,下面兩種方式均可以
create table t25(
id int,
name char(10),
constraint uni_id unique(id)
);
create table t26(
id int,
name char(10),
unique(id)
);
#只能有一個主建,但是可以有多個not null unique
# 創建如下這張表時會報錯,因為一張表中只能存在一個主鍵
create table t27(
id int,
name char(10),
primary key(id),
primary key(name)
);
一張表中可以有多個not null unique
create table t28(
id int not null unique,
name char(10) not null unique
);
DESC t28;
雖然可以存在多個not null unique,但是最終只有一個成為了主鍵,只有ID成為了主鍵
即如果你在定義一個表時,沒有使用primary key定義主鍵,那麽默認就用第一個not null unique修飾的字段作為主鍵
表中不一定需要存在主鍵
我們最後來看一個聯合唯一的主鍵
需求:現在我使用t29來存儲一個服務信息,
為了保證每個服務是獨立的,我需要保證該服務所對應的IP地址和端口的組合不一樣
IP地址可以一樣,只要端口不一樣即可,這就設計到聯合唯一的概念。我們可以將
ip和端口設置為一個聯合主鍵
#聯合唯一
create table t29(
id int,
ip char(15), # 由於IP地址是固定的長度,所以我們推薦使用char類型
port int,
primary key(ip,port)
);
insert into t29 values
(1,‘1.1.1.1‘,3306),
(2,‘1.1.1.2‘,3306),
(3,‘1.1.1.1‘,8080)
;
現在問題來了,這樣設置不合理,因為ID這個字段應該是自增的,用來標識此時到了多少條記錄
既然是自增的,那麽就要將它設置為一個key,要麽是primary key,要麽是unique key;
通常ID字段設置為primary key,我們通常查詢表時,都是通過ID字段來作為查詢依據,這涉及到
MySQL的優化機制。像上面的那樣,如果設置將IP和port設置為primary key,以後查詢就很不方便。
而同時我們又要保證ip和port的組合不為空且唯一,所以只能將其設置為unique。
這樣設置完畢後,就可以保證ip和port是聯合唯一的,但主鍵不是它們兩個
create table t30(
id int primary key auto_increment,
ip char(15) not null,
port int not null,
unique(ip,port)
);
desc t30;
此時我們可以得知ip和port就是聯合唯一的,下面我們插入值就可以使用如下的方式啦,非常方便:
insert into t30(ip,port) values
(‘1.1.1.1‘,3306),
(‘1.1.1.1‘,3307),
(‘1.1.1.2‘,3307)
;
結語:
本篇博客主要梳理了數據類型相關聯的知識點,大家需要重點掌握不同數據類型的約束,下一篇我們將重點梳理使用外鍵來定義不同表之間的關系。
Python學習之旅—Mysql數據庫之數據類型和約束