MySQL數據類型
MySQL支持多種數據類型,主要有數值類型、日期/時間類型和字符串類型。
1.數值數據類型
包括整數類型TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT、浮點小數數據類型FLOAT和DOUBLE、定點小樹類型DECIMAL。
2.日期/時間類型
包括YEAR、TIME、DATE、DATETIME和TIMESTAMP。
3.字符串類型
包括CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET等。
-
1. 整數類型
數值型數據類型主要用來存儲數字,MYSQL提供了多種數值數據類型,不同的數據庫有不同的取值范圍,可以存儲的值范圍越大,其所存儲的控件也會越大。MySQL主要提供整數類型有:TINYTINT、SMALLINT、MEDIUMINT、INT、BIGINT。整數類型屬性的字段可以添加AUTO_INCREMENT自增約束條件。下表列出了MySQL中的數值類型。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
TINYINT | 很小的整數 | 1個字節 |
SMALLINT | 小的整數 | 2個字節 |
MEDIUMINT | 中等大小的整數 | 3個字節 |
INT | 普通大小的整數 | 4個字節 |
BIGINT | 大整數 | 8個字節 |
從表可知,不同類型整數存儲所需的字節數是不同的,占用字節數最小的是TINYINT類型,占用字節最大的是BIGINT類型,相應的占用字節越多的類型所能表示的數值范圍越大。根據占用字節數可以求出每一種數據的取值范圍,例如TINYINT需要1個字節(8bits)來存儲,那么TINYINT無符號數的最大值為2^8-1,即255;TINYINT有符號數的最大值為2^7-1,即127。其它類型如下表所示:
數據類型 | 有符號 | 無符號 |
---|---|---|
TINYINT | -128~127 | 0~255 |
SMALLINT | -32768~32767 | 0~65535 |
MEDIUMINT | -8388608~8388607 | 0~16777215 |
INT | -2147483648~2147483647 | 0~4294967295 |
BIGINT | -9223372036854775808~9223372036854775807 | 0~18446744073709551615 |
1.2 浮點數類型和定點數類型
MySQL中使用浮點數和定點數來表示小數。浮點類型有兩種:單精度(FLOAT)和雙精度(DOUBLE)。定點類型只有一種:DECIMAL。浮點類型和定點類型都可以用(M,N)來表示,其中M稱為精度,表示總共的位數;N稱為標度,是表示小數的位數。下表列出了小數類型存儲的需求。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
FLOAT | 單精度浮點數 | 4個字節 |
DOUBLE | 雙精度浮點數 | 8個字節 |
DECIMAL(M,D),DEC | 壓縮的”嚴格”定點數 | M+2個字節 |
DECIMAL類型不同於FLOAT和DOUBLE,DECIMAL實際是以串存放的,DECIMAL可能的最大取值范圍與DOUBLE一樣,但是其有效的取值范圍由M和D的值決定。如果改變M而固定D,則取值范圍將隨M的變大而變大。
1.3 日期/時間類型
MySQL中有多種表示日期的數據類型,主要有:DATETIME、DATE、TIMESTAMP、TIME和YEAR。下表列出了MySQL日期/時間類型:
類型名稱 | 日期格式 | 日期范圍 | 存儲需求 |
---|---|---|---|
YEAR | YYYY | 1901~2155 | 1字節 |
TIME | HH:MM:SS | -838:59:59~838:59:59 | 3字節 |
DATE | YYYY-MM-DD | 1000-01-01~9999-12-3 | 3字節 |
DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00~9999-12-31 23:59:59 | 8字節 |
TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1970-01-01 UTC ~ 2038-01-19 03:14:07 UTC | 4字節 |
1.4 字符串類型
字符串類型用來存儲字符串數據,除了可以存儲字符串之外,還可以存儲其它數據,比如圖片和聲音二進制數據。字符串可以進行區分或者不區分大小寫的串比較,另外,還可以進行模式匹配查找。MySQL中字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。下表列出了字符串數據類型。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
CHAR(M) | 固定長度非二進制字符串 | M字節,1<=M<=255 |
VARCHAR(M) | 變長非二進制字符串 | L+1字節,在此L<=M和1<=M<=255 |
TINYTEXT | 非常小的非二進制字符串 | L+1字節,在此L<2^8 |
TEXT | 小的非二進制字符串 | L+2字節,在此L<2^16 |
MEDIUMTEXT | 中等大小的非二進制字符串 | L+3字節,在此L<2^32 |
LONGTEXT | 大的非二進制字符串 | L+4字節,在此L<2^24 |
ENUM | 枚舉類型,只能有一個枚舉字符串值 | 1或2個字節,取決於枚舉值數目(最大值65535) |
SET | 一個設置,字符串對象可以有0個或多個SET成員 | 1,2,3,4或8個字節,取決於集合成員的數量(最多64個成員) |
1.5 二進制類型
MySQL支持兩類字符型數據:文本字符串和二進制字符串。MySQL中存儲二進制字符串數據類型有:BIT、BINARY、TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。下表列出了二進制數據類型:
類型名稱 | 說明 | 存儲需求 |
---|---|---|
BIT(M) | 位字段類型 | 大約(M+7)/8個字節 |
BINARY(M) | 固定長度二進制字符串 | M個字節 |
VARBINARY(M) | 可變長度二進制字符串 | M+1個字節 |
TINYBLOB(M) | 非常小的BLOB | L+1個字節,在此L<2^8 |
BLOB(M) | 小BLOB | L+2字節,在此L<2^16 |
MEDIUMBLOB(M) | 中等大小的BLOB | L+3字節,在此L<2^24 |
LONGBLOB(M) | 非常大的BLOB | L+4字節,在此L<2^32 |
如何選擇數據類型
MySQL提供了大量的數據類型,為了優化存儲,提高數據庫性能,在任何情況下均應該使用精確的類型。即在所有可以表示該列值的類型中,該類型使用的存儲最少。
2.1 整數和浮點數
如果不需要小數部分,則使用整數來保存數據;如果需要小數部分,則使用浮點數來表示。對於浮點數據列,存入的數值會對該列定義的小數位進行四舍五入。例如,如果列的值范圍為1-99999,若使用整數,則MEDIUMINT UNSIGNED是最好的類型;若需存儲小數,則使用FLOAT類型。
浮點類型包括FLOAT和DOUBLE類型。DOUBLE類型精度比FLOAT類型高,因此,如要求存儲精度較高時,應選擇DOUBLE。
2.2 浮點數和定點數
浮點數FLOAT、DOUBLE相對於定點數DECIMAL的優勢是:在長度一定的情況下,浮點數能表示更大的數據范圍。但是由於浮點數容易產生誤差,因此對精確度要求比較高時,建議使用DECIMAL來存儲。DECIMAL在MySQL中是以字符串存儲的,用於定義貨幣等對精確度要求較高的數據。DECIMAL在MySQL中是以字符串存儲的。在數據遷移中,float(M,D)是非標准SQL定義,數據庫遷移可能會出現問題,最好不要這樣使用。另外兩個浮點數進行減法和比較運算時也容易出現問題,因此在進行計算的時候,一定要小心。如果進行數值比較,建議使用DECIMAL類型。
2.3 日期/時間類型
MySQL對於不同種類的日期和時間有多種數據類型,比如YEAR和TIME。如果只需記錄年份,則使用YEAR即可,如果只記錄時間,則使用TIME類型。
如果同時需要記錄日期和時間則可以使用TIMESTAMP或者DATETIME類型。由於TIMESTAMP這個列取值時范圍小於DATETIME的取值范圍,因此存儲范圍較大的日期最好使用DATETIME。
TIMESTAMP也有一個DATETIME不具備的屬性。默認情況下,當插入一條記錄但並沒有指定TIMESTAMP這個列值時,MySQL會把TIMESTAMP列設為當前的時間。因此需要插入記錄同時插入當前時間時,使用TIMESTAMP是方便的,另外TIMESTAMP在空��上比DATETIME更有效。
2.4 CHAR與VARCHAR之間的特點與選擇
CHAR與VARCHAR之間的區別:
CHAR是固定長度字符,VARCHAR是可變長度字符;CHAR會自動刪除插入數據的尾部空格,VARCHAR不刪除尾部空格。
CHAR是固定長度,所以它的處理速度比VARCHAR速度要快,但是它的缺點就是浪費存儲空間。所以對存儲不大,但在速度上有要求的可以使用CHAR類型,反之可以使用VARCHAR類型來實現。
存儲引擎對CHAR和VARCHAR的影響:
對於MyISAM存儲引擎,最好使用固定長度的數據列代替可變長度的數據列。這樣可以使整個表靜態化,從而使數據檢索更快,用存儲空間換查詢時間。
對於InnoDB存儲引擎:使用可變長的數據列,因為InnoDB數據表的存儲格式不分固定長度和可變長度,因此使用CHAR不一定比使用VARCHAR更好,但由於VARCHAR是按照實際存的長度存儲,比較節省空間,所以對磁盤I/O和數據存儲總量比較好。
2.5 ENUM和SET
ENUM只能取單值,它的數據列表示一個枚舉集合。它的合法值列表最多有65535個成員。因此,在需要從多個值中選取一個時,可以使用ENUM。比如:性別字段適合定義成ENUM類型,每次只能從’男’ 或 ‘女’中取一個值。
SET可取多值。它的合法取值列表最多允許有64個成員。空字符串也是一個合法的SET值。在需要取多個值的時候,適合使用SET類型,比如:要存儲一個興趣愛好,最好使用SET類型。
ENUM和SET的值是以字符串形式出現的,但在內部,MySQL以數值的形式存儲它們。
2.6 BLOB和TEXT
BLOB是二進制字符串,TEXT是非二進制字符串,二者均可存放大容量信息。BLOB主要存儲圖片、音頻信息等,而TEXT只能存儲純文本文件,應分清二者存儲的關系。
完整約束
約束條件與數據類型的寬度一樣,都是可選參數
作用:用於保證數據的完整性和一致性
分類及詳解

