內容提要:
-
建表完整語法規范(create table 表格(字段名1 類型 (寬度) 約束條件))
-
MySQL數據庫數據類型(整型、浮點型、字符類型(char與varchar)、日期類型、枚舉與集合)
-
約束條件(primary key、unique key、not null、foreign key)
一、創建表的完整語法
語法:
create table 表名(
字段名1 類型 (寬度) 約束條件,
字段名2 類型 (寬度) 約束條件,
字段名3 類型 (寬度) 約束條件);
特別注意:
- 在同一張表中,字段名不能相同
- 寬度和約束條件為可選項,但是字段名和類型必須有
- 最后一個字段添加完畢后后面不能加逗號!
補充:1、這里的寬度是對存儲數據的一種限制,在不同MySQL版本里面可能會出現不同的結果,這里只是不同版本的默認約束條件不一樣導致,在最新版本5,7中如果輸入數據
寬度超出限制,則會報錯。
2、類型與約束條件的區別:類型是限制字段必須以什么樣的數據類型存儲,二約束條件是在這一類型之上添加一種額外的限制。
二、MySQL基本數據類型
-
整型(int)
- 分類:tinyint smallint mediumint int bigint
- 作用:儲存年齡、等級、id、各種號碼等
- 類型存儲范圍:

-
驗證整型字段有無符號及范圍 int類型默認是有符號的,也就是說默認支持輸入負數到正數 mysql> reate table t1(id tinyint); mysql> insert into t1 values(128),(-129); #結果:ERROR 1264 (22003): Out of range value for column 'id' at row 1 # 因為tinyint類型最大正整數限制為127,輸入128超出范圍。報錯 create table t2(id tinyint unsigned); # unsigned表示這里類型設置為無符號(無正負號) mysql> insert into t2 values (0),(255); #這里類型約束為無符號,所以輸入負數就會報錯,輸入超過255的數也會報錯。tinyint無符號范圍是0-255。 以下同理: create table t3(id int unsigned); mysql> insert into t3 values (4294967296); ERROR 1264 (22003): Out of range value for column 'id' at row 1 mysql> insert into t3 values (4294967295); Query OK, 1 row affected (0.01 sec) 強調:對於整型來說,數據類型之后的寬度並不是存儲限制,而是現實寬度限制,所以在創建表的時候, 如果字段采用的是整型類型,完全無需指定顯示寬度,因為默認的顯示寬度(11),一般情況下,就足夠顯示完整的數據。
-
浮點型(分為float、double、decimal)
- 應用場景:身高、體重、薪資
- 字符限制特點(5,3),前一位表示所有的位數,后一位表示小數個數
- 區別對比:
# 存儲限制 float(255,30) double(255,30) decimal(65,30) # 精確度驗證 mysql> create table t9(x float(255,30)); mysql> create table t10(x double(255,30)); mysql> create table t11(x decimal(65,30)); mysql> insert into t9 values(1.111111111111111111111111111111); mysql> insert into t10 values(1.111111111111111111111111111111); mysql> insert into t11 values(1.111111111111111111111111111111); mysql> select * from t9; +----------------------------------+ | x | +----------------------------------+ | 1.111111164093017600000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t10; +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111200000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t11; +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111111111111111111 | +----------------------------------+ 1 row in set (0.00 sec) 從上面的查詢創建的表中數據可以看出: 精度對比:decimal的精度最高,其次是double,最后是float, 但是就算是精度最低的float它的精度也有16位,所以一般使用完全能夠應付99%的數據場景。
-
字符類型(char定長與varchar變長)
- 作用:姓名、地址、描述類信息
- 理解通過實際使用來描述:
char: mysql> create table t12(name char(4)); mysql> insert into t12 values ('hello'); ERROR 1406 (22001): Data too long for column 'name' at row 1 # 超出限制范圍會報錯。 mysql> insert into t12 values ('hell'); Query OK, 1 row affected (0.01 sec) mysql> insert into t12 values ('he'); Query OK, 1 row affected (0.00 sec) mysql> select * from t12; +------+ | name | +------+ | hell | # 4個字符正好填滿 | he | #不夠4個字符空格補全 +------+ -------------------------------------------------------------- varchar: mysql> create table t13(name varchar(4)); mysql> insert into t13 values ('hello'); ERROR 1406 (22001): Data too long for column 'name' at row 1 # 超出范圍,報錯 mysql> insert into t13 values ('hell'); Query OK, 1 row affected (0.00 sec) mysql> insert into t13 values ('he'); Query OK, 1 row affected (0.01 sec) mysql> select * from t13; +------+ | name | +------+ | hell | # 正好4個,填滿 | he | # 不夠4個,按實際寬度占位。(這里看不出來,但是一定要記住,varchar是變長,所以不夠4個肯定按實際寬度存儲) +------+ ##### TIP: select char_length(name) from t12 select char_length(name) from t13 # 仍然無法查看到真正的結果 """首先應該肯定的是在硬盤上存的絕對是真正的數據,但顯示的時候mysql會自動將末尾的空格取掉""" # 如果不想讓mysql幫你做自動去除末尾空格的操作,需要再添加一個模式 set global sql_mode="strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH"; # 退出客戶端重新登陸 select char_length(x) from t12; #4 select char_length(y) from t13; #1 # 針對char類型,mysql在存儲時會將數據用空格補全存放到硬盤中。但是會在讀出結果的時候自動取掉末尾的空格 ####
- char 與 varchar 的使用區別
- name char(5)
- 優點:浪費空間,每個name信息都是按照5個字符存,這樣如果不夠5個的也會用空格補全,造成存儲空間浪費
- 缺點:存取速度很快,因為存儲數據的結構固定,所以存取速度快。
- egon alex lxx jxx txx 存用5個字符5個字符存,取的話也是5個字符為一部分取,准確快捷
- name varchar(5)
- 缺點:存取速度慢,每個name信息按照可變長的形式去存,同時存的時候要在前面加入該字符長度的報頭,一並存入,取的時候按照報頭里的長度數據去取數據,比char多了好幾步,所以存取數據相比較char會慢些。
- 優點:節省空間,通過可變長來存入,加上報頭數據也不會造成空間的太多浪費
- 1bytes+egon 1bytes+alex 1bytes+lxx 1bytes+jxx 1bytes+txx
- name char(5)
-
時間類型
- 分類:
- date:2019-05-13
- time:11:11:11
- datetime:2019-05-13 11:11:11
- year:2019
- 測試:
mysql> create table stu(id int,name char(16),birth_d date,study_time time,reg_time datetime); # 創建表 mysql> insert into stu values(1,'jason','2019-05-09','11:11:11','2019-11-11 11:11"11'); #插入表數據 Query OK, 1 row affected (0.00 sec) mysql> select * from stu; # 顯示表內容 +------+-------+------------+------------+---------------------+ | id | name | birth_d | study_time | reg_time | +------+-------+------------+------------+---------------------+ | 1 | jason | 2019-05-09 | 11:11:11 | 2019-11-11 11:11:11 | +------+-------+------------+------------+---------------------+ 1 row in set (0.00 sec)
- 分類:
-
枚舉與集合類型:
- 分類
- 枚舉enum 多選一
- 集合set 多選 一或多
- 示例:
enum枚舉: mysql> create table usr(id int,name char(16),gender enum('male','female','others')); Query OK, 0 rows affected (0.05 sec) mysql> insert into usr values(1001,'jsson','xxx'); ERROR 1265 (01000): Data truncated for column 'gender' at row 1 mysql> insert into usr values(1001,'jsson','male'); Query OK, 1 row affected (0.01 sec) mysql> insert into usr values(1002,'egon','female'); Query OK, 1 row affected (0.01 sec) mysql> select * from usr; +------+-------+--------+ | id | name | gender | +------+-------+--------+ | 1001 | jsson | male | | 1002 | egon | female | +------+-------+--------+ 2 rows in set (0.00 sec) ----------------------------------------------------------------- set集合: mysql> create table tea(id int,name char(16),gender enum('male','female','other'),hobby set('read','sleep','dbj')); Query OK, 0 rows affected (0.04 sec) mysql> insert into tea values(10011,'egon','female','read,dbj'); Query OK, 1 row affected (0.01 sec) mysql> insert into tea values(10012,'alex','male','dbj'); Query OK, 1 row affected (0.05 sec) mysql> select * from tea; +-------+------+--------+----------+ | id | name | gender | hobby | +-------+------+--------+----------+ | 10011 | egon | female | read,dbj | | 10012 | alex | male | dbj | +-------+------+--------+----------+ 2 rows in set (0.00 sec)
- 分類
-
約束條件
- 類型
PRIMARY KEY (PK) 標識該字段為該表的主鍵,可以唯一的標識記錄 FOREIGN KEY (FK) 標識該字段為該表的外鍵 NOT NULL 標識該字段不能為空 UNIQUE KEY (UK) 標識該字段的值是唯一的 AUTO_INCREMENT 標識該字段的值自動增長(整數類型,而且為主鍵) DEFAULT 為該字段設置默認值 UNSIGNED 無符號 ZEROFILL 使用0填充not null + defaultnot null:不為空
-
not null + default
-
mysql> create table us(id int,name char(16)); Query OK, 0 rows affected (0.05 sec) mysql> insert into us values (1,null); Query OK, 1 row affected (0.01 sec) mysql> desc us; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | char(16) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ mysql> delete from us where id=1; # 先清空存入的null數據 Query OK, 1 row affected (0.01 sec) mysql> alter table us modify name char(16) not null; # 將name輸入的數據限制為非空 Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc us; # 查看表格式: +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | char(16) | NO | | NULL | | +-------+----------+------+-----+---------+-------+ mysql> insert into us values(002,null); # 此時再輸入null就會報錯了,因為我們限制了name必須輸入未非空的字符。 ERROR 1048 (23000): Column 'name' cannot be null default 默認值 mysql> create table st(id int,name char(16) not null,gender enum('male','female') default 'male'); # 為gender字段設置默認值‘male,前面指定輸入字段不包含gender時候,這時候的默認字段名就會生效。 Query OK, 0 rows affected (0.03 sec) mysql> insert into st(id,name) values (1001,'lxx'); Query OK, 1 row affected (0.01 sec) mysql> select * from st; +------+------+--------+ | id | name | gender | +------+------+--------+ | 1001 | lxx | male | +------+------+--------+ 1 row in set (0.00 sec)
-
unique 某個字段對應的值在當前表中是唯一的,不能重復
###單列唯一: mysql> create table user1(id int unique,name char(16)); Query OK, 0 rows affected (0.04 sec) mysql> insert into user1 values (1,'js'),(1,'eg'); #報錯 ERROR 1062 (23000): Duplicate entry '1' for key 'id' mysql> insert into user1 values (1,'js'),(2,'eg'); #不報錯 Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 ###聯合唯一:多個字段如果同時有相同的輸入時,會報錯 mysql> create table server(id int,ip char(16),port int,unique(ip,port)); Query OK, 0 rows affected (0.04 sec) mysql> desc server; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | ip | char(16) | YES | MUL | NULL | | | port | int(11) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> insert into server values (1,'127.0.0.1',8080); Query OK, 1 row affected (0.01 sec) mysql> insert into server values (2,'127.0.0.1',8080); #ip和port都相同,報錯 ERROR 1062 (23000): Duplicate entry '127.0.0.1-8080' for key 'ip' mysql> insert into server values (2,'127.0.0.2',8080); # 僅僅是port相同不會報錯 Query OK, 1 row affected (0.00 sec) mysql> insert into server values (3,'127.0.0.1',8081); #僅僅是ip相同也不會報錯 Query OK, 1 row affected (0.00 sec) mysql> select * from server; 查看結果: +------+-----------+------+ | id | ip | port | +------+-----------+------+ | 1 | 127.0.0.1 | 8080 | | 2 | 127.0.0.2 | 8080 | | 3 | 127.0.0.1 | 8081 | +------+-----------+------+ 3 rows in set (0.00 sec)
-
primary key+auto_increment(mysql數據類型及約束條件的重點內容,必須要掌握)
# 單從約束角度來說 primary key 等價於not null + unique mysql> create table tt1(id int primary key); # 設置id主鍵唯一 Query OK, 0 rows affected (0.04 sec) mysql> desc tt1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.00 sec) mysql> insert into tt1 values (1),(1); # 主鍵不唯一,報錯 ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> insert into tt1 values (1),(2); #唯一,不報錯 Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 -----------------------------------------------------------------
重點內容: 一、一張表中必須有且只有一個主鍵,如果你沒有設置主鍵,那么會從上到下搜索直到遇到一個非null且unique的字段自動將其設為主鍵。 mysql> create table ts1(id int,name char(16),age int not null unique,addr char(16) not null unique)engine=innodb; Query OK, 0 rows affected (0.04 sec) mysql> desc ts1; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | char(16) | YES | | NULL | | | age | int(11) | NO | PRI | NULL | | | addr | char(16) | NO | UNI | NULL | | +-------+----------+------+-----+---------+-------+ ------------------------------------------------------------------ 二、如果表里面沒有指定的任何可以設置的主鍵字段,那么innodb存儲引擎會采用自己的默認的一個隱藏的字段作為主鍵,隱藏意味着你在查詢的時候無法根據主鍵字段加速查詢了 ------------------------------------------------------------------ 三、一張表中通常都應該有一個id字段,並且通常將id字段設為主鍵 ------------------------------------------------------------------ 額外知識點: #聯合主鍵:與聯合唯一字段一個道理,即多個字段聯合起來作為表的主鍵,本質上將多個字段總體看為一個主鍵 mysql> create table ts2(ip char(16),port int,primary key(ip,port)); Query OK, 0 rows affected (0.04 sec) mysql> desc ts2; # 2個字段合為一個主鍵。 +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | ip | char(16) | NO | PRI | NULL | | | port | int(11) | NO | PRI | NULL | | +-------+----------+------+-----+---------+-------+
auto_increment 自增約束 mysql> create table ts3(id int primary key auto_increment,name char(16)); Query OK, 0 rows affected (0.05 sec) mysql> insert into ts3(name) values ('jason'),('alex'),('lxx'); #只輸入name字段信息 Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from ts3; # 查看自增結果 +----+-------+ | id | name | +----+-------+ | 1 | jason | | 2 | alex | | 3 | lxx | +----+-------+ ------------------------------------------------------------------ 補充: 接着上面的例子,如果我將其中一個字段比如lxx,刪除后再添加字段,會出現: mysql> delete from ts3 where id=3; Query OK, 1 row affected (0.01 sec) mysql> insert into ts3(name) values ('xxxx'); Query OK, 1 row affected (0.01 sec) mysql> select * from ts3; +----+-------+ | id | name | +----+-------+ | 1 | jason | | 2 | alex | | 4 | xxxx | # 此時序號居然還是接着自增。 +----+-------+ 3 rows in set (0.00 sec) tip:如果要清楚繼續自增,從頭開始的話,就必須清空表,才行。 mysql> truncate ts3; # 將整張表重置,id重新從0開始記錄。 Query OK, 0 rows affected (0.03 sec) mysql> insert into ts3(name) values ('eeeee'); Query OK, 1 row affected (0.01 sec) mysql> select * from ts3; +----+-------+ | id | name | +----+-------+ | 1 | eeeee | +----+-------+
-
- 類型
-------------------------------------------------------------------------------------------------------------------------------------------
-
嚴格模式補充
我們剛剛在上面設置了char,tinyint,存儲數據時超過它們的最大存儲長度,發現數據也能正常存儲進去,只是mysql幫我們自動截取了最大長度。但在實際情況下,我們應該盡量減少數據庫的操作,緩解數據庫的壓力,讓它僅僅只管理數據即可,這樣的情況下就需要設置安全模式
show variables like "%mode%"; # 查看數據庫配置中變量名包含mode的配置參數 # 修改安全模式 set session # 只在當前操作界面有效 set global # 全局有效 set global sql_mode ='STRICT_TRANS_TABLES' # 修改完之后退出當前客戶端重新登陸即可
