Files
build-web-application-with-…/zh-tw/05.4.md
2019-02-26 01:40:54 +08:00

136 lines
3.8 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.4 使用PostgreSQL資料庫
PostgreSQL 是一個自由的物件-關係資料庫伺服器(資料庫管理系統),它在靈活的 BSD-風格許可證下發行。它提供了相對其他開放原始碼資料庫系統(比如 MySQL 和 Firebird),和對專有系統比如 Oracle、Sybase、IBM 的 DB2 和 Microsoft SQL Server的一種選擇。
PostgreSQL和MySQL比較它更加龐大一點因為它是用來替代Oracle而設計的。所以在企業應用中採用PostgreSQL是一個明智的選擇。
MySQL被Oracle收購之後正在逐步的封閉自MySQL 5.5.31以後的所有版本將不再遵循GPL協議鑑於此將來我們也許會選擇PostgreSQL而不是MySQL作為專案的後端資料庫。
## 驅動
Go實現的支援PostgreSQL的驅動也很多因為國外很多人在開發中使用了這個資料庫。
- https://github.com/lib/pq 支援database/sql驅動純Go寫的
- https://github.com/jbarham/gopgsqldriver 支援database/sql驅動純Go寫的
- https://github.com/lxn/go-pgsql 支援database/sql驅動純Go寫的
在下面的示例中我採用了第一個驅動因為它目前使用的人最多在github上也比較活躍。
## 例項程式碼
資料庫建表語句:
```sql
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
department character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);
CREATE TABLE userdetail
(
uid integer,
intro character varying(100),
profile character varying(100)
)
WITH(OIDS=FALSE);
```
看下面這個Go如何操作資料庫表資料:增刪改查
```Go
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
func main() {
db, err := sql.Open("postgres", "user=astaxie password=astaxie dbname=test sslmode=disable")
checkErr(err)
//插入資料
stmt, err := db.Prepare("INSERT INTO userinfo(username,department,created) VALUES($1,$2,$3) RETURNING uid")
checkErr(err)
res, err := stmt.Exec("astaxie", "研發部門", "2012-12-09")
checkErr(err)
//pg不支援這個函式因為他沒有類似MySQL的自增ID
// id, err := res.LastInsertId()
// checkErr(err)
// fmt.Println(id)
var lastInsertId int
err = db.QueryRow("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) returning uid;", "astaxie", "研發部門", "2012-12-09").Scan(&lastInsertId)
checkErr(err)
fmt.Println("最後插入id =", lastInsertId)
//更新資料
stmt, err = db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", 1)
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=$1")
checkErr(err)
res, err = stmt.Exec(1)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
從上面的程式碼我們可以看到PostgreSQL是透過`$1`,`$2`這種方式來指定要傳遞的引數而不是MySQL中的`?`另外在sql.Open中的dsn資訊的格式也與MySQL的驅動中的dsn格式不一樣所以在使用時請注意它們的差異。
還有pg不支援LastInsertId函式因為PostgreSQL內部沒有實現類似MySQL的自增ID返回其他的程式碼幾乎是一模一樣。
## links
* [目錄](<preface.md>)
* 上一節: [使用SQLite資料庫](<05.3.md>)
* 下一節: [使用Beego orm函式庫進行ORM開發](<05.5.md>)