# 5.4 PostgreSQLデータベースの使用

PostgreSQLはフリーなオブジェクト-リレーショナルデータベースサーバ（データベース管理システム）です。これは活発なBSDライクなライセンスで公開されています。他のオープンソースなデータベースシステム(MySQLやFirebird)やOracle、Sybase、IBMのDB2やMicrosoft SQL Serverといったプロプライエタリなシステムに対する選択肢の一つです。

PostgreSQLとMSQLを比較すると、これは少々巨大です。これはOracleの代替として設計されているためです。そのため、企業のアプリケーションではPostgreSQLを選択することが賢い選択の一つとなっています。

MySQLはOracleに買収され、現在徐々にクローズされつつあります。(MySQL 5.5.31以降のすべてのバージョンがGPLライセンスを順守していません)。これに鑑み、将来我々もプロジェクトのバックエンドのデータベースとしてMySQLではなくPostgreSQLを選択することになるかもしれません。

## ドライバ
GoはPostgreSQLをサポートしたドライバも非常に多く実装されています。国外では多くの人が開発でこのデータベースを使用しているためです。

- https://github.com/bmizerany/pq database/sqlドライバをサポートしています。純粋にGoで書かれています。
- https://github.com/jbarham/gopgsqldriver database/sqlドライバをサポートしています。純粋にGoで書かれています。
- https://github.com/lxn/go-pgsql database/sqlドライバをサポートしています。純粋にGoで書かれています。

下の例では一つ目のドライバを採用してご説明します。これは使用している人が最も多く、githubでも比較的活発であるからです。

## 実例コード
データベースのテーブル作成文：

	CREATE TABLE userinfo
	(
		uid serial NOT NULL,
		username character varying(100) NOT NULL,
		departname character varying(500) NOT NULL,
		Created date,
		CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
	)
	WITH (OIDS=FALSE);

	CREATE TABLE userdeatail
	(
		uid integer,
		intro character varying(100),
		profile character varying(100)
	)
	WITH(OIDS=FALSE);

下ではGoがどのようにデータベースのテーブルのデータを操作するか見て行きましょう：追加・削除・修正・検索

package main

	import (
		"database/sql"
		"fmt"
		_ "github.com/bmizerany/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,departname,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)

		//データの更新
		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>)
   * 次へ: [beedbライブラリを使ってORM開発を行う](<05.5.md>)
