...

パッケージ sql

import "database/sql"
概要
目次
サブディレクトリ

概要 ▾

sql パッケージは SQL (あるいは SQL のような) データベースの一般的なインターフェースを提供します。

sql パッケージは,データベースドライバと一緒に使う必要があります。 ドライバのリストは, https://golang.org/s/sqldrivers で確認できます。

キャンセルをサポートしないドライバの場合,クエリが終了して初めて返ってきます。

使用例は, https://golang.org/s/sqlwiki の wiki をご覧ください。

例 (OpenDBCLI)

コード:

package sql_test

import (
    "context"
    "database/sql"
    "flag"
    "log"
    "os"
    "os/signal"
    "time"
)

var pool *sql.DB // データベースコネクションプール

func Example_openDBCLI() {
    id := flag.Int64("id", 0, "person ID to find")
    dsn := flag.String("dsn", os.Getenv("DSN"), "connection data source name")
    flag.Parse()

    if len(*dsn) == 0 {
        log.Fatal("missing dsn flag")
    }
    if *id == 0 {
        log.Fatal("missing person ID")
    }
    var err error

    // 通常,ドライバを開いてもデータベースへの接続は試みられません。
    pool, err = sql.Open("driver-name", *dsn)
    if err != nil {
        // これは接続エラーではなく,
        // DSN 解析エラーまたは別の初期化エラーです。
        log.Fatal("unable to use data source name", err)
    }
    defer pool.Close()

    pool.SetConnMaxLifetime(0)
    pool.SetMaxIdleConns(3)
    pool.SetMaxOpenConns(3)

    ctx, stop := context.WithCancel(context.Background())
    defer stop()

    appSignal := make(chan os.Signal, 3)
    signal.Notify(appSignal, os.Interrupt)

    go func() {
        select {
        case <-appSignal:
            stop()
        }
    }()

    Ping(ctx)

    Query(ctx, *id)
}

// データベースに ping を実行し,ユーザーが提供した DSN が有効でセーバーにアクセスできるかを検証します。
// ping が失敗した場合は,エラーでプログラムを終了します。
func Ping(ctx context.Context) {
    ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
    defer cancel()

    if err := pool.PingContext(ctx); err != nil {
        log.Fatalf("unable to connect to database: %v", err)
    }
}

// データベースにクエリを出し,結果を表示します。
// クエリが失敗した場合は,エラーを出してプログラムを終了します。
func Query(ctx context.Context, id int64) {
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    var name string
    err := pool.QueryRowContext(ctx, "select p.name from people as p where p.id = :id;", sql.Named("id", id)).Scan(&name)
    if err != nil {
        log.Fatal("unable to execute search query", err)
    }
    log.Println("name=", name)
}

例 (OpenDBService)

コード:

package sql_test

import (
    "context"
    "database/sql"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "net/http"
    "time"
)

func Example_openDBService() {
    // 通常,ドライバを開いてもデータベースへの接続は試みられません。
    db, err := sql.Open("driver-name", "database=test1")
    if err != nil {
        // これは接続エラーではなく,
        // DSN 解析エラーまたは別の初期化エラーです。
        log.Fatal(err)
    }
    db.SetConnMaxLifetime(0)
    db.SetMaxIdleConns(50)
    db.SetMaxOpenConns(50)

    s := &Service{db: db}

    http.ListenAndServe(":8080", s)
}

type Service struct {
    db *sql.DB
}

func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    db := s.db
    switch r.URL.Path {
    default:
        http.Error(w, "not found", http.StatusNotFound)
        return
    case "/healthz":
        ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
        defer cancel()

        err := s.db.PingContext(ctx)
        if err != nil {
            http.Error(w, fmt.Sprintf("db down: %v", err), http.StatusFailedDependency)
            return
        }
        w.WriteHeader(http.StatusOK)
        return
    case "/quick-action":
        // これは短い SELECT です。 リクエストコンテキストを
        // コンテキストタイムアウトのために使用します。
        ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
        defer cancel()

        id := 5
        org := 10
        var name string
        err := db.QueryRowContext(ctx, `
select
    p.name
from
    people as p
    join organization as o on p.organization = o.id
where
    p.id = :id
    and o.id = :org
;`,
            sql.Named("id", id),
            sql.Named("org", org),
        ).Scan(&name)
        if err != nil {
            if err == sql.ErrNoRows {
                http.Error(w, "not found", http.StatusNotFound)
                return
            }
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        io.WriteString(w, name)
        return
    case "/long-action":
        // これは長いSELECTです。
        // リクエストコンテキストをコンテキストタイムアウトのために使用しますが,
        // 完了するまでしばらく時間をかけます。
        // クエリが完了する前にクライアントがキャンセルした場合,クエリもキャンセルされます。
        ctx, cancel := context.WithTimeout(r.Context(), 60*time.Second)
        defer cancel()

        var names []string
        rows, err := db.QueryContext(ctx, "select p.name from people as p where p.active = true;")
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        for rows.Next() {
            var name string
            err = rows.Scan(&name)
            if err != nil {
                break
            }
            names = append(names, name)
        }
        // rows の "Close" で生じたエラーをチェックします。
        // 複数のステートメントが 1 つのバッチで実行され,行が読み取られるだけでなく書き込まれる場合,チェックはより重要になります。
        if closeErr := rows.Close(); closeErr != nil {
            http.Error(w, closeErr.Error(), http.StatusInternalServerError)
            return
        }

        // 行スキャンエラーをチェックします。
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        // 行のイテレーション中にエラーが生じていないかチェックします。
        if err = rows.Err(); err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        json.NewEncoder(w).Encode(names)
        return
    case "/async-action":
        // このアクションは,クライアントが途中で HTTP リクエストを
        // キャンセルした場合でも保持しようとする副作用があります。
        // このため,タイムアウトのベースとして http リクエストコンテキスト
        // を使用しません。
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()

        var orderRef = "ABC123"
        tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
        _, err = tx.ExecContext(ctx, "stored_proc_name", orderRef)

        if err != nil {
            tx.Rollback()
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        err = tx.Commit()
        if err != nil {
            http.Error(w, "action in unknown state, check state before attempting again", http.StatusInternalServerError)
            return
        }
        w.WriteHeader(http.StatusOK)
        return
    }
}

目次 ▾

変数
func Drivers() []string
func Register(name string, driver driver.Driver)
type ColumnType
    func (ci *ColumnType) DatabaseTypeName() string
    func (ci *ColumnType) DecimalSize() (precision, scale int64, ok bool)
    func (ci *ColumnType) Length() (length int64, ok bool)
    func (ci *ColumnType) Name() string
    func (ci *ColumnType) Nullable() (nullable, ok bool)
    func (ci *ColumnType) ScanType() reflect.Type
type Conn
    func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)
    func (c *Conn) Close() error
    func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)
    func (c *Conn) PingContext(ctx context.Context) error
    func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error)
    func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
    func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row
    func (c *Conn) Raw(f func(driverConn interface{}) error) (err error)
