Files
build-web-application-with-…/zh-tw/05.2.md
2019-06-22 23:41:28 +08:00

142 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 5.2 使用 MySQL 資料庫
目前 Internet 上流行的網站構架方式是 LAMP其中的 M 即 MySQL, 作為資料庫MySQL 以免費、開源、使用方便為優勢成為了很多 Web 開發的後端資料庫儲存引擎。
## MySQL 驅動
Go 中支援 MySQL 的驅動目前比較多,有如下幾種,有些是支援 database/sql 標準,而有些是採用了自己的實現介面,常用的有如下幾種:
- https://github.com/go-sql-driver/mysql 支援 database/sql全部採用 go 寫。
- https://github.com/ziutek/mymysql 支援 database/sql也支援自訂的介面全部採用 go 寫。
- https://github.com/Philio/GoMySQL 不支援 database/sql自訂介面全部採用 go 寫。
接下來的例子我主要以第一個驅動為例(我目前專案中也是採用它來驅動),也推薦大家採用它,主要理由:
- 這個驅動比較新,維護的比較好
- 完全支援 database/sql 介面
- 支援 keepalive保持長連線雖然 [ 星星](http://www.mikespook.com)fork 的 mymysql 也支援 keepalive但不是執行緒安全的這個從底層就支援了 keepalive。
## 範例程式碼
接下來的幾個小節裡面我們都將採用同一個資料庫表結構:資料庫 test使用者表 userinfo關聯使用者資訊表 userdetail。
```sql
CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NULL DEFAULT NULL,
`department` VARCHAR(64) NULL DEFAULT NULL,
`created` DATE NULL DEFAULT NULL,
PRIMARY KEY (`uid`)
);
CREATE TABLE `userdetail` (
`uid` INT(10) NOT NULL DEFAULT '0',
`intro` TEXT NULL,
`profile` TEXT NULL,
PRIMARY KEY (`uid`)
)
```
如下範例將示範如何使用 database/sql 介面對資料庫表進行增刪改查操作
```Go
package main
import (
"database/sql"
"fmt"
//"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "astaxie:astaxie@/test?charset=utf8")
checkErr(err)
//插入資料
stmt, err := db.Prepare("INSERT userinfo SET username=?,department=?,created=?")
checkErr(err)
res, err := stmt.Exec("astaxie", "研發部門", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
//更新資料
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
//查詢資料
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
//刪除資料
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
透過上面的程式碼我們可以看出Go 操作 Mysql 資料庫是很方便的。
關鍵的幾個函式我解釋一下:
sql.Open()函式用來開啟一個註冊過的資料庫驅動go-sql-driver 中註冊了 mysql 這個資料庫驅動,第二個參數是 DSN(Data Source Name),它是 go-sql-driver 定義的一些資料庫連結和配置資訊。它支援如下格式:
user@unix(/path/to/socket)/dbname?charset=utf8
user:password@tcp(localhost:5555)/dbname?charset=utf8
user:password@/dbname
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname
db.Prepare()函式用來回傳準備要執行的 sql 操作,然後回傳準備完畢的執行狀態。
db.Query()函式用來直接執行 Sql 回傳 Rows 結果。
stmt.Exec()函式用來執行 stmt 準備好的 SQL 語句
我們可以看到我們傳入的參數都是 =? 對應的資料,這樣做的方式可以一定程度上防止 SQL 注入。
## links
* [目錄](<preface.md>)
* 上一節:[database/sql 介面](<05.1.md>)
* 下一節:[使用 SQLite 資料庫](<05.3.md>)