[討論] 東區幻境MariaDB系列教學06-建立表 - 討論區

[討論] 東區幻境MariaDB系列教學06-建立表

文章瀏覽次數 657 文章回覆數 11

Dack

Dack圖像(預設)

2021-10-23 17:46:12

From:219.70.166.106

在之前觀念文及阿慶大大的文章中,我們知道資料庫的操作怎樣都脫離不了新增、修改、查詢及刪除(簡稱增刪改查)這四個動作。接續上一篇刪除表及查詢表的內容,我們緊接著要談談建立表。
由於本篇教學的內容稍微龐大了點,小弟會儘量以標題分段並講得簡單點,讓各位學習時較好理解且方便用螢幕報讀程式四處跳躍。另外感謝板上大大的回饋,小弟從善如流把資料庫名稱改成了「final_war」。

語法說明

要建立表時,我們會使用「CREATE TABLE」指令。基本語法長得像下面這樣。

CREATE TABLE `新表名`(
`欄位名稱1` 約束內容,
`欄位名稱2` 約束內容,
`欄位名稱3` 約束內容,
...
`最後一個欄位名稱` 約束內容
);

新表名及欄位名稱還比較好理解。新表名指的就是我們希望新表叫的名字,欄位名稱相當我們在Excel工作表首欄、首列會放的姓名啊性別啊等,欄列大標題的概念。不過MariaDB乃至各SQL資料庫是沒有列標題的,這點在理解上要特別注意。
至於約束內容是什麼意思呢?在前面的教學中我們好像有提過,一般藉SQL操作的資料庫系統常是所謂的關聯式資料庫。為了儘量確保增刪改查的速度及資料存儲時的嚴謹度,系統會要求各欄位必須規定好存入資料的型別、欄位在表中的特性等等。

範例演示

小弟知道再不舉例說明各位大概要睡著了。接續上次開發game的故事,我們好像剛把舊表殺完,現在呢!我們就開始來建一張叫players的新表。
這張新表裡要有幾個欄位,分別用來存資料在資料庫的編號、玩家姓名、使用武器、等級、血量、魔力量、攻擊力、防禦力、速度等訊息。而它們個別的約束,我們暫時先這樣規劃:

  • 資料編號:這個欄位的資料型別統一為整數,且要會自動做數值遞增填充。另外它也是這張表的主鍵,不允許留空。
  • 玩家名稱:存名字的欄位毫無疑問得用上字串類型別。考量到大家的名字各有長短,我們這邊就用20個單位的自動伸縮字串varchar。另外名稱在我們的系統是必須資料,我們同樣不許留空。
  • 使用武器:武器通常也都會是如槍、刀、法杖等的名稱,我們用10個單位的自動伸縮字串來存。另外由於玩家必須得持有武器,我們這欄也不許留空。
  • 等級:在我們的遊戲裡,規劃等級是從1等到100等,咱就用超小整數bit來存。另外玩家必定會要有等級的,本欄也不可留空。
  • 血量:我們估計玩家的血量會依等級增長而增長,最多應該會可以有幾千滴血。不過資料型別中沒有這個長度的項目可選用,我們就用個小整數smallint來存。另外玩家必定會有血量的,血量欄也不可留空。
  • 魔力量:魔力量就是玩家放招攻擊時會消耗的,我們規劃它跟血量一樣應該會有幾千單位。這邊直接採用跟血量相同的約束,為不可留空的smallint。
  • 攻擊力:隨玩家等級增長與配點,攻擊力也會隨之增強。我們預估它大約會有幾百幾千到幾萬,就用個smallint。另外玩家一定會有攻擊力的,不然開戰後總打不死別人可就糗了。攻擊力也不可留白。
  • 防禦力:防禦力跟攻擊力一樣,我們就也套用資料型別smallint。另外為避免玩家沒有防禦力被別人一打就掛,我們也不許本欄留空。
  • 速度:曾打game練等的大大應該知道,速度也是可隨等級或配點不斷提升的。在大亂鬥、出任務、組隊打副本中,誰速度快誰就有先發制人的場控本錢。我們同樣套用資料型別smallint且不可留白,不然開戰後連動都不能動只能被敵人砍可就完了。

照上述資料表的規劃,我們的players表建立指令會像下面這樣。

CREATE TABLE `players`(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(20) NOT NULL,
`weapon` VARCHAR(10) NOT NULL,
`LV` BIT NOT NULL,
`HP` SMALLINT NOT NULL,
`SP` SMALLINT NOT NULL,
`ATK` SMALLINT NOT NULL,
`DEF` SMALLINT NOT NULL,
`SPD` SMALLINT NOT NULL
);