type DB
    func Open(driverName, dataSourceName string) (*DB, error)
    func OpenDB(c driver.Connector) *DB
    func (db *DB) Begin() (*Tx, error)
    func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)
    func (db *DB) Close() error
    func (db *DB) Conn(ctx context.Context) (*Conn, error)
    func (db *DB) Driver() driver.Driver
    func (db *DB) Exec(query string, args ...interface{}) (Result, error)
    func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)
    func (db *DB) Ping() error
    func (db *DB) PingContext(ctx context.Context) error
    func (db *DB) Prepare(query string) (*Stmt, error)
    func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error)
    func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
    func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
    func (db *DB) QueryRow(query string, args ...interface{}) *Row
    func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row
    func (db *DB) SetConnMaxLifetime(d time.Duration)
    func (db *DB) SetMaxIdleConns(n int)
    func (db *DB) SetMaxOpenConns(n int)
    func (db *DB) Stats() DBStats
type DBStats
type IsolationLevel
    func (i IsolationLevel) String() string
type NamedArg
    func Named(name string, value interface{}) NamedArg
type NullBool
    func (n *NullBool) Scan(value interface{}) error
    func (n NullBool) Value() (driver.Value, error)
type NullFloat64
    func (n *NullFloat64) Scan(value interface{}) error
    func (n NullFloat64) Value() (driver.Value, error)
type NullInt32
    func (n *NullInt32) Scan(value interface{}) error
    func (n NullInt32) Value() (driver.Value, error)
type NullInt64
    func (n *NullInt64) Scan(value interface{}) error
    func (n NullInt64) Value() (driver.Value, error)
type NullString
    func (ns *NullString) Scan(value interface{}) error
    func (ns NullString) Value() (driver.Value, error)
type NullTime
    func (n *NullTime) Scan(value interface{}) error
    func (n NullTime) Value() (driver.Value, error)
type Out
type RawBytes
type Result
type Row
    func (r *Row) Scan(dest ...interface{}) error
type Rows
    func (rs *Rows) Close() error
    func (rs *Rows) ColumnTypes() ([]*ColumnType, error)
    func (rs *Rows) Columns() ([]string, error)
    func (rs *Rows) Err() error
    func (rs *Rows) Next() bool
    func (rs *Rows) NextResultSet() bool
    func (rs *Rows) Scan(dest ...interface{}) error
type Scanner
type Stmt
    func (s *Stmt) Close() error
    func (s *Stmt) Exec(args ...interface{}) (Result, error)
    func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, error)
    func (s *Stmt) Query(args ...interface{}) (*Rows, error)
    func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error)
    func (s *Stmt) QueryRow(args ...interface{}) *Row
    func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row
type Tx
    func (tx *Tx) Commit() error
    func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
    func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)
    func (tx *Tx) Prepare(query string) (*Stmt, error)
    func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error)
    func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)
    func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
    func (tx *Tx) QueryRow(query string, args ...interface{}) *Row
    func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row
    func (tx *Tx) Rollback() error
    func (tx *Tx) Stmt(stmt *Stmt) *Stmt
    func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt
type TxOptions

パッケージファイル

convert.go ctxutil.go sql.go

変数

ErrConnDone は,既に接続プールに返された接続上で操作が実行された場合に返されます。

var ErrConnDone = errors.New("sql: connection is already closed")

ErrNoRows は,QueryRow が行を返さない場合に Scan によって返されます。そのような場合, QueryRow は,Scan でこのエラーを返す *Row 値を返します。

var ErrNoRows = errors.New("sql: no rows in result set")

ErrTxDone は,既にコミットまたはロールバックされたトランザクションに対して実行された操作で返されます。

var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back")

func Drivers 1.4

func Drivers() []string

Drivers は,登録されているドライバの名前のソートされたリストを返します。

func Register

func Register(name string, driver driver.Driver)

Register は,指定した名前でデータベースドライバが使用可能になります。 Register が同じ名前で 2 回呼び出された場合,または driver が nil の場合, パニックします。

type ColumnType 1.8

ColumnType には,列の名前と型が含まれます。

type ColumnType struct {
    // エクスポートされていないフィールドがあります
}

func (*ColumnType) DatabaseTypeName 1.8

func (ci *ColumnType) DatabaseTypeName() string

DatabaseTypeName は列型のデータベースシステム名を返します。空の文字列が返された場合,ドライバ型名はサポートされていません。ドライバのデータ型のリストについては,ドライバのドキュメントを参照してください。長さ指定子は含まれていません。一般的な型には, "VARCHAR", "TEXT", "NVARCHAR", "DECIMAL", "BOOL", "INT", "BIGINT" があります。

func (*ColumnType) DecimalSize 1.8

func (ci *ColumnType) DecimalSize() (precision, scale int64, ok bool)

DecimalSize は, 10 進数型のスケールと精度を返します。該当しない場合,またはサポートされていない場合, ok は false です。

func (*ColumnType) Length 1.8

func (ci *ColumnType) Length() (length int64, ok bool)

Length は,テキスト型やバイナリ型などの可変長列型の列型の長さを返します。型の長さが無制限の場合,値は math.MaxInt64 になります (データベースの制限はすべて適用されます) 。列の型が int などの可変長ではない場合,またはドライバでサポートされていない場合, ok は false となります。

func (*ColumnType) Name 1.8

func (ci *ColumnType) Name() string

Name は列の名前または別名を返します。

func (*ColumnType) Nullable 1.8

func (ci *ColumnType) Nullable() (nullable, ok bool)

Nullable は,列が NULL 許容かどうかを返します。ドライバがこの機能をサポートしていない場合は, ok が false になります。

func (*ColumnType) ScanType 1.8

