返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

exec

发布于 2024-10-12 19:15:51 字数 1739 浏览 0 评论 0 收藏 0

执行 INSERT、UPDATE、DELETE 等无记录返回的操作。

  • 方法 Exec 自动释放连接。
  • 对结果( Result )处理,无需持有连接。

返回自增 Id 和受影响的行数,需数据库和驱动支持。

package main

import (
	"database/sql"
	"log"

	_ "github.com/mattn/go-sqlite3"
)

func main() {
	log.SetFlags(log.Lshortfile)
    
	db, err := sql.Open("sqlite3", "./test.db")
	if err != nil { log.Fatalln(err) }
	defer db.Close()

    // ------------------
    
	q := `INSERT INTO user (id, name) VALUES (?, ?)`

	result, err := db.Exec(q, 3, "u3")
	if err != nil { log.Fatalln(err)  }

    // ------------------

	id, err := result.LastInsertId()
	if err != nil { log.Fatalln(err)  }
	println(id)

	rows, err := result.RowsAffected()
	if err != nil { log.Fatalln(err)  }
	println(rows)
}

源码剖析

exec 退出前,释放连接。

// database/sql/sql.go

func (db *DB) exec(ctx, query, args, strategy) (Result, error) {
	dc, err := db.conn(ctx, strategy)
	return db.execDC(ctx, dc, dc.releaseConn, query, args)
}
func (db *DB) execDC(ctx, dc, release, query, args) (res Result, err error) {
    
    // 确保归还连接。
	defer func() {
		release(err)
	}()
    
    // 检查接口实现。
	execerCtx, ok := dc.ci.(driver.ExecerContext)
    
    // 执行!
	if ok {
		withLock(dc, func() {
			resi, err = ctxDriverExec(ctx, execerCtx, execer, query, nvdargs)
		})
        
		if err != driver.ErrSkip {
			if err != nil {
				return nil, err
			}
			return driverResult{dc, resi}, nil
		}
	}

    // 以 Prepare 方式执行。
	withLock(dc, func() {
		si, err = ctxDriverPrepare(ctx, dc.ci, query)
	})
	ds := &driverStmt{Locker: dc, si: si}
	defer ds.Close()
    
	return resultFromStatement(ctx, dc.ci, ds, args...)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文