執行結果會像下面這樣。

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.4.12-MariaDB mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> use `final_war`;
Database changed
MariaDB [final_war]> CREATE TABLE `players`(
    -> `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> `name` VARCHAR(20) NOT NULL,
    -> `weapon` VARCHAR(10) NOT NULL,
    -> `LV` BIT NOT NULL,
    -> `HP` SMALLINT NOT NULL,
    -> `SP` SMALLINT NOT NULL,
    -> `ATK` SMALLINT NOT NULL,
    -> `DEF` SMALLINT NOT NULL,
    -> `SPD` SMALLINT NOT NULL
    -> );
Query OK, 0 rows affected (0.032 sec)

MariaDB [final_war]>

看到「Query OK」後,表示我們的表已經建立成功了。我們來下指令確認一下。

MariaDB [final_war]> SHOW TABLES;
+---------------------+
| Tables_in_final_war |
+---------------------+
| players             |
+---------------------+
1 row in set (0.001 sec)

MariaDB [final_war]>

補充說明1:約束

看到上面的指令後,好多人大概要腦袋爆炸了。什麼是「AUTO_INCREMENT」?什麼是「NOT NULL」?什麼是「PRIMARY KEY」?亂七八糟的天啊!
別急別急,您先聽小弟說。之前有跟各位多次強調,以SQL操作的資料庫系統對資料的存儲要求是很嚴謹的,這個特性就體現在我們建表的這個時候。若改用流程來敘述,我們可以把語法看成:我要個新表叫巴樂巴樂巴樂。它的第一個欄位叫巴樂巴樂巴樂,存進來的資料型別只能是巴樂巴樂巴樂,且這些資料還要怎樣怎樣怎樣。下一個欄位跟下下個欄位都是如此,有自己接受的資料型別及其內資料的特性。在我們建表時這些規則都得先約法三章,而這些資料型別啊特性啊就是所謂的約束。各位可以稍做消化。
資料型別部分,相信小弟貼出範例語句時必定喚醒好多人對資料型別那篇教學的印象。對資料型別還不太熟悉的大大,練習時儘管倒帶回去瞧瞧喔!那上面範例中,有些看不懂的東西意思是什麼呢?且聽小弟說明。

主鍵

小弟相信板上的大大們應該跟小弟一樣,有一段將近20年的求學人生。各位想想,今天老師要找班上的某位同學,有什麼辦法可以直接簡單精準的找到他呢?學校教務處、學務處(舊稱訓導處)中的老師找學校裡的某位同學,怎樣可以簡單精準的找到這位同學呢?
為了解決以上問題,我們應該都被分配了個座號及學號。這樣所有同學都有個唯一的資訊了,必要時這個資訊還可以拿來決定順序。實在是太神了。
上面提到的座號及學號,指的就是MariaDB中的主鍵。它是一張表中絕對代表某筆資料的唯一值,我們通常會以整數(int)或大整數(bigint)來存儲它。當有跨表查詢、資料互相關聯的需要時,我們也會用上它。您看,這玩一兒是不是非常重要呢?
我們教學使用的MariaDB版本為10.4.12,它已經強制規定任何資料表一定要有一個套用主鍵約束的欄位,否則建表指令會發生錯誤並且回滾。

自動遞增

要講自動遞增「AUTO_INCREMENT」,得繼續說說剛剛的上學往事。假使班上原本有36位同學,如果有轉學生來的話他會是幾號座號呢?任何人應該都會覺得這什麼白吃問題,當然就37號啦!別說37號了,再多來個3位都會自動被分配38號、39號及40號好嗎?
大家會很直覺的這樣認為,是因為各位都聰明異常。會這樣說,是因為我們用的電腦實在是太笨太笨太笨了。我們會自己腦補37號、38號,MariaDB可不會。要知道沒有特別設定約束的話,每次我們插入資料可都要指定新資料在每個欄位中的值,包括主鍵primary key欄也是。資料量小的話還好,如果表中已有幾百萬筆資料,我們得先看最後一筆資料的主鍵值,然後再算算現在要插的資料應該要是幾號的主鍵值。這樣還不搞死DBA以及後端RD,看來他們上沒幾天班就得發瘋掛急診去了。
好在MariaDB有一個叫「AUTO_INCREMENT」的約束,用上了之後MariaDB就也有腦補座號的能力了。這樣以後插入資料我們寫好想插什麼,主鍵部分MariaDB會自動幫我們維護。您看,這是不是也挺神的!?

諾值null

跟各位解釋什麼是「NOT NULL」之前,小弟得先說說什麼是NULL(或稱諾值)。讓小弟繼續唬爛上面的學校往事。
好!包含轉學生在內的大家都有學號了,該來填寫通訊錄了。通訊錄裡大概就姓名、手機、電子信箱等等。不過不是大家都有手機啊!要知道地球上還是存在不少管小朋友管很嚴不給買手機電腦的恐龍家長。請問:這個時候該怎麼辦呢?
板上應該會有不少大大再次跳出嗆小弟問白吃問題,阿就留空就好了逆!是的,各位很聰明知道可以留空,可如果插入進資料庫時在SQL指令裡留空系統可就直接報錯回滾了。沒辦法,我們的電腦實在不聰明。
為了解決要留空的狀況,MariaDB資料型別裡有一個叫NULL的東西。這個英文單字出現在表中或指令中時表示的就是留白留空沒填任何資料的意思。如果您學過程式設計,它就是php的null、Java Script的null、Python的None。
知道了什麼是諾值之後,「NOT NULL」這個約束應該就難不倒各位了吧?是的,它的意思指的就是在填寫資料時,本欄位不許留空。要是插入資料的指令中有NULL值,系統會報錯回滾。
通常在建製資料庫時,小弟建議大家儘可能別用諾值。不然在使用count、sum等內建函式時可能會有不可預期的結果。使用查詢語句時,可能也會發生資料丟失的麻煩狀況。會有留白需要的欄位,我們可以用個像0之類的預設值。

補充說明2:好用指令

看完建表指令後,初次接觸的大大應該會有建表指令好麻煩的心得。其實如果您有了點資料庫管理經驗,建表或改表對您來說仍然會是不容易的。甚至文件沒寫好、團隊沒溝通好,當初表是怎麼建立起來的大家可能都忘了。這個時候怎麼辦呢!?
還好開發MariaDB的大牛們有幫我們想到這個問題,此時來條「SHOW CREATE TABLE 表名」或「DESC 表名」指令就ok啦!
空口無感,我們立刻用剛建的players表來試試。執行結果會像下面這樣。

MariaDB [final_war]> SHOW CREATE TABLE `players`;
+---------+---------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------------------------+
| Table   | Create Table

                                                     |
+---------+---------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------------------------+
| players | CREATE TABLE `players` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `weapon` varchar(10) NOT NULL,
  `LV` bit(1) NOT NULL,
  `HP` smallint(6) NOT NULL,
  `SP` smallint(6) NOT NULL,
  `ATK` smallint(6) NOT NULL,
  `DEF` smallint(6) NOT NULL,
  `SPD` smallint(6) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+---------+---------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------------------------+
1 row in set (0.007 sec)

MariaDB [final_war]> DESC `players`;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| id     | int(11)     | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20) | NO   |     | NULL    |                |
| weapon | varchar(10) | NO   |     | NULL    |                |
| LV     | bit(1)      | NO   |     | NULL    |                |
| HP     | smallint(6) | NO   |     | NULL    |                |
| SP     | smallint(6) | NO   |     | NULL    |                |
| ATK    | smallint(6) | NO   |     | NULL    |                |
| DEF    | smallint(6) | NO   |     | NULL    |                |
| SPD    | smallint(6) | NO   |     | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
9 rows in set (0.023 sec)

MariaDB [final_war]>

蘿蔔青菜,各有所愛。各位大大覺得哪個指令的產生結果看起來爽就儘管用北!

結語

到這邊我們就把資料庫建表的基本重點帶完了。由於內容稍微多了點,有在追本教學的大大若您是第一次接觸可千萬要自己親自下下看指令唷!這種技術性的知能是絕對無法用看的就懂的,必須要動手實作才會真的學進去。
那麼在下一篇教學裡,我們就繼續說說系統需求改變了得改資料表了,這個時候該怎麼辦。
※最後更新時間:2021-10-23 17:50:48 From:219.70.166.106 By:Dack
※最後更新時間:2021-10-23 17:52:48 From:219.70.166.106 By:Dack

留言

#1

阿慶

阿慶圖像

2021-10-23 20:42:58

From:219.91.112.100

一班來說,如果指令很長,在括號換行後都會內縮兩隔來稍微排版一下,就像 SHOW CREATE TABLE `players`; 顯示的一樣

CREATE TABLE `players` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `weapon` varchar(10) NOT NULL,
  `LV` bit(1) NOT NULL,
  `HP` smallint(6) NOT NULL,
  `SP` smallint(6) NOT NULL,
  `ATK` smallint(6) NOT NULL,
  `DEF` smallint(6) NOT NULL,
  `SPD` smallint(6) NOT NULL,
  PRIMARY KEY (`id`)
);

其實把 primary key 指令寫在下面,或寫在欄位約束中的效果一樣。
另外補充一個我覺得很重要的語法是 comment (註解)
把欄位加上註解,開發者也比較好理解,就像這樣:

CREATE TABLE `players` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL COMMENT '玩家名稱',
  `weapon` varchar(10) NOT NULL COMMENT '使用武器',
  `LV` bit(1) NOT NULL COMMENT '等級',
  `HP` smallint(6) NOT NULL COMMENT '血量',
  `SP` smallint(6) NOT NULL COMMENT '魔力量',
  `ATK` smallint(6) NOT NULL COMMENT '攻擊力',
  `DEF` smallint(6) NOT NULL COMMENT '防禦力',
  `SPD` smallint(6) NOT NULL COMMENT '速度,',
  PRIMARY KEY (`id`)
);

#2

阿慶

阿慶圖像

2021-10-23 20:45:16

From:219.91.112.100

另外,等級的欄位類型是否有誤?

  `LV` bit(1) NOT NULL,

bit只能存0跟1,預設是 bit(1) 就只能存0或1
bit(2) 就只能存 00, 01, 10, 11 四種
參考這篇文章

#3

Maxe

Maxe圖像(預設)

2021-10-24 14:20:05

From:36.230.10.59

  1. 雖說我已經學過了,但這種教學文看來還是蠻有趣的,可能因為我個人比較喜歡拿現實可能發生的狀況來舉例說明一種觀念的方式吧。
  2. 現在通常不會用這麼小的單位了,最小通常使用 int 與 varchar 且都不指定長度,畢竟現在不向當時創立 SQL 的時代,空間非常的寶貴,統一字串與數字類型以及長度,除了所有語法和欄位相同,還可避免大部分資料長度太小的問題。

#4

阿慶

阿慶圖像

2021-10-24 16:11:55

From:219.91.112.100

我還是會看狀況耶
假如真有儲存年齡的欄位,我可能還是繼續用 smallint 或 tinyint
因為可以完全確定人類了年齡不會超過上限
雖然說不用擔心儲存空間問題
但畢竟不同資料類型有固定的儲存單位長度
就還是覺得也沒必要浪費那個根本永遠用不到的空間來儲存資料
比如同樣是 tinyint(2), smallint(2), mediaint(2), bigint(2)
存進去的數字需要耗費的bits還是不一樣

#5

特種兵

特種兵圖像(預設)

2021-10-25 10:50:45

From:211.23.21.202

像是給 bool 都會自動變成較大的 tinyint 就可以知道現在的趨勢囉

#6

阿慶

阿慶圖像

2021-10-25 11:52:55

From:211.23.21.202

欄位設定 boolean 或 bool 就會給 tinyint(1)
因為 tinyint 是 0 到 127
剛好給 LV 用,很夠了。

#7

Dack

Dack圖像(預設)

2021-10-25 21:39:02

From:219.70.166.106

握的天啊!小弟學藝不精
測試後發現確實以前1位元組大小的bit已只給存0跟1了
硬插的話MariaDB_v10.1.13還會給過,
小弟預設的教學版本10.4.12直接報錯QQ

#8

Dack

Dack圖像(預設)

2021-10-25 21:41:29

From:219.70.166.106

真糟糕,沒事幹嘛跟Microsoft SQL看齊!?
專門用bit存boolean的資料庫系統不就Microsoft SQL!?(冏)

#9

阿慶

阿慶圖像

2021-10-26 10:06:53

From:211.23.21.202

建議還是把文章改一下為好

#10

貓貓蟲

貓貓蟲圖像

2021-10-26 13:55:38

From:36.231.139.124

其實MSSQL 市占率還滿高的 MySQL 優點就是免費 但是效能來說MSSQL和oracle稍微好一點

說到bit 其實電腦底層只看得懂0和1 所以bool相當於 0 = false 和 1 = true

還有差別就是儲存所佔的記憶體大小 但現代人很少去記了

想到大學時候的必修資料庫系統就很頭痛XD

前面CRUD基本觀念弄好後 後面才是考驗

#11

Maxe

Maxe圖像(預設)

2021-10-26 14:05:16

From:211.23.21.202

所以實際開始使用之後,就能體會以前上課的時候,老師為何前面不停的教各種各樣複雜的查詢,而最後才教增刪改表,以及使用者權限等等。