func (ci *ColumnType) ScanType() reflect.Type

ScanType は, Rows.Scan を使用してスキャンするのに適した Go の型を返します。ドライバがこの機能をサポートしていない場合, ScanType は空のインターフェース型を返します。

type Conn 1.9

Conn は,データベース接続プールではなく,単一のデータベース接続を表します。継続的な単一データベース接続が特に必要な場合以外は, DB からのクエリの実行を優先してください。

データベースプールに接続を返すには, Conn は Close を呼び出す必要があります。実行中のクエリと同時に行うこともできます。

Close を呼び出した後,接続でのすべての操作は ErrConnDone で失敗します。

type Conn struct {
    // エクスポートされていないフィールドがあります
}

func (*Conn) BeginTx 1.9

func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)

BeginTx はトランザクションを開始します。

引数のコンテキストは,トランザクションがコミットまたはロールバックされるまで使用されます。コンテキストがキャンセルされると, sql パッケージはトランザクションをロールバックします。 BeginTx に渡されたコンテキストがキャンセルされた場合, Tx.Commit はエラーを返します。

引数の TxOptions は任意であり,デフォルトを使用する場合は nil でしょう。ドライバがサポートしていないデフォルト以外の分離レベルが使用されている場合,エラーが返されます。

コード:

tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
if err != nil {
    log.Fatal(err)
}
id := 37
_, execErr := tx.Exec(`UPDATE users SET status = ? WHERE id = ?`, "paid", id)
if execErr != nil {
    _ = tx.Rollback()
    log.Fatal(execErr)
}
if err := tx.Commit(); err != nil {
    log.Fatal(err)
}

func (*Conn) Close 1.9

func (c *Conn) Close() error

Close は接続を接続プールに返します。 Close の後のすべての操作は ErrConnDone を返します。 Close は他の操作と平行に呼び出しても安全であり,他のすべての操作が終了するまでブロックします。まず,使用したコンテキストをキャンセルして,そのすぐ後 Close を呼び出すのがよいでしょう。

func (*Conn) ExecContext 1.9

func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)

ExecContext は,行を返さずにクエリを実行します。args は,クエリ内のプレースホルダパラメータ用です。

コード:

// *DB は接続プールです。 Conn を呼び出して,専用接続を用意します。
//
conn, err := db.Conn(ctx)
if err != nil {
    log.Fatal(err)
}
defer conn.Close() // 接続をプールに返します。
id := 41
result, err := conn.ExecContext(ctx, `UPDATE balances SET balance = balance + 10 WHERE user_id = ?;`, id)
if err != nil {
    log.Fatal(err)
}
rows, err := result.RowsAffected()
if err != nil {
    log.Fatal(err)
}
if rows != 1 {
    log.Fatalf("expected single row affected, got %d rows affected", rows)
}

func (*Conn) PingContext 1.9

func (c *Conn) PingContext(ctx context.Context) error

PingContext は,データベースへの接続がまだ有効であることを確認します。

func (*Conn) PrepareContext 1.9

func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error)

PrepareContext は後から使うクエリや実行のためのプリペアドステートメントを作成します。返されたステートメントから複数のクエリまたは実行を平行実行できます。ステートメントが不要になった場合,呼び出し側はステートメントの Close メソッドを呼び出す必要があります。

引数のコンテキストは,ステートメントの実行にではなく,ステートメントの準備に使用されます。

func (*Conn) QueryContext 1.9

func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)

QueryContext は,行を返すクエリ (通常は SELECT) を実行します。args は,クエリ内のプレースホルダパラメータ用です。

func (*Conn) QueryRowContext 1.9

func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row

QueryRowContext は,最大で 1 行を返すと予想されるクエリを実行します。 QueryRowContext は常に nil 以外の値を返します。 Row の Scan メソッドが呼び出されるまで,エラーは延期されます。クエリが行を返さない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

func (*Conn) Raw 1.13

func (c *Conn) Raw(f func(driverConn interface{}) error) (err error)

Raw は f を実行し, f の期間中,内部のドライバー接続を公開します。 driverConn は, f の外部で使用しないでください。

f が戻り, err が nil になると, Conn.Close が呼び出されるまで Conn は引き続き使用可能になります。

type DB

DB は, 0 個以上の内部接続プールを表すデータベースハンドルです。複数のゴルーチンが同時に使用しても安全です。

sql パッケージは自動的に接続を作成および解放します。アイドル接続の空きプールも維持します。データベースに接続ごとの状態という概念がある場合,そのような状態はトランザクション (Tx) または接続 (Conn) 内で確実に取得できます。 DB.Begin が呼び出されると,返された Tx は単一の接続にバインドされます。トランザクションでコミットまたはロールバックが呼び出されると,そのトランザクションの接続は DB のアイドル接続プールに返されます。プールサイズは SetMaxIdleConns で制御できます。

type DB struct {
    // エクスポートされていないフィールドがあります
}

func Open

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

Open は,データベースドライバ名とドライバ固有のデータソース名で指定されたデータベースを開きます。通常は少なくともデータベース名と接続情報で構成されています。

ほとんどのユーザーは, *DB を返すドライバ固有の接続ヘルパー関数を介してデータベースを開きます。 Go 標準ライブラリにはデータベースドライバは含まれていません。サードパーティドライバの一覧については, https://golang.org/s/sqldrivers を参照してください。

Open は,データベースへの接続を作成せずにその引数を検証するだけです。データソース名が有効であることを確認するには, Ping を呼び出します。

返された DB は,複数のゴルーチンによる平行使用に対して安全であり,独自のアイドル接続プールを維持します。したがって, OpenDB 関数は一度だけ呼び出されるべきです。 DB を閉じる必要はめったにありません。

func OpenDB 1.10

func OpenDB(c driver.Connector) *DB

OpenDB は Connector を使用してデータベースを開くので,ドライバは文字列ベースのデータソース名をつかわずにすみます。

ほとんどのユーザーは, *DB を返すドライバ固有の接続ヘルパー関数を介してデータベースを開きます。 Go 標準ライブラリにはデータベースドライバは含まれていません。サードパーティドライバの一覧については, https://golang.org/s/sqldrivers を参照してください。

OpenDB は,データベースへの接続を作成せずにその引数を検証するだけです。データソース名が有効であることを確認するには, Ping を呼び出します。

