Golang訪問SQL like資料庫(二)——sql package主要資料結構及方法

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

接上一篇,sql package的主要實現是database/sql, sql 中比較重要的資料結構是:

  • type DB
  • type Row
  • type Rows
  • type Stmt
  • Type Tx

sql.Register

sql.Register介面用於註冊資料庫驅動。第三方開發的資料庫,需要在init中調用這個介面來完成本驅動的註冊。

介面聲明為:

func Register(name string, driver driver.Driver)

如果Register被調用了兩次註冊相同name的driver,或者driver為nil,Register將會panic。

函數Open

func Open(dirverName, dataSourceName string)(*DB error)

Open函數根據傳參中的db drivername和driver-specific描述資訊開啟一個指定的資料庫,driver-specific描述資訊通常包含database name和串連資訊。不同driver所支援的dataSourceName格式可能不同。

Open一般只是驗證參數,而不會為database建立串連。如果要驗證dataSourceName所指定的串連是否有效,則需要調用Ping函數進行測試。

Open返回一個指向DB類型的指標。DB維護自己的idle connection pool,它可以安全的被多個gorutines並發使用。

Type DB

DB是database/sql中主要的資料結構,定義了各種對database的基本操作方法。

DB是一個代表了零個或更多潛在串連的串連池的database handle。它可以安全的被多個goroutine並發使用。

sql package自動的建立和釋放串連,同時它還為空白閑串連維護一個空閑池。如果資料庫有per-connection state的概念,每個狀態只能在一個事物中被可靠的觀察到。一旦DB.Begin被調用,它返回的Tx綁定到唯一的一個串連。如果針對一個事物的CommitRollback被調用,則該事務的串連將會被回退到DB的idle connection pool。pool的尺寸可以通過SetMaxIdleConns設定。

type DB struct {    driver driver.Driver    dsn string    numClosed uint64    mu sync.Mutex    freeConn []*driverConn    numOpen int    openerCh Chan struct{}    closed bool    dep map[finalCloser]depSet    lastPut     map[*driverConn]string    maxIdle     int    maxOpen     int    maxLifetime time.Duration    cleanerCh   chan struct{}}

func (*DB) Begin

func (db *DB)Begin() (*Tx, error)

Begin啟動一個事務,事務見得隔離等級有driver決定。

func (*DB) Close

func (db *DB)Close() error

Close用於關閉資料庫,釋放所有開啟的資源。關閉資料庫是非常少有的操作,因為資料庫處理就是要長期存在,並且能夠在多個goroutine中共用。

func (*DB) Driver

func (db *DB)Driver() driver.Driver

Driver函數返回資料庫的底層驅動資訊。

func (*DB) Exec

func (db *DB)Exec(query string, args ...interface{}) (Result, error)

Exec執行的Query不會返回任何行。

type Result是對一條SQL語句執行的總結。Result包含兩個方法: LastInsertId返回資料庫執行一條命令所產生的整形值。通常是插入一新行時的“auto increment”欄位。RowsAffected返回update、insert或delete操作所影響的行號。並不是所有的資料庫或資料庫驅動都支援這兩個特徵。

type Result interface {    LastInsertId() (int64, error)    RowsAffected()(int64, error)}

func (*DB) Ping

func (db *DB) Ping() error

ping函數用於驗證到資料庫的串連是否還是alive的狀態。如果連結非alive狀態,則建立串連。

func (*DB) Prepare

func (db *DB) Prepare(query string) (*Stmt, error)

Prepare函數準備一個statement用於稍後的queries和executions。多個Queries和executions可以通過Prepare返回的statement並發執行。當不再使用statement是,調用者必須調用statement的Close方法關閉statement。

func (*DB) Query

func (db *DB) Query(query string, args ...interface{})(*Rows, error)

Query函數執行對資料庫的Query並返回執行結果Rows的指標,可以有後文提到的Rows提供的方法迭代遍曆所有的結果。

func (*DB) QueryRow

func (db *DB) QueryRow(query string, args ...interface{}) *Row

