MySQL數據庫中的數據類型
數據類型(data_type)是指系統中所允許的數據的類型。MySQL 數據類型定義了列中可以存儲什么數據以及該數據怎樣存儲的規則。
數據庫中的每個列都應該有適當的數據類型,用於限制或允許該列中存儲的數據。例如,列中存儲的為數字,則相應的數據類型應該為數值類型。
如果使用錯誤的數據類型可能會嚴重影響應用程序的功能和性能,所以在設計表時,應該特別重視數據列所用的數據類型。更改包含數據的列不是一件小事,這樣做可能會導致數據丟失。因此,在創建表時必須為每個列設置正確的數據類型和長度。
MySQL 的數據類型有大概可以分為 5 種,分別是整數類型、浮點數類型和定點數類型、日期和時間類型、字符串類型、二進制類型等。
1.MySQL整數類型
整數類型又稱數值型數據,數值型數據類型主要用來存儲數字。
MySQL 提供了多種數值型數據類型,不同的數據類型提供不同的取值范圍,可以存儲的值范圍越大,所需的存儲空間也會越大。
MySQL 主要提供的整數類型有 TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,其屬性字段可以添加 AUTO_INCREMENT 自增約束條件。
下表中列出了 MySQL 中的數值類型。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
TINYINT | 很小的整數 | 1個字節 |
SMALLINT | 小的整數 | 2個宇節 |
MEDIUMINT | 中等大小的整數 | 3個字節 |
INT (INTEGHR) | 普通大小的整數 | 4個字節 |
BIGINT | 大整數 | 8個字節 |
從上表中可以看到,不同類型的整數存儲所需的字節數不相同,占用字節數最小的是 TINYINT 類型,占用字節最大的是 BIGINT 類型,占用的字節越多的類型所能表示的數值范圍越大。
根據占用字節數可以求出每一種數據類型的取值范圍。例如,TINYINT 需要 1 個字節(8bit)來存儲,那么 TINYINT 無符號數的最大值為 28-1,即 255;TINYINT 有符號數的最大值為 27-1,即 127。其他類型的整數的取值范圍計算方法相同,
如下表所示。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
TINYINT | -128〜127 | 0 〜255 |
SMALLINT | -32768〜32767 | 0〜65535 |
MEDIUMINT | -8388608〜8388607 | 0〜16777215 |
INT (INTEGER) | -2147483648〜2147483647 | 0〜4294967295 |
BIGINT | -9223372036854775808〜9223372036854775807 | 0〜18446744073709551615 |
- 測試int數據類型
#用utf8mb4創建world庫
mysql> CREATE DATABASE world CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.00 sec)
#建表;
mysql> use world;
Database changed
mysql> CREATE TABLE t2(id int);
Query OK, 0 rows affected (0.17 sec)
#查看建表語句
mysql> show create table t2;
+-------+-----------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------+
| t2 | CREATE TABLE `t2` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+-----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
#查看表結構
mysql> desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
#插入數據
mysql> insert t2 values('-2147483647');
Query OK, 1 row affected (0.00 sec)
mysql> insert t2 values('123212321');
Query OK, 1 row affected (0.00 sec)
#插入的數據超出int類型范圍
mysql> insert t2 values('-2147483649');
ERROR 1264 (22003): Out of range value for column 'id' at row 1
#插入的數據超出int類型長度
mysql> insert t2 values('12321232112');
ERROR 1264 (22003): Out of range value for column 'id' at row 1
2.MySQL小數類型
MySQL 中使用浮點數和定點數來表示小數。
浮點類型有兩種,分別是單精度浮點數(FLOAT)和雙精度浮點數(DOUBLE);定點類型只有一種,就是 DECIMAL。
浮點類型和定點類型都可以用(M, D)來表示,其中M稱為精度,表示總共的位數;D稱為標度,表示小數的位數。
浮點數類型的取值范圍為 M(1~255)和 D(1~30,且不能大於 M-2),分別表示顯示寬度和小數位數。M 和 D 在 FLOAT 和DOUBLE 中是可選的,FLOAT 和 DOUBLE 類型將被保存為硬件所支持的最大精度。DECIMAL 的默認 D 值為 0、M 值為 10。
下表中列出了 MySQL 中的小數類型和存儲需求。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
FLOAT | 單精度浮點數 | 4 個字節 |
DOUBLE | 雙精度浮點數 | 8 個字節 |
DECIMAL (M, D) | 壓縮的“嚴格”定點數 | M+2 個字節 |
DECIMAL 類型不同於 FLOAT 和 DOUBLE。DOUBLE 實際上是以字符串的形式存放的,DECIMAL 可能的最大取值范圍與 DOUBLE 相同,但是有效的取值范圍由 M 和 D 決定。如果改變 M 而固定 D,則取值范圍將隨 M 的變大而變大。
從上表中可以看到,DECIMAL 的存儲空間並不是固定的,而由精度值 M 決定,占用 M+2 個字節。
FLOAT 類型的取值范圍如下:
- 有符號的取值范圍:-3.402823466E+38~-1.175494351E-38。
- 無符號的取值范圍:0 和 -1.175494351E-38~-3.402823466E+38。
DOUBLE 類型的取值范圍如下:
- 有符號的取值范圍:-1.7976931348623157E+308~-2.2250738585072014E-308。
- 無符號的取值范圍:0 和 -2.2250738585072014E-308~-1.7976931348623157E+308。
3.MySQL字符串類型
字符串類型用來存儲字符串數據,還可以存儲圖片和聲音的二進制數據。字符串可以區分或者不區分大小寫的串比較,還可以進行正則表達式的匹配查找。
MySQL 中的字符串類型有 CHAR、VARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、ENUM、SET 等。
下表中列出了 MySQL 中的字符串數據類型,括號中的M表示可以為其指定長度。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
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^24 |
LONGTEXT | 大的非二進制字符串 | L+4字節,在此,L<2^32 |
ENUM | 枚舉類型,只能有一個枚舉字符串值 | 1或2個字節,取決於枚舉值的數目 (最大值為65535) |
VARCHAR 和 TEXT 類型是變長類型,其存儲需求取決於列值的實際長度(在前面的表格中用 L 表示),而不是取決於類型的最大可能尺寸。
例如,一個 VARCHAR(10) 列能保存一個最大長度為 10 個字符的字符串,實際的存儲需要字符串的長度 L 加上一個字節以記錄字符串的長度。對於字符 “abcd”,L 是 4,而存儲要求 5 個字節。
- 測試char和varchar類型
#建表
mysql> CREATE TABLE t1(id int,name varchar(12));
Query OK, 0 rows affected (0.01 sec)
#插入數據
mysql> INSERT INTO t1 values('1','張三');
Query OK, 1 row affected (0.00 sec)
#字符超過數據類型的限制值
mysql> INSERT INTO t1 values('2','zhangsanlinsi');
ERROR 1406 (22001): Data too long for column 'name' at row 1
- 測試enum類型
#建表
mysql> CREATE TABLE t3(id int,name varchar(10),sex enum('man','girl'));
Query OK, 0 rows affected (0.32 sec)
#插入數據
mysql> INSERT INTO t3 values('1','張三','man');
Query OK, 1 row affected (0.00 sec)
#枚舉類型,只能插入指定的值,不能插入額外的值
mysql> INSERT INTO t3 values('1','李四','nan');
ERROR 1265 (01000): Data truncated for column 'sex' at row 1
- 建表測試
#建學生表
mysql> CREATE TABLE student(id int,name varchar(10),sex enum('男','女'),age tinyint,cometime datetime);
Query OK, 0 rows affected (0.01 sec)
#插入數據
mysql> INSERT INTO student values('1','張三','男','19',now());
Query OK, 1 row affected (0.01 sec)
#查看
mysql> select * from student;
+------+--------+------+------+---------------------+
| id | name | sex | age | cometime |
+------+--------+------+------+---------------------+
| 1 | 張三 | 男 | 19 | 2021-09-28 11:13:11 |
+------+--------+------+------+---------------------+
1 row in set (0.00 sec)
4.建表的數據屬性
not null: 非空
primary key: 主鍵(唯一且非空的)
auto_increment: 自增(此列必須是:primary key或者unique key)
unique key: 唯一鍵(單獨的唯一的)
default: 默認值
unsigned: 非負數
comment: 注釋
- 案例
#建表
mysql> CREATE TABLE student(
-> id int unsigned primary key auto_increment comment '學生id',
-> name varchar(10) not null comment '學會姓名',
-> sex enum('男','女') default '男' comment '性別',
-> age tinyint unsigned comment '年齡',
-> cometime datetime default now() comment '入學時間',
-> class varchar(12) not null comment '班級',
-> status enum('0','1') default 1 comment '狀態');
Query OK, 0 rows affected (0.39 sec)
#查看建表語句
mysql> show create table student;
| student | CREATE TABLE `student` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '學生id',
`name` varchar(10) NOT NULL COMMENT '學會姓名',
`sex` enum('男','女') DEFAULT '男' COMMENT '性別',
`age` tinyint(3) unsigned DEFAULT NULL COMMENT '年齡',
`cometime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '入學時間',
`class` varchar(12) NOT NULL COMMENT '班級',
`status` enum('0','1') DEFAULT '0' COMMENT '狀態',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
1 row in set (0.00 sec)
#插入數據
mysql> INSERT INTO student(name,class) values('張三','高二3班');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO student(name,class) values('李四','高二3班');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO student(name,class) values('林五','高二3班');
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO student(name,sex,age,class) values('楊雪','女','16','高二3班');
Query OK, 1 row affected (0.01 sec)
#查看數據
mysql> select * from student;
+----+--------+------+------+---------------------+------------+--------+
| id | name | sex | age | cometime | class | status |
+----+--------+------+------+---------------------+------------+--------+
| 1 | 張三 | 男 | NULL | 2021-09-28 11:26:42 | 高二3班 | 0 |
| 2 | 李四 | 男 | NULL | 2021-09-28 11:27:33 | 高二3班 | 0 |
| 3 | 林五 | 男 | NULL | 2021-09-28 11:28:11 | 高二3班 | 0 |
| 4 | 楊雪 | 女 | 16 | 2021-09-28 11:32:25 | 高二3班 | 0 |
+----+--------+------+------+---------------------+------------+--------+
4 rows in set (0.00 sec)
5.MySQL日期和時間
MySQL 中有多處表示日期的數據類型:YEAR、TIME、DATE、DTAETIME、TIMESTAMP。當只記錄年信息的時候,可以只使用 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 | 1980-01-01 00:00:01 UTC ~ 2040-01-19 03:14:07 UTC | 4 個字節 |
- 案例
mysql> create table d1(id int,name char, date1 date, date2 time, date3 datetime, date4 timestamp,date5 year);
Query OK, 0 rows affected (0.12 sec)
mysql> insert into d1 values (1, '1', '2021-09-09','12:12:12','2021-09-09','2021-09-09','2021');
Query OK, 1 row affected (0.00 sec)
mysql> select * from d1;
+------+------+------------+----------+---------------------+---------------------+-------+
| id | name | date1 | date2 | date3 | date4 | date5 |
+------+------+------------+----------+---------------------+---------------------+-------+
| 1 | 1 | 2021-09-09 | 12:12:12 | 2021-09-09 00:00:00 | 2021-09-09 00:00:00 | 2021 |
+------+------+------------+----------+---------------------+---------------------+-------+
1 row in set (0.00 sec)
datetime 和 timestamp 之間的區別?
1、兩者的存儲方式不一樣
對於TIMESTAMP,它把客戶端插入的時間從當前時區轉化為UTC(世界標准時間)進行存儲。查詢時,將其又轉化為客戶端當前時區進行返回。
對於DATETIME,不做任何改變,基本上是原樣輸入和輸出。
2、兩者所能存儲的時間范圍不一樣
timestamp所能存儲的時間范圍為:‘1970-01-01 00:00:01.000000’ 到 ‘2038-01-19 03:14:07.999999’。
datetime所能存儲的時間范圍為:‘1000-01-01 00:00:00.000000’ 到 ‘9999-12-31 23:59:59.999999’。
mysql> insert into t1 values (1, '1', '2021-09-09','12:12:12','2221-09-09 12','2221-09-09','2021');
1292 - Incorrect datetime value: '2221-09-09' for column 'date4' at row 1
6.MySQL二進制類型
MySQL 中的二進制字符串有 BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。
下表中列出了 MySQL 中的二進制數據類型,括號中的M表示可以為其指定長度。
類型名稱 | 說明 | 存儲需求 |
---|---|---|
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 |
- 案例
import pymysql
class BlobDataTestor:
def __init__(self):
self.conn = pymysql.connect(host='127.0.0.1', user='root', passwd='123456', db='db1', port=3306)
def __del__(self):
try:
self.conn.close()
except:
pass
def closedb(self):
self.conn.close()
def setup(self):
cursor = self.conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS `Dem_Picture` (
`ID` int(11) NOT NULL auto_increment,
`PicData` mediumblob,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
""")
def testRWBlobData(self):
# 讀取源圖片數據
f = open("D:\\1.jpg", "rb")
b = f.read()
f.close()
# 將圖片數據寫入表
cursor = self.conn.cursor()
cursor.execute("INSERT INTO Dem_Picture (PicData) VALUES (%s)", (pymysql.Binary(b)))
# self.conn.commit()
# 讀取表內圖片數據,並寫入硬盤文件
cursor.execute("SELECT PicData FROM Dem_Picture ORDER BY ID DESC limit 1")
d = cursor.fetchone()[0]
cursor.close()
f = open("D:\\1.jpg", "wb")
f.write(d)
f.close()
# 下面一句的作用是:運行本程序文件時執行什么操作
if __name__ == "__main__":
test = BlobDataTestor()
try:
test.setup()
test.testRWBlobData()
# test.teardown()
finally:
test.closedb()
7.MySQL系統變量
在 MySQL 數據庫,變量分為系統變量和用戶自定義變量。系統變量以 @@ 開頭,用戶自定義變量以 @ 開頭。
服務器維護着兩種系統變量,即全局變量(GLOBAL VARIABLES)和會話變量(SESSION VARIABLES)。全局變量影響 MySQL 服務的整體運行方式,會話變量影響具體客戶端連接的操作。
每一個客戶端成功連接服務器后,都會產生與之對應的會話。會話期間,MySQL 服務實例會在服務器內存中生成與該會話對應的會話變量,這些會話變量的初始值是全局變量值的拷貝。
查看系統變量
#查看MySQL中所有的全局變量信息
mysql> SHOW GLOBAL VARIABLES;
#查看與當前會話相關的所有會話變量以及全局變量。 其中SESSION關鍵字可以省略
mysql> SHOW SESSION VARIABLES;