NetLife Guru

Open source Go packages for fast, maintainable web systems. Built with a documentation-first approach.

Product
OverviewGolang packagesNews
Documentation
DocumentationGo LoggerGo RouterGo DB Form
Company
OverviewContactNewsGitHub
Community / Support
Supportinfo@netlife.guru
© 2026 NetLife Guru. All rights reserved.
GitHubinfo@netlife.guru
NetLife GuruNetLife GuruNetLife Guru
NetLife GuruNetLife GuruNetLife Guru
OverviewDocumentationNewsSupportContact

Golang packages

AboutMulti-DriverSQL Files
ExecInsertUpdateDelete
DBMutations

Exec

Execute SQL or CQL statements using Exec, ExecQuery, Insert, Update, and Delete.

The db package provides execution helpers for statements that do not return rows.

Use these helpers for inserts, updates, deletes, schema changes, maintenance queries, and other SQL or CQL statements where the result is represented by db.Result.

Overview

FunctionPurpose
ExecExecute a raw SQL or CQL statement
ExecQueryExecute a prepared db.Query value
InsertExecute an insert statement
UpdateExecute an update statement
DeleteExecute a delete statement

Insert, Update, and Delete are semantic wrappers around Exec.

They do not inspect, validate, or rewrite SQL. They exist to make application code easier to read.

Exec

Use Exec when you want to execute a raw statement with arguments.

result, err := db.Exec(ctx, conn, `
	UPDATE users
	SET active = ?
	WHERE id = ?
`, active, id)

if err != nil {
	return err
}

Exec creates a db.Query internally and passes it to ExecQuery.

Conceptually, this:

result, err := db.Exec(ctx, conn, query, args...)

is equivalent to:

q, err := db.Raw(query, args...)
if err != nil {
	return nil, err
}

result, err := db.ExecQuery(ctx, conn, q)

Use Exec when the operation is generic or when you do not want to label it as insert, update, or delete.

ExecQuery

Use ExecQuery when you already have a db.Query.

q, err := db.Raw(`
	UPDATE users
	SET active = ?
	WHERE id = ?
`, active, id)

if err != nil {
	return err
}

result, err := db.ExecQuery(ctx, conn, q)
if err != nil {
	return err
}

This is useful when queries are built or selected before execution.

For example:

q, err := db.Dialect(conn, queries.UpdateUserStatus, active, id)
if err != nil {
	return err
}

result, err := db.ExecQuery(ctx, conn, q)
if err != nil {
	return err
}

Semantic Helpers

Insert, Update, and Delete call Exec internally.

func Insert(ctx context.Context, c Execer, query string, args ...any) (Result, error) {
	return Exec(ctx, c, query, args...)
}

func Update(ctx context.Context, c Execer, query string, args ...any) (Result, error) {
	return Exec(ctx, c, query, args...)
}

func Delete(ctx context.Context, c Execer, query string, args ...any) (Result, error) {
	return Exec(ctx, c, query, args...)
}

These helpers are intentionally simple.

They do not make the package an ORM. They only communicate intent in repository or service code.

Insert

Use Insert when the statement creates new data.

result, err := db.Insert(ctx, conn, `
	INSERT INTO users (name, email, active)
	VALUES (?, ?, ?)
`, name, email, active)

if err != nil {
	return err
}

For MySQL, the returned result can expose LastInsertId.

fmt.Println(result.LastInsertId())
fmt.Println(result.RowsAffected())

PostgreSQL often uses RETURNING, so when you need the generated ID, db.Value is usually a better fit.

id, found, err := db.Value[int64](ctx, conn, `
	INSERT INTO users (name, email, active)
	VALUES ($1, $2, $3)
	RETURNING id
`, name, email, active)

Scylla often generates IDs in application code and writes them explicitly.

Update

Use Update when the statement modifies existing data.

result, err := db.Update(ctx, conn, `
	UPDATE users
	SET active = ?
	WHERE id = ?
`, active, id)

if err != nil {
	return err
}

fmt.Println(result.RowsAffected())

Update does not validate that the SQL statement is an UPDATE.

It is a readable wrapper around Exec.

Delete

Use Delete when the statement removes data.

result, err := db.Delete(ctx, conn, `
	DELETE FROM users
	WHERE id = ?
`, id)

if err != nil {
	return err
}

fmt.Println(result.RowsAffected())

Delete does not validate that the SQL statement is a DELETE.

It is a readable wrapper around Exec.

Result

Execution helpers return db.Result.

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

Use RowsAffected to inspect how many rows were changed.

affected := result.RowsAffected()

Use LastInsertId when the selected driver supports it.

id := result.LastInsertId()

Driver behavior differs:

DriverRowsAffectedLastInsertId
MySQLsupportedsupported
Postgressupportedusually 0; prefer RETURNING with Value
Scylladriver-specificusually not used

Placeholder Style

Execution helpers do not rewrite placeholders.

Use the placeholder style required by the selected driver.

DriverPlaceholder style
MySQL?
Postgres$1, $2, $3
Scylla?

MySQL example:

result, err := db.Update(ctx, conn, `
	UPDATE users
	SET active = ?
	WHERE id = ?
`, active, id)

PostgreSQL example:

result, err := db.Update(ctx, conn, `
	UPDATE users
	SET active = $1
	WHERE id = $2
`, active, id)

Scylla example:

result, err := db.Update(ctx, conn, `
	UPDATE users_by_id
	SET active = ?
	WHERE id = ?
`, active, id)

When to Use Each Helper

NeedUse
Execute any statementExec
Execute an existing db.QueryExecQuery
Communicate insert intentInsert
Communicate update intentUpdate
Communicate delete intentDelete
Return a value from a statementValue
Execute dialect-selected statementDialect + ExecQuery

Recommended Style

Use semantic helpers when the operation is clear.

result, err := db.Insert(ctx, conn, insertUserQuery, name, email, active)
result, err := db.Update(ctx, conn, updateUserQuery, active, id)
result, err := db.Delete(ctx, conn, deleteUserQuery, id)

Use Exec for generic statements.

result, err := db.Exec(ctx, conn, query, args...)

Use ExecQuery when working with db.Query.

q, err := db.Raw(query, args...)
if err != nil {
	return err
}

result, err := db.ExecQuery(ctx, conn, q)

Not an ORM

These helpers do not generate SQL and do not know what your statement does.

They are small execution helpers over explicit SQL or CQL.

You still control:

  • the statement text
  • placeholders
  • arguments
  • transaction boundaries
  • driver-specific behavior
  • schema and data model design

MapsDialect

Use db.MapsDialect to read dynamic map rows using driver-specific SQL selected from db.DialectSQL.

Insert

Insert rows using the shared DB API and understand driver-specific insert behavior.

On this page

OverviewExecExecQuerySemantic HelpersInsertUpdateDeleteResultPlaceholder StyleWhen to Use Each HelperRecommended StyleNot an ORM