QureyRow用於最多隻有一行返回的資料庫Query操作。所以QueryRow總是會返回一條non-nil操作。對於錯誤查詢或者查詢所返回的實際結果為空白時,只有Row結構體(對象)的Scan方法被調用時才能體現。

Example:

id := 123var username stringerr := db.QueryRow("SELECT username FROM users WHERE id=?", id).Scan(&username)switch {case err == sql.ErrNoRows:    log.Printf("No user with that ID.")case err != nil:    log.Fatal(err)default:    fmt.Printf("Username is %s\n", username)}

func (*DB) SetConnMaxLifetime

func (db *DB)SetConnMaxLifetime(d time.Duration)

SetConnMaxLifetime用於設定串連可被重新使用的最大時間間隔。如果逾時,則串連會在重新使用前被關閉。如果 d <= 0, 則串連將被持續保留。

func (*DB) SetMaxIdleConns

func (db *DB)SetMaxIdleConns(n int)

SetMaxIdleConns設定idle connection pool的最大串連數。如果MaxOpenConns的值 > 0,但是小於這裡設定的MaxIdleConns,則MaxIdleConns將自動降到與MaxOpenConns的限制相同。

如果 <= 0, 則沒有空閑串連會被保留。

func (*DB) SetMaxOpenConns

func (db *DB)SetMaxOpenConns(n int)

SetMaxOpenConns用於設定Database最大可以開啟的串連數。

如果 <= 0, 則沒有串連限制。且預設值為0(無限制)

func (*DB)Stats

func (db *DB)Stats() DBStats

Stats函數返回資料庫的統計資訊。

type DBStats struct {    OpenConnections int}

Type Row

type Row struct{}

Row 資料結構只有一個方法Scan

func (r *Row)Scan(dst ...interface{})

Scan將匹配行中的列拷貝到dest所指向的values中。如果有多行匹配,則只返回第一行並丟棄多餘的行。如果沒有行匹配,則返回**ErrNoRows。dst中的values個數必須與返回的行的列數相同。

Scan將從database中讀取的列轉換為如下所列的Go的普通類型和sql package提供的特殊類型。

  • *string
  • *[]byte
  • *int, *int8, *int16, *int32, *int64
  • *uint, *uint8, *uint16, *uint32, *uint64
  • *bool
  • *float32, *float64
  • *interface{}
  • *RawBytes

最簡單的case是:如果從資料庫讀取的來源資料是interger,bool或string類型等,用T標識該類型,則目標正好是指向T的指標*T ,則scan簡單的通過指標將資料分配到目標變數。

Scan同樣可以在sting和numeric類型資料間無損轉換。Scan直接將從資料庫擷取的numeric類型資料字串化(stringify)為string。相反,如果將string轉化為numeric類型則需要檢查是否溢出等。同理不同類型的numeric之間轉換也需要考慮精度問題。*有一個例外就是:如果將scan得到的float64數值字串化為字串可能會丟失部分資訊。所以通常情況下,將float類型數值轉換為float64類型。

如果目標資料類型為*[]byte, Scan將從資料庫讀取的來源資料拷貝到目標地址的對於位置。Copy的副本有調用者擁有,可以被修改,且可以被無限期持有。使用類型*RawBytes可以避免拷貝操作。

如果參數的類型為*interface{},Scan將直接拷貝驅動返回的資料而不做任何的轉換。

如果源類型是time.Time,可以被Scan轉換為*time.Time, *interface{}, *string或*[]byte類型。轉換為*string或*[]byte時,將會使用到time.Format3339Nano

源類型是bool,可以被Scan轉換為*bool, *interface{}, *string, *[]byte或*RawBytes

如果要將來源資料Scan到*bool類型,則需要中繼資料是true,false,1,0或者可以被strconv.ParseBool解析的string

Type Rows

Rows結構體類似於type Row,Row是返回單行的Query結果,Rows說多行的Query結果。

type Rows struct {}

func (*Rows)Close

func (rs *Rows)Close() error