PRIMARY KEY (PK) 標識該字段為該表的主鍵,可以唯一的標識記錄 FOREIGN KEY (FK) 標識該字段為該表的外鍵 NOT NULL 標識該字段不能為空 UNIQUE KEY (UK) 標識該字段的值是唯一的 AUTO_INCREMENT 標識該字段的值自動增長(整數類型,而且為主鍵) DEFAULT 為該字段設置默認值 UNSIGNED 無符號 ZEROFILL 使用0填充 1. 是否允許為空,默認NULL,可設置NOT NULL,字段不允許為空,必須賦值 2. 字段是否有默認值,缺省的默認值是NULL,如果插入記錄時不給字段賦值,此字段使用默認值 sex enum('male','female') not null default 'male' age int unsigned NOT NULL default 20 必須為正值(無符號) 不允許為空 默認是20 3. 是否是key 主鍵 primary key 外鍵 foreign key 索引 (index,unique...)
類型一 not null和default
not null - 不可空
default默認值,創建列時可以指定默認值,當插入數據時如果未主動設置,則自動添加默認值

==================not null==================== mysql> create table t1(id int); #id字段默認可以插入空 mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t1 values(); #可以插入空 mysql> create table t2(id int not null); #設置字段id不為空 mysql> desc t2; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | +-------+---------+------+-----+---------+-------+ mysql> insert into t2 values(); #不能插入空 ERROR 1364 (HY000): Field 'id' doesn't have a default value ==================default==================== #設置id字段有默認值后,則無論id字段是null還是not null,都可以插入空,插入空默認填入default指定的默認值 mysql> create table t3(id int default 1); mysql> alter table t3 modify id int not null default 1; ==================綜合練習==================== mysql> create table student( -> name varchar(20) not null, -> age int(3) unsigned not null default 18, -> sex enum('male','female') default 'male', -> hobby set('play','study','read','music') default 'play,music' -> ); mysql> desc student; +-------+------------------------------------+------+-----+------------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------------------------+------+-----+------------+-------+ | name | varchar(20) | NO | | NULL | | | age | int(3) unsigned | NO | | 18 | | | sex | enum('male','female') | YES | | male | | | hobby | set('play','study','read','music') | YES | | play,music | | +-------+------------------------------------+------+-----+------------+-------+ mysql> insert into student(name) values('egon'); mysql> select * from student; +------+-----+------+------------+ | name | age | sex | hobby | +------+-----+------+------------+ | egon | 18 | male | play,music | +------+-----+------+------------+
類型二 unique(設置唯一約束)