返された DB は,複数のゴルーチンによる平行使用に対して安全であり,独自のアイドル接続プールを維持します。したがって, OpenDB 関数は一度だけ呼び出されるべきです。 DB を閉じる必要はめったにありません。

func (*DB) Begin

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

トランザクションを開始します。デフォルトの分離レベルはドライバによって異なります。

func (*DB) BeginTx 1.8

func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)

BeginTx はトランザクションを開始します。

引数のコンテキストは,トランザクションがコミットまたはロールバックされるまで使用されます。コンテキストがキャンセルされると, sql パッケージはトランザクションをロールバックします。 BeginTx に渡されたコンテキストがキャンセルされた場合, Tx.Commit はエラーを返します。

引数の TxOptions は任意であり,デフォルトを使用する場合は nil でしょう。ドライバがサポートしていないデフォルト以外の分離レベルが使用されている場合,エラーが返されます。

func (*DB) Close

func (db *DB) Close() error

Close はデータベースを閉じ,新しいクエリが開始されなくなります。Close はその後,サーバー上で処理を開始したすべてのクエリが終了するのを待ちます。

DB ハンドルは長期間存続し,多くのゴルーチン間で共有されることを意図しているため, DB を閉じることはめったにありません。

func (*DB) Conn 1.9

func (db *DB) Conn(ctx context.Context) (*Conn, error)

Conn は,新しい接続を開くか,接続プールから既存の接続を返すことによって 1 つの接続を返します。 Conn は,接続が返されるか ctx がキャンセルされるまでブロックします。同一の Conn で実行されたクエリは,同一のデータベースセッションで実行されます。

すべての Conn は,使用後に Conn.Close を呼び出してデータベースプールに返す必要があります。

func (*DB) Driver

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

Driver はデータベースの内部ドライバを返します。

func (*DB) Exec

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

Exec は,行を返さずにクエリを実行します。args は,クエリ内のプレースホルダパラメータ用です。

func (*DB) ExecContext 1.8

func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)

ExecContext は,行を返さずにクエリを実行します。args は,クエリ内のプレースホルダパラメータ用です。

コード:

id := 47
result, err := db.ExecContext(ctx, "UPDATE balances SET balance = balance + 10 WHERE user_id = ?", id)
if err != nil {
    log.Fatal(err)
}
rows, err := result.RowsAffected()
if err != nil {
    log.Fatal(err)
}
if rows != 1 {
    log.Fatalf("expected to affect 1 row, affected %d", rows)
}

func (*DB) Ping 1.1

func (db *DB) Ping() error

Ping は,データベースへの接続がまだ有効であることを確認し,必要に応じて接続を確立します。

func (*DB) PingContext 1.8

func (db *DB) PingContext(ctx context.Context) error

PingContext は,データベースへの接続がまだ有効であることを確認し,必要に応じて接続を確立します。

コード:

// Ping と PingContext を使用して,データベースサーバーとの
// 通信がまだ可能かどうかを判断できます。
//
// コマンドラインアプリケーションで使用する場合は,Ping を使用して
// さらにクエリが可能であること,また渡された DSN が有効であることを確認できます。
//
// 長期サービスで使用する場合,Ping はヘルスチェックシステム
// で用いることができます。

ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
defer cancel()

status := "up"
if err := db.PingContext(ctx); err != nil {
    status = "down"
}
log.Println(status)

func (*DB) Prepare

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

Prepare は後から使うクエリや実行のためのプリペアドステートメントを作成します。返されたステートメントから複数のクエリまたは実行を平行実行できます。ステートメントが不要になった場合,呼び出し側はステートメントの Close メソッドを呼び出す必要があります。

コード:

projects := []struct {
    mascot  string
    release int
}{
    {"tux", 1991},
    {"duke", 1996},
    {"gopher", 2009},
    {"moby dock", 2013},
}

stmt, err := db.Prepare("INSERT INTO projects(id, mascot, release, category) VALUES( ?, ?, ?, ? )")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close() // プリペアドステートメントはサーバーリソースを占有するため,使用後に閉じる必要があります。

for id, project := range projects {
    if _, err := stmt.Exec(id+1, project.mascot, project.release, "open source"); err != nil {
        log.Fatal(err)
    }
}

func (*DB) PrepareContext 1.8

func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error)

PrepareContext は後から使うクエリや実行のためのプリペアドステートメントを作成します。返されたステートメントから複数のクエリまたは実行を平行実行できます。ステートメントが不要になった場合,呼び出し側はステートメントの Close メソッドを呼び出す必要があります。

引数のコンテキストは,ステートメントの実行にではなく,ステートメントの準備に使用されます。

func (*DB) Query

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

Query は,行を返すクエリ (通常は SELECT) を実行します。args は,クエリ内のプレースホルダパラメータ用です。

例 (MultipleResultSets)

コード:

age := 27
q := `
create temp table uid (id bigint); -- Create temp table for queries.
insert into uid
select id from users where age < ?; -- Populate temp table.

-- First result set.
select
    users.id, name
from
    users
    join uid on users.id = uid.id
;

-- Second result set.
select 
    ur.user, ur.role
from
    user_roles as ur
    join uid on uid.id = ur.user
;
    `
rows, err := db.Query(q, age)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
    var (
        id   int64
        name string
    )
    if err := rows.Scan(&id, &name); err != nil {
        log.Fatal(err)
    }
    log.Printf("id %d name is %s\n", id, name)
}
if !rows.NextResultSet() {
    log.Fatalf("expected more result sets: %v", rows.Err())
}
var roleMap = map[int64]string{
    1: "user",
    2: "admin",
    3: "gopher",
}
for rows.Next() {
    var (
        id   int64
        role int64
    )
    if err := rows.Scan(&id, &role); err != nil {
        log.Fatal(err)
    }
    log.Printf("id %d has role %s\n", id, roleMap[role])
}
if err := rows.Err(); err != nil {
    log.Fatal(err)
}

func (*DB) QueryContext 1.8

func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)

QueryContext は,行を返すクエリ (通常は SELECT) を実行します。args は,クエリ内のプレースホルダパラメータ用です。

コード:

age := 27
rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()
names := make([]string, 0)

