5.4 PostgreSQL

PostgreSQL is an object-relational database management system available for many platforms including Linux, FreeBSD, Solaris, Microsoft Windows and Mac OS X. It is released under an MIT-style license, and is thus free and open source software. It’s larger than MySQL because it’s designed for enterprise usage as an alternative to Oracle. Postgresql is a good choice for enterprise type projects.

PostgreSQL drivers

There are many database drivers available for PostgreSQL. Here are three examples of them:

I will use the first one in the examples that follow.

Samples

We create the following SQL:

  1. CREATE TABLE userinfo
  2. (
  3. uid serial NOT NULL,
  4. username character varying(100) NOT NULL,
  5. department character varying(500) NOT NULL,
  6. Created date,
  7. CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
  8. )
  9. WITH (OIDS=FALSE);

An example:

  1. package main
  2. import (
  3. "database/sql"
  4. "fmt"
  5. _ "github.com/lib/pq"
  6. "time"
  7. )
  8. const (
  9. DB_USER = "postgres"
  10. DB_PASSWORD = "postgres"
  11. DB_NAME = "test"
  12. )
  13. func main() {
  14. dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
  15. DB_USER, DB_PASSWORD, DB_NAME)
  16. db, err := sql.Open("postgres", dbinfo)
  17. checkErr(err)
  18. defer db.Close()
  19. fmt.Println("# Inserting values")
  20. var lastInsertId int
  21. err = db.QueryRow("INSERT INTO userinfo(username,department,created) VALUES($1,$2,$3) returning uid;", "astaxie", "研发部门", "2012-12-09").Scan(&lastInsertId)
  22. checkErr(err)
  23. fmt.Println("last inserted id =", lastInsertId)
  24. fmt.Println("# Updating")
  25. stmt, err := db.Prepare("update userinfo set username=$1 where uid=$2")
  26. checkErr(err)
  27. res, err := stmt.Exec("astaxieupdate", lastInsertId)
  28. checkErr(err)
  29. affect, err := res.RowsAffected()
  30. checkErr(err)
  31. fmt.Println(affect, "rows changed")
  32. fmt.Println("# Querying")
  33. rows, err := db.Query("SELECT * FROM userinfo")
  34. checkErr(err)
  35. for rows.Next() {
  36. var uid int
  37. var username string
  38. var department string
  39. var created time.Time
  40. err = rows.Scan(&uid, &username, &department, &created)
  41. checkErr(err)
  42. fmt.Println("uid | username | department | created ")
  43. fmt.Printf("%3v | %8v | %6v | %6v\n", uid, username, department, created)
  44. }
  45. fmt.Println("# Deleting")
  46. stmt, err = db.Prepare("delete from userinfo where uid=$1")
  47. checkErr(err)
  48. res, err = stmt.Exec(lastInsertId)
  49. checkErr(err)
  50. affect, err = res.RowsAffected()
  51. checkErr(err)
  52. fmt.Println(affect, "rows changed")
  53. }
  54. func checkErr(err error) {
  55. if err != nil {
  56. panic(err)
  57. }
  58. }

Note that PostgreSQL uses the $1, $2 format instead of the ? that MySQL uses, and it has a different DSN format in sql.Open. Another thing is that the PostgreSQL driver does not support sql.Result.LastInsertId(). So instead of this,

  1. stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3);")
  2. res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
  3. fmt.Println(res.LastInsertId())

use db.QueryRow() and .Scan() to get the value for the last inserted id.

  1. err = db.QueryRow("INSERT INTO TABLE_NAME values($1) returning uid;", VALUE1").Scan(&lastInsertId)
  2. fmt.Println(lastInsertId)