# Day27 Golang MySQL 我的資料庫 在成功連上SQL資料庫後, 我們可以在一開始先寫好`init()` 初始化資料庫的連線。 ```go var db *sql.DB // 與DB連線。 init() 初始化,時間點比 main() 更早。 func init() { dbConnect, err := sql.Open( "mysql", "root:root@tcp(127.0.0.1:3306)/", ) if err != nil { log.Fatalln(err) } err = dbConnect.Ping() if err != nil { log.Fatalln(err) } db = dbConnect // 用全域變數接 db.SetMaxOpenConns(10) // 可設置最大DB連線數,設<=0則無上限(連線分成 in-Use正在執行任務 及 idle執行完成後的閒置 兩種) db.SetMaxIdleConns(10) // 設置最大idle閒置連線數。 // 更多用法可以 進 sql.DBStats{}、sql.DB{} 裡面看 } ``` --- Golang中的`*sql.DB`這一物件抽了一層介面出來, 日後等子孫們不想使用`MySQL`時, 只需更換 [**driver**](https://github.com/golang/go/wiki/SQLDrivers) 即可。 若在使用上時出現 `Error 1046 no database selected`的錯誤, 表示沒有指定資料庫,可改成以下指定該資料庫來連線。 ```go db, err := sql.Open( "mysql", "root:root@tcp(127.0.0.1:3306)/dbName", ) ``` 或者用SQL語法的`USE`來指定資料庫。 ```go db.Exec("USE `school`") ``` ## 建立、刪除資料庫 下`SQL語法關鍵字`時,通常會使用`全大寫`(雖然小寫也可以,但大寫較容易區分) #### 【建立資料庫】Create Database ```go db.Exec("CREATE DATABASE `test1`") ``` 加了`IF NOT EXISTS `之後,會先檢查要建立的物件存不存在,如果不存在再執行建立。 否則 如果無法建立物件時(未成功執行),`err` 會回傳 `Error 1007: Can't create database '..'; database exists`。 ```go _, err := db.Exec("CREATE DATABASE IF NOT EXISTS `test1`") ``` #### 【刪除資料庫】Detele Database 同樣能先判斷`IF EXISTS `看欲刪除的物件存不存在。 ```go db.Exec("DROP DATABASE IF EXISTS `test1`") ``` 此外,SQL語法可以用變數代入、拉出來寫成一個`func` ```go func main() { createDb("`school`") // 比較好的習慣會使用 `` 反引號(重音號)來區隔名字 // deleteDb("`school`") } func createDb(dbName string) { _, err := db.Exec("CREATE DATABASE IF NOT EXISTS " + dbName + ";") if err != nil { log.Fatalln(err) } fmt.Print(err) } func deleteDb(dbName string) { _, err := db.Exec("DROP DATABASE IF EXISTS " + dbName + ";") if err != nil { log.Fatalln(err) } } ``` ## 用Goland IDE與資料庫連線 新增MySQL ![新增MySQL](https://i.imgur.com/uIXAhna.png) 輸入帳號與密碼 ![輸入帳號密碼](https://i.imgur.com/jYVCEh2.png) 切換到Scheme頁面 ![Scheme](https://i.imgur.com/pxEbqy5.png) ## 建立、刪除表格 資料表中每個欄位都必須要有類型、並設置Byte長度,才能存放該型別的資料。 常見的變數類型有: * `INT`(每長度 4 bytes): 數字,存放整數資料 * `CHAR`(每長度 1 byte): 固定長度字串 * `VARCHAR`: 可變長度字串,用多少長度就多少 * `TEXT`: 文字敘述、說明(長度較長) * `DATE`: 時間格式 * `TIMESTAMP`: 時間戳 #### 【建立資料表】Create Table 建立student的表格 ```go func createTable1() { // SQL: CREATE TABLE IF NOT EXISTS `school.student` // 初始化Table 沒給任何欄位時,會出現 `A table must have at least 1 column` 的錯誤 _, err := db.Exec("CREATE TABLE IF NOT EXISTS `school`.`student`(`name` VARCHAR (10))") if err != nil { log.Fatalln(err) } // 或者用 USE 來指定該資料庫 // db.Exec("USE `school`") // _, err := db.Exec("CREATE TABLE IF NOT EXISTS `student`(`name` VARCHAR (10))") } ``` 再建立一個teacher的表格,這次存放`name(VARCHAR)`、`age(INT)`兩個欄位, 並且設置name為`PRIMARY KEY`(唯一不重複的識別ID)。 表單目前內是沒任何內容的。 ![teacher表格](https://i.imgur.com/TKaHMIV.png) ```go _, err := db.Exec("CREATE TABLE IF NOT EXISTS `school`.`teacher`(`name` VARCHAR (10) PRIMARY KEY, `age` INT (1))") ``` #### 【刪除表格】Detele Table ```go _, err := db.Exec("DROP TABLE IF EXISTS `school`.`student`") ``` #### 【更改欄位】Alter Table 替 student的Table加上 `id` 這個會自動遞增(AUTO_INCREMENT)的欄位,並設定成主鍵(數字遞增的特性:唯一、不重複,且Not Null)。 ```go _, err := db.Exec("ALTER TABLE `school`.`student` ADD `id` INT AUTO_INCREMENT PRIMARY KEY;") ``` ![Alter AUTO_INCREMENT](https://i.imgur.com/9gXCTh1.png) ## 反引號 vs 雙引號 `資料表、欄位` 會用反引號\` \` 包起來,以防與SQL語法關鍵字搞混。 而雙引號" "常用在字串的組合、組成SQL語法傳遞給資料庫。