Close將關閉一個Rows,防止仍然能夠對Rows繼續進行枚舉。如果Next的返回結果是false,Rows將被自動關閉,關閉依然能夠滿足對結果的錯誤檢查。Close是idempotent的,不會影響對結果的錯誤檢查。

func (*Rows)Columns

func (rs *Rows)Columns()([]string, error)

Column返回列的名字列表。如果Rows已經被Close,則返回error。

func (*Rows)Err

func (rs *Rows)Err() error

如果在枚舉過程中有Error,Err將返回error。Err可以在顯示的或隱式的Close Rows後被調用。

func (*Rows) Next

func (rs *Rows)Next() bool

Next為Scan函數準備下一條結果,如果還有結果則返回true。沒有下一行或在準備過程中發生了錯誤則返回false,Err能夠將這兩種錯誤區分開來。

每次調用Scan擷取結果前都需要首先執行Next。

func (*Rows) Scan

Rows的Scan同Row的Scan,參考func (*Row)Scan

Type Stmt

Stmt是一個準備狀態。Stmt提供一些方法將準備狀態執行。Stmt可以安全的被多個goroutine並發執行。

type Stmt struct {}

Stmt提供如下方法:

func (s *stmt)Close() errfunc (s *stmt)Exec(args ...interface{})(Result, error)func (s *stmt)Query(args ...interface{}) (*Rows, error)func (s *stmt)QueryRow(args ...interface{}) (*Row, error)

Stmt有調用func (*DB)Prepare返回,所以如下兩個方式等效:

stmt,err := db.Prepare(querystring)res, err := stmt.Exec(...)

等效於:

res, err := db.Exec(querystring, ...)

舉一反三,其他方法也是一樣。

Tyte Tx

type Tx struct{}

Tx是進行中的資料庫事務。一次資料庫事務必須以Commit或Rollback結束。調用Commit或Rollback後,如果事務失敗則會返回錯誤ErrTxDone。

所以事務由func (*DB)Begin()返回Transaction *Tx開始,以Tx的Commit或Rollback結束。需要注意的是:有Tx的Prepare方法返回的statement也只是有Commit或Rollback關閉,而不是Stmt的Close方法關閉。

func (*Tx) Prepare

func (tx \*Tx)Prepare(query string) (\*stmt, error)

類似於DB的Prepare,Prepare為當前事務建立一個準備好的statement。當事務的的Commit或Rollback被調用後,這個statement將不在有效。

func (*Tx) Commit

func (tx *Tx)Commit() error

Commit提交當前事務。

func (*Tx) Exec

func (tx *Tx)Exec(query string, args ...interface{}) (Result, error)

Exec執行不返回結果的Query,如Insert,Update等。

func (*Tx) Query

func (tx *Tx)Query(query string, args ...interface{}) (*Rows, error)

同前面DB和Stmt的Query

func (*Tx)QueryRow

func (tx *Tx)QueryRow(query string, args ...interface{}) *Row

同DB和Stmt的Query

func (*Tx)Rollback

func (tx *Tx)Rollback() error

Rollback丟棄當前事務的操作。

func (*Tx)Stmt(stmt *stmt) *Stmt

Stmt根據一個已經存在的Stmt返回一個針對當前事務的特定Stmt。

如:

updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?")...tx, err := db.Begin()...res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)

上面樣本根據statement updateMoney通過Tx.Stmt得到了針對當前事務tx的相同statement。新得到的特殊statement將在tx的Commit或Rollback執行後失效。

參考連結

https://golang.org/src/database/sql/doc.txt
https://godoc.org/database/sql
https://golang.org/src/database/sql/
https://godoc.org/github.com/lib/pq
https://github.com/lib/pq
https://godoc.org/github.com/lib/pq
http://jmoiron.github.io/sqlx/
https://github.com/jmoiron/sqlx/blob/master/sqlx.go
https://github.com/golang/go/wiki/SQLInterface
https://github.com/golang/go/wiki/SQLDrivers

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.