for rows.Next() {
    var name string
    if err := rows.Scan(&name); err != nil {
        // スキャンエラーをチェックします。
        // クエリ rows は defer で閉じます。
        log.Fatal(err)
    }
    names = append(names, name)
}
// データベースが書き込まれている場合は,ドライバから返される可能性がある
// Close エラーを必ず確認してください。クエリは自動コミットエラー発生ゆえに,
// 変更が強制的にロールバックされるかもしれません。
rerr := rows.Close()
if rerr != nil {
    log.Fatal(err)
}

// Rows.Err は,Rows.Scan で最後に発生したエラーを報告します。
if err := rows.Err(); err != nil {
    log.Fatal(err)
}
fmt.Printf("%s are %d years old", strings.Join(names, ", "), age)

func (*DB) QueryRow

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

QueryRow は,最大で 1 行を返すと予想されるクエリを実行します。 QueryRow は常に nil 以外の値を返します。 Row の Scan メソッドが呼び出されるまで,エラーは延期されます。クエリが行を返さない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

func (*DB) QueryRowContext 1.8

func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row

QueryRowContext は,最大で 1 行を返すと予想されるクエリを実行します。 QueryRowContext は常に nil 以外の値を返します。 Row の Scan メソッドが呼び出されるまで,エラーは延期されます。クエリが行を返さない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

コード:

id := 123
var username string
var created time.Time
err := db.QueryRowContext(ctx, "SELECT username, created_at FROM users WHERE id=?", id).Scan(&username, &created)
switch {
case err == sql.ErrNoRows:
    log.Printf("no user with id %d\n", id)
case err != nil:
    log.Fatalf("query error: %v\n", err)
default:
    log.Printf("username is %q, account created on %s\n", username, created)
}

func (*DB) SetConnMaxLifetime 1.6

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

SetConnMaxLifetime は,接続が再利用される最大時間を設定します。

期限切れの接続は再利用の前に遅延して閉じることがあります。

d <= 0 の場合,接続は永久に再利用されます。

func (*DB) SetMaxIdleConns 1.1

func (db *DB) SetMaxIdleConns(n int)

SetMaxIdleConns は,アイドル接続プール内の最大接続数を設定します。

MaxOpenConns が 0 より大きく,新しい MaxIdleConns より小さい場合,新しい MaxIdleConns は MaxOpenConns を超えないように減らされます。

n <= 0 の場合,アイドル接続は保持されません。

デフォルトの最大アイドル接続数は現在 2 です。これは将来のリリースで変更される可能性があります。

func (*DB) SetMaxOpenConns 1.2

func (db *DB) SetMaxOpenConns(n int)

SetMaxOpenConns は,データベースへのオープン接続の最大数を設定します。

MaxIdleConns が 0 より大きく,新しい MaxOpenConns が MaxIdleConns より小さい場合, MaxIdleConns は新しい MaxOpenConns を超えないように減らされます。

n <= 0 の場合,オープン接続数に制限はありません。デフォルトは 0 (無制限) です。

func (*DB) Stats 1.5

func (db *DB) Stats() DBStats

Stats はデータベース統計を返します。

type DBStats 1.5

DBStats にはデータベース統計が含まれています。

type DBStats struct {
    MaxOpenConnections int // データベースへの最大オープン接続数; added in Go 1.11

    // プールステータス
    OpenConnections int // 使用中あるいはアイドル中の確立された接続数
    InUse           int // 現在使用中の接続数; added in Go 1.11
    Idle            int // アイドル接続の数; added in Go 1.11

    // カウンタ
    WaitCount         int64         // 待機した接続の総数; added in Go 1.11
    WaitDuration      time.Duration // 新たな接続を待つためにブロックした総合時間; added in Go 1.11
    MaxIdleClosed     int64         // SetMaxIdleConns が原因で閉じられた接続の総数; added in Go 1.11
    MaxLifetimeClosed int64         // SetConnMaxLifetime が原因で閉じられた接続の総数; added in Go 1.11
}

type IsolationLevel 1.8

IsolationLevel は TxOptions で使用されるトランザクション分離レベルです。

type IsolationLevel int

BeginTx でドライバがサポートする可能性があるさまざまな分離レベル。ドライバが特定の分離レベルをサポートしていない場合は,エラーが返されることがあります。

https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels を参照してください。

const (
    LevelDefault IsolationLevel = iota
    LevelReadUncommitted
    LevelReadCommitted
    LevelWriteCommitted
    LevelRepeatableRead
    LevelSnapshot
    LevelSerializable
    LevelLinearizable
)

func (IsolationLevel) String 1.11

func (i IsolationLevel) String() string

String は,トランザクション遮断レベルの名前を返します。

type NamedArg 1.8

NamedArg は名前付き引数です。 NamedArg 値は, Query または Exec への引数として使用し, SQL ステートメント内の対応する名前付きパラメーターにバインドすることができます。

NamedArg 値をより簡潔に作成するには, Named 関数を参照してください。

type NamedArg struct {

    // Name は,パラメータプレースホルダの名前です。
    //
    // 空の場合,引数リスト内の順序位置が使用されます。
    //
    //
    // 名前はシンボル接頭辞を省略しなければなりません。
    Name string

    // Value はパラメータの値です。
    // クエリ引数と同じ値型が割り当たるかもしれません。
    //
    Value interface{}
    // エクスポートされていないフィールドがあります
}

func Named 1.8

func Named(name string, value interface{}) NamedArg

Named は, NamedArg 値を作成する簡潔な方法です。

使用例

db.ExecContext(ctx, `
    delete from Invoice
    where
        TimeCreated < @end
        and TimeCreated >= @start;`,
    sql.Named("start", startTime),
    sql.Named("end", endTime),
)

type NullBool

NullBool は null の可能性がある bool を表します。 NullBool は Scanner インターフェースを実装しているため, NullString と同様に,スキャン先として使用できます。

type NullBool struct {
    Bool  bool
    Valid bool // Valid は,Bool が NULL でないとき true になります
}

func (*NullBool) Scan

func (n *NullBool) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullBool) Value

func (n NullBool) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type NullFloat64

NullFloat64 は, null の可能性がある float64 を表します。 NullFloat64 は Scanner インターフェースを実装しているため, NullString と同様に,スキャン先として使用できます。

type NullFloat64 struct {
    Float64 float64
    Valid   bool // Valid は,Float64 が NULL でないときに true となります
}

func (*NullFloat64) Scan

func (n *NullFloat64) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullFloat64) Value

func (n NullFloat64) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type NullInt32 1.13