方法一: create table department1( id int, name varchar(20) unique, comment varchar(100) ); 方法二: create table department2( id int, name varchar(20), comment varchar(100), constraint uk_name unique(name) ); mysql> insert into department1 values(1,'IT','技術'); Query OK, 1 row affected (0.00 sec) mysql> insert into department1 values(1,'IT','技術'); 會報錯 怎么解決呢??? ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'
約束not null和unique結合的神奇之處:

mysql> create table t1(id int not null unique); Query OK, 0 rows affected (0.02 sec) mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.00 sec)
其實Notnull和unique結合就相當於把上面示例中的id字段設置為主鍵

create table service( id int primary key auto_increment, name varchar(20), host varchar(15) not null, port int not null, unique(host,port) #聯合唯一 ); mysql> insert into service values -> (1,'nginx','192.168.0.10',80), -> (2,'haproxy','192.168.0.20',80), -> (3,'mysql','192.168.0.30',3306) -> ; Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 將主鍵設置為host和port倆個字段
類型三 primary key設置主鍵
primary key 字段的值不為空且唯一 可設置為主鍵(單列做主鍵 多列做主鍵(符合主鍵))
單列主鍵:

============單列做主鍵=============== #方法一:not null+unique create table department1( id int not null unique, #主鍵 name varchar(20) not null unique, comment varchar(100) ); mysql> desc department1; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | NO | UNI | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec) #方法二:在某一個字段后用primary key create table department2( id int primary key, #主鍵 name varchar(20), comment varchar(100) ); mysql> desc department2; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.00 sec) #方法三:在所有字段后單獨定義primary key create table department3( id int, name varchar(20), comment varchar(100), constraint pk_name primary key(id); #創建主鍵並為其命名pk_name mysql> desc department3; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | comment | varchar(100) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ rows in set (0.01 sec)
多列主鍵:

==================多列做主鍵================ create table service( ip varchar(15), port char(5), service_name varchar(10) not null, primary key(ip,port) ); mysql> desc service; +--------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+-------+ | ip | varchar(15) | NO | PRI | NULL | | | port | char(5) | NO | PRI | NULL | | | service_name | varchar(10) | NO | | NULL | | +--------------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> insert into service values -> ('172.16.45.10','3306','mysqld'), -> ('172.16.45.11','3306','mariadb') -> ; Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into service values ('172.16.45.10','3306','nginx'); ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'
類型四 auto_increment
設置自增字段:

#不指定id,則自動增長 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' ); mysql> desc student; +-------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | sex | enum('male','female') | YES | | male | | +-------+-----------------------+------+-----+---------+----------------+ mysql> insert into student(name) values -> ('egon'), -> ('alex') -> ; mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | | 2 | alex | male | +----+------+------+ #也可以指定id mysql> insert into student values(4,'asb','female'); Query OK, 1 row affected (0.00 sec) mysql> insert into student values(7,'wsb','female'); Query OK, 1 row affected (0.00 sec) mysql> select * from student; +----+------+--------+ | id | name | sex | +----+------+--------+ | 1 | egon | male | | 2 | alex | male | | 4 | asb | female | | 7 | wsb | female | +----+------+--------+ #對於自增的字段,在用delete刪除后,再插入值,該字段仍按照刪除前的位置繼續增長 mysql> delete from student; Query OK, 4 rows affected (0.00 sec) mysql> select * from student; Empty set (0.00 sec) mysql> insert into student(name) values('ysb'); mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 8 | ysb | male | +----+------+------+ #應該用truncate清空表,比起delete一條一條地刪除記錄,truncate是直接清空表,在刪除大表時用它 mysql> truncate student; Query OK, 0 rows affected (0.01 sec) mysql> insert into student(name) values('egon'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 1 | egon | male | +----+------+------+ 1 row in set (0.00 sec)
設置自增字段的起始值和自增步長:

#在創建完表后,修改自增字段的起始值 mysql> create table student( -> id int primary key auto_increment, -> name varchar(20), -> sex enum('male','female') default 'male' -> ); mysql> alter table student auto_increment=3; mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 mysql> insert into student(name) values('egon'); Query OK, 1 row affected (0.01 sec) mysql> select * from student; +----+------+------+ | id | name | sex | +----+------+------+ | 3 | egon | male | +----+------+------+ row in set (0.00 sec) mysql> show create table student; ....... ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 #也可以創建表時指定auto_increment的初始值,注意初始值的設置為表選項,應該放到括號外 create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' )auto_increment=3; #設置步長 sqlserver:自增步長 基於表級別 create table t1( id int。。。 )engine=innodb,auto_increment=2 步長=2 default charset=utf8 mysql自增的步長: show session variables like 'auto_inc%'; #基於會話級別 set session auth_increment_increment=2 #修改會話級別的步長 #基於全局級別的 set global auth_increment_increment=2 #修改全局級別的步長(所有會話都生效) #!!!注意了注意了注意了!!! If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 翻譯:如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 比如:設置auto_increment_offset=3,auto_increment_increment=2 mysql> set global auto_increment_increment=5; Query OK, 0 rows affected (0.00 sec) mysql> set global auto_increment_offset=3; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'auto_incre%'; #需要退出重新登錄 +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | +--------------------------+-------+ create table student( id int primary key auto_increment, name varchar(20), sex enum('male','female') default 'male' ); mysql> insert into student(name) values('egon1'),('egon2'),('egon3'); mysql> select * from student; +----+-------+------+ | id | name | sex | +----+-------+------+ | 3 | egon1 | male | | 8 | egon2 | male | | 13 | egon3 | male | +----+-------+------+
類型五 foreign key
單獨作為一個知識點來講述 詳見foreign key詳解文章