前言
????????上篇文章小編講述了關于MySQL表的DDL操作,在那里我多次使用了MySQL的數據類型,但是我并沒有去講述MySQL的數據類型,想必各位讀者已經很好奇MySQL的數據類型都有什么了,今天這篇文章我將會詳細的去講述MySQL的數據類型,希望可以為各位解惑。
1.數據類型以及分類
????????在詳細說明每個數據類型之間,我先來讓各位看一看MySQL中有幾種數據類型以及它們的分類(只截取了比較重要的一部分,還有一些我并沒有展示出來,各位讀者感興趣可以去官方網站自行學習)。
????????上面的類型有很多種,不過很多我們在學C語言的時候就已經感到很熟悉了,就比如數值類型中的int類型,它就是我們在C語言學習的整型,這點MySQL和C語言還是一樣的,當然MySQL和C語言還是有差異的地方的,就比如文本類型的中的char,在C語言中,它代表的是字符類型,也就是'A'、'B'等等的字符;而它在MySQL代表的事一個固定長度的字符串,各位千萬不要把它的定義和C語言的混為一談。下面我將從數值類型、文本。二進制類型。時間日類類型以及string類型這幾個方面,詳細講述MySQL的數據類型以及它和編程語言的異同,幫各位避開這些認知陷阱。
2.數值類型
????????上表就是我想要講述的數值類型,此時我先簡單的帶著各位看下這個表,這個表大多數的都是和整型int相關的,之所以放到一起是因為我認為它們是有相似性的,當我講述完其中幾個以后,剩下的類型各位就可以自己去領悟了(絕對不是因為我偷懶),下面我來分別講述一下這幾種類型。
2.1.tinyint類型
????????通過上表,我們可以簡單的知道它所代表的范圍是-128到127,因為它是占據一個字節,一個字節是八個比特位,所以它可以表示2^8也就是256個不同的值(從00000000到11111111);在計算機用補碼表示有符號整數時,最高位為0表示正數(0到127),最高位為1表示負數(-1到-128),其中 10000000 這個特殊編碼被定義為 -128,因此整體范圍就是 -128 到 127。因此它的范圍就是-128到127,可能有些讀者好奇它的范圍真的卡的那么嚴嗎?不要急,下面我簡單的進行范圍的測試(里面涉及到表的DML的知識,這是我下一篇文章要講述的,各位讀者可以先期待著)。
1.范圍檢測
????????此時我簡單的建立一個表,這個表的名字是student,里面涉及學生的學號以及姓名(就這么簡單就好了),下面是實現的代碼(建議各位讀者可以自行實現,之后再來和我的進行對照)。
create table student(name varchar(20) #代表的是姓名id tinyint
);#代表表的創建
插入邊界值
????????此時我們可以先插入最大值試一試,因為我還沒有講述表的插入操作,所以各位知曉我的目的是把一個學生姓名為張三的,id為127;
insert into student values('張三',127);
????????此時可以看出插入成功了,下面我們查詢我們插入的數據。同樣的,這涉及到表的查詢操作,我依舊不解釋。
select * from student;
????????下面我們插入最小值試一下,插入一個姓名為李四,id為-128(有點奇怪)的數據。
insert into student values('李四',-128);
????????此時數據依然是插入成功了,我們依舊可以查詢插入的數據。
select * from student;
插入一個不在范圍內的值
????????此時我試著插入一個姓名為小禾,id為128的數據。
insert into student values('小禾',128);
????????正如我們所見,嘗試插入超出 tinyint
范圍(-128 到 127)的值導致了錯誤。這驗證了整型的一個重要規則:當插入的值超出該整型定義的數值范圍時,數據庫系統會報錯。 其他整型(如 smallint
, int
, bigint
)的核心機制與此完全相同,區別僅在于它們能容納的范圍大小不同。既然原理一致,我們就不再逐一贅述。接下來,讓我們把目光轉向另一種重要的數據類型——小數類型。
2.2.小數類型
1.float類型
語法:
float[(m, d)] [unsigned] : M指定顯示長度,d指定小數位數,占用空間4個字節
????????與整型不同,float
類型在定義時需要指定兩個參數,語法為 float(M, D)
。下面我來詳細解釋這兩個參數的含義和使用規則:
參數解析
-
M
(總精度/顯示寬度):代表該浮點數總共可以顯示的最大數字位數(包括整數部分和小數部分的所有數字字符,不包括小數點本身和符號位)。-
例如:
128.1
包含數字1
,2
,8
,1
→ 總共 4 位數字 -
12.81
包含數字1
,2
,8
,1
→ 總共 4 位數字
-
-
D
(小數位數/標度):代表該浮點數小數點后允許的最大位數。-
例如:
128.1
的小數點后有 1 位數字 (1
) -
12.81
的小數點后有 2 位數字 (81
)
-
關鍵特性
-
M
和D
定義的是上限值[敲重點]:實際存儲的數字位數可以少于M
,小數位數可以少于D
,但不能超過 -
float
存儲的是近似值而非精確值(這一點與整型完全不同) -
數值范圍極大(約 ±10^38),但精度有限(約7位有效數字)
實例演示
????????下面我通過一個建表實例,展示 float
類型的使用規則:
1. 創建測試表
-- 創建包含float(4,2)類型的測試表
CREATE TABLE product (name VARCHAR(20), ?-- 產品名稱price FLOAT(4,2) ? -- 價格(總位數不超過4,小數位不超過2)
);
2. 插入合法數據
-- 有效數據:總位數4,小數位2
INSERT INTO product VALUES ('鉛筆', 12.34); ?-- 數字:1,2,3,4 → 4位
?
-- 有效數據:總位數3<4,小數位1<2
INSERT INTO product VALUES ('橡皮', 8.5); ? ?-- 數字:8,5 → 2位(總位數不足)
?
-- 有效數據:邊界值測試
INSERT INTO product VALUES ('筆記本', 99.99); -- 數字:9,9,9,9 → 4位
3. 插入非法數據(驗證限制)
-- 超出總位數限制(5>4)
INSERT INTO product VALUES ('鋼筆', 100.00);
-- 錯誤:總位數5 (1,0,0,0,0) > 4
?
-- 超出小數位限制(3>2)
INSERT INTO product VALUES ('尺子', 12.345);
-- 錯誤:小數位數3 > 2
?
-- 同時違反兩項規則
INSERT INTO product VALUES ('文具盒', 123.45);
-- 錯誤:總位數5>4 且 小數位2>2?(實際D=2允許2位小數,但總位數超限)
4. 查詢驗證
SELECT * FROM product;
????????執行結果應顯示:
+-----------+-------+
| name ? ? ?| price |
+-----------+-------+
| 鉛筆 ? ? ?| 12.34 |
| 橡皮 ? ? ?| ?8.50 | -- 自動補零顯示
| 筆記本 ? ?| 99.99 |
+-----------+-------+
重要注意事項
-
精度陷阱:
float
存儲的是近似值,對精度要求高的場景(如金融計算)應使用decimal
類型-- 精度問題示例 INSERT INTO product VALUES ('計算器', 1.0 / 3.0); -- 存儲為0.3333333432674408
-
參數可選性:可以不指定
(M,D)
,此時使用系統默認精度CREATE TABLE temp (value FLOAT); -- 不指定參數
-
顯示補充:當實際小數位不足時,查詢結果會自動補零顯示(如
8.5
顯示為8.50
)
????????通過以上實例,各位讀者可以清晰看到:float(4,2)
可以存儲 12.34
(剛好滿位)、8.5
(位數不足)和 99.99
(邊界值),但拒絕 100.00
(總位數超限)和 12.345
(小數位超限)。這種靈活的位數控制使 float
成為處理科學計算和大范圍數值的理想選擇,但切記它的近似特性可能帶來精度問題!
2.decimal
????????在金融計算、貨幣交易等需要絕對精度的場景中,decimal
類型是 MySQL 中最值得信賴的數據類型。與 float
的近似存儲不同,decimal
以固定精度存儲數值,確保計算結果完全精確,避免浮點數常見的舍入誤差問題。
核心特性解析
-
精確存儲機制:
-
將數值拆分為整數部分和小數部分分別存儲
-
采用定點數表示法,而非浮點數的科學計數法
-
完全避免二進制浮點數的精度損失問題
-
-
參數定義語法:
decimal(M, D)
-
M
(總精度):總位數(整數部分+小數部分),范圍 1-65 -
D
(小數位數):小數點后的位數,范圍 0-30 且 D ≤ M -
示例:
decimal(5,2)
可存儲123.45
(5位總數,2位小數)
-
-
存儲空間優化:
-
每9位數字占用4字節
-
存儲空間 = 整數部分空間 + 小數部分空間
-
示例:
decimal(18,9)
需要 9字節(每部分9位,各需4字節,共8字節?實際需要9字節)
-
金融級精度演示
創建賬戶表
CREATE TABLE bank_account (account_id INT PRIMARY KEY,owner_name VARCHAR(50),-- 總位數10位,其中2位小數(最大存儲:99,999,999.99)balance DECIMAL(10,2) ?
);
精確交易操作
-- 初始存款:精確存儲
INSERT INTO bank_account VALUES (1001, '張三', 10000.00);
?
-- 存款利息計算(年化3.5%,按日計息)
UPDATE bank_account
SET balance = balance * (1 + 0.035/365)
WHERE account_id = 1001;
?
-- 查詢結果(顯示精確計算結果)
SELECT * FROM bank_account;
????????輸出結果:
+------------+------------+--------------+
| account_id | owner_name | balance ? ? ?|
+------------+------------+--------------+
| ? ? ? 1001 | 張三 ? ? ? | 10000.958904 | -- 精確到小數點后6位
+------------+------------+--------------+
邊界值測試
-- 最大允許值(符合decimal(10,2))
INSERT INTO bank_account VALUES (1002, '李四', 99999999.99); -- 成功
?
-- 超出整數部分限制
INSERT INTO bank_account VALUES (1003, '王五', 100000000.00);
-- 錯誤:總位數超過10位(整數部分8位+小數2位=10位,100000000是9位整數)
?
-- 超出小數部分限制
UPDATE bank_account SET balance = 12345.678 WHERE account_id = 1001;
-- 錯誤:小數位3位 > 2位(自動四舍五入為12345.68)
decimal vs float 關鍵對比
特性 | decimal | float |
---|---|---|
精度保證 | 精確存儲(無誤差) | 近似存儲(有誤差) |
適用場景 | 財務計算、貨幣金額 | 科學測量、大范圍值 |
計算速度 | 較慢(精確計算開銷大) | 較快 |
存儲空間 | 較大(每9位需4字節) | 固定4字節 |
數值范圍 | 受M限制(最大10^65) | 極大(約±10^38) |
小數處理 | 精確舍入 | 二進制近似 |
重要注意事項
-
四舍五入規則:
-- 顯示指定精度時的自動舍入 INSERT INTO bank_account VALUES (1004, '趙六', 123.456); -- 實際存儲:123.46(小數部分自動四舍五入到2位)
-
默認精度設置:
-- 不指定參數時使用默認精度 CREATE TABLE tax_records (amount DECIMAL ?-- 等效于decimal(10,0) );
-
零值處理:
-- 小數位不足時自動補零 INSERT INTO bank_account VALUES (1005, '錢七', 500.5); SELECT balance FROM bank_account WHERE account_id = 1005; -- 顯示:500.50
-
計算精度擴展:
-- 計算過程中會保留最大精度 SELECT balance * 1.123456789 FROM bank_account; -- 結果將包含更多小數位
最佳實踐建議
-
財務系統必選:所有貨幣金額、稅率計算必須使用
decimal
-
合理設置精度:
-
貨幣:
decimal(19,4)
(兼容國際標準) -
百分比:
decimal(5,2)
(存儲0.00~999.99%) -
科學測量:根據儀器精度確定
-
-
警惕隱式轉換:
-- 混合類型計算可能導致精度丟失 SELECT balance + 123.456 FROM bank_account; -- 結果會被截斷
-
性能權衡:高并發系統需評估精確計算帶來的性能開銷
黃金法則:當需要精確計算時選擇
decimal
,當可接受近似值時選擇float
。在金融、電商、賬務系統中,decimal
的精度保障遠重于其性能開銷。
????????通過 decimal
類型,MySQL 為開發者提供了符合銀行級標準的數值存儲方案。它的精確性特性使其成為處理貨幣金額、財務計算和任何需要完美精度的商業場景的首選工具。
????????以上就是我想要講述的MySQL中關于數值類型的定義,各位目前想要掌握它們,我的建議是在后續我進行DML的時候,跟著我一起敲代碼。那么就可以更快的去掌握這些知識,畢竟比起死記硬背,動用往往是記憶最好的方式,下面我要進行字符串類型的講述了。
3.字符串類型
3.1.char類型
1.語法
????????char類型相比數值類型,用法就比較簡單了,下面先來看看它的語法。
char(L): 固定長度字符串,L是可以存儲的長度,單位為字符,最大長度值可以為255
????????這個語法接受起來就比上面的float要簡單很多,我們僅需知道,此時char括號里面的數字代表的事可以存儲的字符的長度,記住,說的是字符的長度,而不是字節的長度,就比如,'你好'就代表兩個字符,'A'代表一個字符等等,下面我就通過一個例子來告訴各位它的用法。
2.用法
????????下面,我繼續從student表里面添加一列,充當家庭住址(place),其用法如下(此時設計表的增的操作,我上篇文章已經介紹了,忘記的讀者自行去看我上篇文章)。
alter table student add place char(20);
????????此時,即可看到表里新增的一列。
????????下面我往里面插入20個字符(測試閾值),可以看到插入是成功的。
????????但是當我插入21個字符的時候,系統就會報錯了,這就可以看出MySQL對于數據范圍控制的嚴謹性。
3.2.varchar類型
1.語法
varchar(L): 可變長度字符串,L表示字符長度,最大長度65535個字節
? ?varchar
也是一種字符串類型。你可能會問,既然已有 char
類型,為何還需要 varchar
?關鍵在于它們的存儲機制不同。
????????如前所述,char
是固定長度的字符串。例如,當你定義一個長度為 20 個字符的 char
字段時,即使你只插入了一個字符的數據,數據庫依然會分配完整的 20 個字符空間。
????????而 varchar
則是可變長度的字符串。在同樣的場景下(定義長度為 20,但僅插入 1 個字符),varchar
類型只會分配實際所需的空間,即僅占用 1 個字符的空間。
2.用法
????????因為它和char類型的字符串其實很像(只不過是一個靜態一個動態),所以此時我就不寫用法了(偷懶一下)。
3.3.char類型和varchar類型的比較
1.比較
????????此時,我們可以通過一張表格來看出這兩個類型的區別。
????????從這張圖可以看出這倆的區別,我剛才也說了,varchar是變長的字符串,所以它的大小是根據當時字符大小來決定的,而char類型是定長字符串,無論輸入了多少個字符,只要在和合理的范圍內,它們的大小是確定的。
2.如何選擇這兩種類型
-
如果數據確定長度都一樣,就使用定長(char),比如:身份證,手機號,md5 【但是我一般也是用varchar】。
-
如果數據長度有變化,就使用變長(varchar), 比如:名字,地址,但是你要保證最長的能存的進去 。
-
定長的磁盤空間比較浪費,但是效率高。
-
變長的磁盤空間比較節省,但是效率低。
-
定長的意義是,直接開辟好對應的空間
-
變長的意義是,在不超過自定義范圍的情況下,用多少,開辟多少。
4.日期和時間類型
1.相關函數
????????常用的日期有如下三個:
-
date:日期。‘yyyy-mm-dd’,占用三個字節。
-
datetime:時間日期格式,‘yyyy-mm-dd HH:ii:ss’表示范圍從1000到9999,占用八個字節。
-
timestamp:時間戳(比較常見的概念,之前我在C語言也使用過它),從1970年開始的yyyy-mm-dd HH:ii:ss格式和datetime完全一致,占用四個字節。
2.使用方法
1.date函數
????????我們先來簡單的使用一下date函數,此時我們往student表里新插入一列,bir代表學生的出生日期。
alter table student add bir date;
????????往里面插入一個元素,這里我就拿我自己的出生日期作為要插入的元素,因為這里面設計到了DML的知識,所以各位先不用記住它的用法。
insert into student(bir) values('2005-2-17');
????????檢查一下此時是否插入成功。
2.datetime
????????下面我們繼續插入新的一列,此時就用enr來表示,代表著入學的年份。
alter table student add enr datetime;
????????往里面插入隨機一個元素,記住用年月日時分秒來表示。
insert into student(enr) values('2023-9-3-12:32:12');
????????此時就代表插入成功,看一下student里面存放的元素。
3.timestamp
????????由于其用法和datetime類似,這里我就不多介紹了(后續我可能重新補充一下)。
5.小結
????????此時文章到這里就結束了,這篇文章寫的比較趕,但也不能說是很趕,因為我前后大約四天才寫完的,所以文章可能讀起來不是那么流暢,這里我先說一聲抱歉了,出現這樣的原因是因為我這周是期末周,大多時間都是在‘預習’知識,信號和系統真的很痛苦,我是真的不太喜歡這門課,導致我學起來特別的難受,到現在我的腦子還是比較混亂的。本文其實還有集合類型沒有講述,但是由于我很少使用它,所以我就先不寫了,后期我可能會補充一點。在最后的hike,祝各位同時處在期末周的大學生們取得一個好成績,祝各位已經放假的大學生們暑假快樂,祝所有人身體健康,每天都快快樂樂的,我是忘梓,一個默默無聞的小博主,各位大佬們,我們下篇文章見啦!