NullInt32 は, null の可能性がある int64 を表します。 NullInt32 は Scanner インターフェースを実装しているため, NullString と同様に,スキャン先として使用できます。

type NullInt32 struct {
    Int32 int32
    Valid bool // Valid は,Int32 が NULL でないときに true となります
}

func (*NullInt32) Scan 1.13

func (n *NullInt32) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullInt32) Value 1.13

func (n NullInt32) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type NullInt64

NullInt64 は, null の可能性がある int64 を表します。 NullInt64 は Scanner インターフェースを実装しているため, NullString と同様に,スキャン先として使用できます。

type NullInt64 struct {
    Int64 int64
    Valid bool // Valid は,Int64 が NULL でないときに true となります
}

func (*NullInt64) Scan

func (n *NullInt64) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullInt64) Value

func (n NullInt64) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type NullString

NullString は, null の可能性がある文字列を表します。 NullString は Scanner インターフェースを実装しているため,スキャン先として使用できます。

var s NullString
err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
...
if s.Valid {
   // use s.String
} else {
   // NULL value
}
type NullString struct {
    String string
    Valid  bool // Valid は,String が NULL でないときに true となります
}

func (*NullString) Scan

func (ns *NullString) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullString) Value

func (ns NullString) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type NullTime 1.13

NullTime は null の可能性がある time.Time を表します。 NullTime は Scanner インターフェースを実装しているため, NullString と同様に,スキャン先として使用できます。

type NullTime struct {
    Time  time.Time
    Valid bool // Valid は, Time が NULL でないとき true になります
}

func (*NullTime) Scan 1.13

func (n *NullTime) Scan(value interface{}) error

Scan は Scanner インターフェースを実装します。

func (NullTime) Value 1.13

func (n NullTime) Value() (driver.Value, error)

値はドライバ Valuer インターフェースを実装します。

type Out 1.9

ストアドプロシージャから OUTPUT 値パラメータを取得するために Out を使用することができます。

すべてのドライバとデータベースが OUTPUT 値パラメータをサポートしているわけではありません。

使用例

var outArg string
_, err := db.ExecContext(ctx, "ProcName", sql.Named("Arg1", sql.Out{Dest: &outArg}))
type Out struct {

    // Dest は,ストアドプロシージャの OUTPUT パラメータの結果
    // に設定される値へのポインタです。
    Dest interface{}

    // In は,パラメータが INOUT パラメータかどうかを表します。
    // もしそうであれば,ストアドプロシージャへの入力値は Dest
    // のポインタで参照されている値で,出力値で置き換えられます。
    In bool
    // エクスポートされていないフィールドがあります
}

type RawBytes

RawBytes は,データベース自体が所有するメモリへの参照を保持するバイトスライスです。 RawBytes へスキャンした後,スライスは次の Next, Scan,または Close 呼び出しまで有効です。

type RawBytes []byte

type Result

Result は,実行された SQL コマンドの要約です。

type Result interface {
    // LastInsertId は,コマンドに対して
    // データベースによって生成された整数を返します。
    // 通常,これは新しい行を挿入するときの「自動インクリメント」列からのものです。
    // すべてのデータベースがこの機能をサポートしているわけではなく,
    // そのようなステートメントの構文はさまざまです。
    LastInsertId() (int64, error)

    // RowsAffected は,更新,挿入,または削除の影響を受ける行の数を返します。 すべてのデータベースまたはデータベースドライバーがこれをサポートするわけではありません。
    RowsAffected() (int64, error)
}

type Row

Row は, QueryRow を呼び出した際にセレクトされた 1 つの行です。

type Row struct {
    // エクスポートされていないフィールドがあります
}

func (*Row) Scan

func (r *Row) Scan(dest ...interface{}) error

Scan は,マッチした行の列を dest が指す値にコピーします。詳細は Rows.Scan のドキュメントを参照してください。複数の行がクエリにマッチする場合, Scan は最初の行を使用し,残りを破棄します。クエリにマッチする行がない場合, Scan は ErrNoRows を返します。

type Rows

Rows はクエリの結果です。カーソルは結果セットの最初の行の前から始まります。 Next を呼び出して次の行に進みます。

type Rows struct {
    // エクスポートされていないフィールドがあります
}

コード:

age := 27
rows, err := db.QueryContext(ctx, "SELECT name FROM users WHERE age=?", age)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

names := make([]string, 0)
for rows.Next() {
    var name string
    if err := rows.Scan(&name); err != nil {
        log.Fatal(err)
    }
    names = append(names, name)
}
// rows をイテレートした際のエラーをチェックする。
if err := rows.Err(); err != nil {
    log.Fatal(err)
}
log.Printf("%s are %d years old", strings.Join(names, ", "), age)

func (*Rows) Close

func (rs *Rows) Close() error

Close は Rows を閉じ,それ以上の列挙はできなくなります。 Next が呼び出されて false が返され,それ以上結果セットがない場合, Rows は自動的に閉じられるので, Err の結果を確認するだけで十分です。Close はべき等であり, Err には影響しません。

func (*Rows) ColumnTypes 1.8

func (rs *Rows) ColumnTypes() ([]*ColumnType, error)

ColumnTypes は,列の型,長さ, NULL 許容などの列情報を返します。一部のドライバでは,入手できない情報があるかもしれません。

func (*Rows) Columns

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

Columns は列名を返します。Rows が閉じている場合, Columns はエラーを返します。

func (*Rows) Err

func (rs *Rows) Err() error

Err は,もしあれば,イテレーション中に発生したエラーを返します。 Err は,明示的または暗黙的な Close の後に呼び出すことができます。

func (*Rows) Next

func (rs *Rows) Next() bool

Next は, Scan メソッドで読み取るため,次の結果行を準備します。成功した場合は true ,次の結果行がない場合や準備中にエラーが発生した場合は false を返します。 2 つのケースを区別するために Err を調べる必要があります。

Scan を呼び出す前には必ず,最初の呼び出しであっても, Next を呼び出す必要があります。

func (*Rows) NextResultSet 1.8

func (rs *Rows) NextResultSet() bool

NextResultSet は,次の結果セットを読み込むため準備します。結果セットがさらにあるかどうかを報告します。もう結果セットがない場合,またはエラーが発生した場合は false を返します。 2 つのケースを区別するために Err メソッドを調べる必要があります。

NextResultSet を呼び出した後,スキャンする前に Next メソッドを常に呼び出す必要があります。さらに結果セットがある場合,結果セットに行がない可能性があります。

func (*Rows) Scan

func (rs *Rows) Scan(dest ...interface{}) error

Scan は現在の行の列を dest が指す値にコピーします。 dest の値の数は,Rows の列数と同じでなければなりません。

Scan は,データベースから読み取られた列を,次の一般的な Go 型と sql パッケージで提供される特殊型に変換します。

*string
*[]byte
*int, *int8, *int16, *int32, *int64
*uint, *uint8, *uint16, *uint32, *uint64
*bool
*float32, *float64
*interface{}
*RawBytes
*Rows (カーソル値)
Scanner を実装している任意の型 (Scanner のドキュメントを参照)

最も単純なケースでは,ソース列の値の型が整数型,ブール型,または文字列型 T で, dest が *T 型の場合, Scan は単にポインタを介して値を割り当てます。

情報が失われない限り, Scan は文字列型と数値型の間の変換も行います。Scan は数値列からスキャンされたすべての数値を *string に文字列化しますが,数値型へのスキャンはオーバーフローをチェックします。たとえば,値が 300 の float64 や値が "300" の文字列は, uint16 にスキャンできますが, uint8 にはスキャンできません。 float64(255) または "255" は uint8 にスキャンできます。 1 つの例外は,一部の float64 の数値を文字列にスキャンすると,文字列化時に情報が失われる可能性があることです。一般に,浮動小数点列を *float64 にスキャンします。

dest 引数が *[]byte 型の場合, Scan はその引数に対応するデータのコピーを保存します。コピーは呼び出し側によって所有されており,無期限に変更および保持することができます。 *RawBytes 型の引数を代わりに使用すればコピーを回避できます。制約については RawBytes のドキュメントを参照してください。

引数の型が *interface{} の場合, Scan は内部のドライバが提供する値を変換せずにコピーします。 []byte 型のソース値から *interface{} にスキャンすると,スライスのコピーが作成され,呼び出し側がその結果を所有します。

time.Time 型のソース値は, *time.Time, *interface{}, *string,または *[]byte 型の値にスキャンできます。後者の 2 つに変換するときは, time.RFC3339Nano が使用されます。

bool 型のソース値は *bool, *interface{}, *string, *[]byte,または *RawBytes 型にスキャンできます。

*bool にスキャンする場合,ソースは true, false, 1, 0,または strconv.ParseBool によって解析可能な文字列入力です。

また, Scan は, "select cursor(select * from my_table) from dual" のようなクエリから返されたカーソルを,スキャン可能な *Rows 値に変換することもできます。親の *Rows が閉じられたなら,親のセレクトクエリは *Rows のすべてのカーソルを閉じます。

type Scanner

Scanner は,Scan で使用されるインターフェースです。

type Scanner interface {
    // Scan はデータベースドライバから値を割り当てます。
    //
    // src の値は以下の型のうちのいずれかです。
    //
    //    int64
    //    float64
    //    bool
    //    []byte
    //    string
    //    time.Time
    //    nil - NULL 値
    //
    // 値を情報を失わずに格納できない場合は,エラーが返されます。
    //
    // []byte などの参照型は,次に Scan を呼び出すまで有効であり,保持するべきではありません。
    // それらの内部のメモリは,ドライバによって所有されています。
    // 保持が必要な場合は,次の Scan の呼び出しの前にそれらの値をコピーしてください。
    Scan(src interface{}) error
}

type Stmt

Stmt はプリペアドステートメントです。 Stmt は複数のゴルーチンによる平行使用に対して安全です。

Stmt が Tx または Conn で準備されている場合,それは最後まで 1 つの内部の接続にバインドされます。 Tx または Conn が閉じると, Stmt は使用できなくなり,すべての操作でエラーを返します。 Stmt が DB 上に準備されている場合,DB の存続期間中使用可能です。 Stmt が新しい内部の接続上で実行する必要があるなら,自動的に新しい接続上で準備します。

type Stmt struct {
    // エクスポートされていないフィールドがあります
}

コード:

// 通常,プロセスを開始する際に 1 つの Stmt を作成します。
stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

// それからは,各クエリを発行する際に再利用します。
id := 43
var username string
err = stmt.QueryRowContext(ctx, id).Scan(&username)
switch {
case err == sql.ErrNoRows:
    log.Fatalf("no user with id %d", id)
case err != nil:
    log.Fatal(err)
default:
    log.Printf("username is %s\n", username)
}

func (*Stmt) Close

func (s *Stmt) Close() error

Close はステートメントを閉じます。

func (*Stmt) Exec

func (s *Stmt) Exec(args ...interface{}) (Result, error)

Exec は与えられた引数でプリペアドステートメントを実行し,ステートメントの効果を要約した結果を返します。

func (*Stmt) ExecContext 1.8

func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, error)

ExecContext は,与えられた引数でプリペアドステートメントを実行し,ステートメントの結果を要約した Result を返します。

func (*Stmt) Query

func (s *Stmt) Query(args ...interface{}) (*Rows, error)

Query は与えられた引数でプリペアードクエリステートメントを実行し,クエリ結果を *Rows として返します。

func (*Stmt) QueryContext 1.8

func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error)

QueryContext は与えられた引数でプリペアードドクエリステートメントを実行し,クエリ結果を *Rows として返します。

func (*Stmt) QueryRow

func (s *Stmt) QueryRow(args ...interface{}) *Row

QueryRow は,指定された引数を使用してプリペアードクエリステートメントを実行します。ステートメントの実行中にエラーが発生した場合,そのエラーは返された *Row で Scan を呼び出したときに返されます。 *Row は必ず nil ではありません。クエリが行を選択しない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

使用例

var name string
err := nameByUseridStmt.QueryRow(id).Scan(&name)

func (*Stmt) QueryRowContext 1.8

func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row

QueryRowContext は,指定された引数を使用してプリペアードクエリステートメントを実行します。ステートメントの実行中にエラーが発生した場合,そのエラーは返された *Row で Scan を呼び出したときに返されます。 *Row は必ず nil ではありません。クエリが行を選択しない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

コード:

// 通常,プロセスを開始する際に 1 つの Stmt を作成します。
stmt, err := db.PrepareContext(ctx, "SELECT username FROM users WHERE id = ?")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

// それからは,各クエリを発行する際に再利用します。
id := 43
var username string
err = stmt.QueryRowContext(ctx, id).Scan(&username)
switch {
case err == sql.ErrNoRows:
    log.Fatalf("no user with id %d", id)
case err != nil:
    log.Fatal(err)
default:
    log.Printf("username is %s\n", username)
}

type Tx

Tx は進行中のデータベーストランザクションです。

トランザクションは, Commit または Rollback の呼び出しで終了する必要があります。

Commit または Rollback の呼び出し後,トランザクションに対するすべての操作は ErrTxDone エラーで失敗します。

トランザクションの Prepare または Stmt メソッドを呼び出してトランザクション用に作成されたプリペアドステートメントは, Commit または Rollback の呼び出しによって閉じられます。

type Tx struct {
    // エクスポートされていないフィールドがあります
}

func (*Tx) Commit

func (tx *Tx) Commit() error

Commit はトランザクションをコミットします。

func (*Tx) Exec

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

Exec は,行を返さないクエリを実行します。例えば, INSERT や UPDATE です。

func (*Tx) ExecContext 1.8

func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)

ExecContext は,行を返さないクエリを実行します。例えば, INSERT や UPDATE です。

コード:

tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
if err != nil {
    log.Fatal(err)
}
id := 37
_, execErr := tx.ExecContext(ctx, "UPDATE users SET status = ? WHERE id = ?", "paid", id)
if execErr != nil {
    if rollbackErr := tx.Rollback(); rollbackErr != nil {
        log.Fatalf("update failed: %v, unable to rollback: %v\n", execErr, rollbackErr)
    }
    log.Fatalf("update failed: %v", execErr)
}
if err := tx.Commit(); err != nil {
    log.Fatal(err)
}

func (*Tx) Prepare

func (tx *Tx) Prepare(query string) (*Stmt, error)

Prepare は,トランザクション内で使用するためのプリペアドステートメントを作成します。

返されたステートメントはそのトランザクション内で機能し,トランザクションがコミットまたはロールバックされると使用できなくなります。

このトランザクションで既存のプリペアドステートメントを使用するには, Tx.Stmt を参照してください。

コード:

projects := []struct {
    mascot  string
    release int
}{
    {"tux", 1991},
    {"duke", 1996},
    {"gopher", 2009},
    {"moby dock", 2013},
}

tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}
defer tx.Rollback() // 関数の後の部分で tx がコミットされている場合,ロールバックは無視されます。

stmt, err := tx.Prepare("INSERT INTO projects(id, mascot, release, category) VALUES( ?, ?, ?, ? )")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close() // プリペアドステートメントはサーバーリソースを占有するため,使用後に閉じる必要があります。

for id, project := range projects {
    if _, err := stmt.Exec(id+1, project.mascot, project.release, "open source"); err != nil {
        log.Fatal(err)
    }
}
if err := tx.Commit(); err != nil {
    log.Fatal(err)
}

func (*Tx) PrepareContext 1.8

func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error)

PrepareContext は,トランザクション内で使用するためのプリペアドステートメントを作成します。

返されたステートメントはそのトランザクション内で機能し,トランザクションがコミットまたはロールバックされたときに閉じられます。

このトランザクションで既存のプリペアドステートメントを使用するには, Tx.Stmt を参照してください。

引数のコンテキストは,返されたステートメントの実行ではなく,コンテキストの準備に使用されます。返されたステートメントはトランザクションコンテキストで実行されます。

func (*Tx) Query

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

Query は,行を返すクエリ (通常は SELECT) を実行します。

func (*Tx) QueryContext 1.8

func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)

QueryContext は,行を返すクエリ (通常は SELECT) を実行します。

func (*Tx) QueryRow

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

QueryRow は,最大で 1 行を返すと予想されるクエリを実行します。 QueryRow は常に nil 以外の値を返します。 Row の Scan メソッドが呼び出されるまで,エラーは延期されます。クエリが行を返さない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

func (*Tx) QueryRowContext 1.8

func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row

QueryRowContext は,最大で 1 行を返すと予想されるクエリを実行します。 QueryRowContext は常に nil 以外の値を返します。 Row の Scan メソッドが呼び出されるまで,エラーは延期されます。クエリが行を返さない場合, *Row の Scan は ErrNoRows を返します。それ以外の場合, *Row の Scan は最初に選択された行を取得し,残りを破棄します。

func (*Tx) Rollback

func (tx *Tx) Rollback() error

Rollback はトランザクションを中止します。

コード:

tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})
if err != nil {
    log.Fatal(err)
}
id := 53
_, err = tx.ExecContext(ctx, "UPDATE drivers SET status = ? WHERE id = ?;", "assigned", id)
if err != nil {
    if rollbackErr := tx.Rollback(); rollbackErr != nil {
        log.Fatalf("update drivers: unable to rollback: %v", rollbackErr)
    }
    log.Fatal(err)
}
_, err = tx.ExecContext(ctx, "UPDATE pickups SET driver_id = $1;", id)
if err != nil {
    if rollbackErr := tx.Rollback(); rollbackErr != nil {
        log.Fatalf("update failed: %v, unable to back: %v", err, rollbackErr)
    }
    log.Fatal(err)
}
if err := tx.Commit(); err != nil {
    log.Fatal(err)
}

func (*Tx) Stmt

func (tx *Tx) 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)

返されたステートメントはそのトランザクション内で機能し,トランザクションがコミットまたはロールバックされたときに閉じられます。

func (*Tx) StmtContext 1.8

func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt

StmtContext は,既存のステートメントからトランザクション固有のプリペアドステートメントを返します。

例:

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

引数のコンテキストは,ステートメントの実行にではなく,ステートメントの準備に使用されます。

返されたステートメントはそのトランザクション内で機能し,トランザクションがコミットまたはロールバックされたときに閉じられます。

type TxOptions 1.8

TxOptions は DB.BeginTx で使用されるトランザクションオプションを保持します。

type TxOptions struct {
    // Isolation はトランザクション分離レベルです。
    // 0 の場合,ドライバまたはデータベースのデフォルトレベルが使用されます。
    Isolation IsolationLevel
    ReadOnly  bool
}

サブディレクトリ

名前 概要
..
driver driver パッケージは, sql パッケージで使われるドライバが実装すべきインターフェースを定義します。