| <!--{ |
| "Title": "Querying for data" |
| }--> |
| |
| When executing an SQL statement that returns data, use one of the `Query` |
| methods provided in the `database/sql` package. Each of these returns a `Row` |
| or `Rows` whose data you can copy to variables using the `Scan` method. |
| You'd use these methods to, for example, execute `SELECT` statements. |
| |
| When executing a statement that doesn’t return data, you can use an `Exec` or |
| `ExecContext` method instead. For more, see |
| [Executing statements that don't return data](/doc/database/change-data). |
| |
| The `database/sql` package provides two ways to execute a query for results. |
| |
| * **Querying for a single row** – `QueryRow` returns at most a single `Row` |
| from the database. For more, see [Querying for a single row](#single_row). |
| * **Querying for multiple rows** – `Query` returns all matching rows as a |
| `Rows` struct your code can loop over. For more, see |
| [Querying for multiple rows](#multiple_rows). |
| |
| If your code will be executing the same SQL statement repeatedly, consider |
| using a prepared statement. For more, see |
| [Using prepared statements](/doc/database/prepared-statements). |
| |
| **Caution:** Don't use string formatting functions such as `fmt.Sprintf` to |
| assemble an SQL statement! You could introduce an SQL injection risk. For more, |
| see [Avoiding SQL injection risk](/doc/database/sql-injection). |
| |
| ### Querying for a single row {#single_row} |
| |
| `QueryRow` retrieves at most a single database row, such as when you want to |
| look up data by a unique ID. If multiple rows are returned by the query, the |
| `Scan` method discards all but the first. |
| |
| `QueryRowContext` works like `QueryRow` but with a `context.Context` argument. |
| For more, see [Canceling in-progress operations](/doc/database/cancel-operations). |
| |
| The following example uses a query to find out if there's enough inventory to |
| support a purchase. The SQL statement returns `true` if there's enough, `false` |
| if not. [`Row.Scan`](https://pkg.go.dev/database/sql#Row.Scan) copies the |
| boolean return value into the `enough` variable through a pointer. |
| |
| ``` |
| func canPurchase(id int, quantity int) (bool, error) { |
| var enough bool |
| // Query for a value based on a single row. |
| if err := db.QueryRow("SELECT (quantity >= ?) from album where id = ?", |
| quantity, id).Scan(&enough); err != nil { |
| if err == sql.ErrNoRows { |
| return false, fmt.Errorf("canPurchase %d: unknown album", id) |
| } |
| return false, fmt.Errorf("canPurchase %d: %v", id, err) |
| } |
| return enough, nil |
| } |
| ``` |
| |
| **Note:** Parameter placeholders in prepared statements vary depending on the |
| DBMS and driver you're using. For example, the |
| [pq driver](https://pkg.go.dev/github.com/lib/pq) for Postgres requires a |
| placeholder like `$1` instead of `?`. |
| |
| #### Handling errors {#single_row_errors} |
| |
| `QueryRow` itself returns no error. Instead, `Scan` reports any error from the |
| combined lookup and scan. It returns |
| [`sql.ErrNoRows`](https://pkg.go.dev/database/sql#ErrNoRows) when the query |
| finds no rows. |
| |
| #### Functions for returning a single row {#single_row_functions} |
| |
| <table id="single-row-functions-list" class="DocTable"> |
| <thead> |
| <tr class="DocTable-head"> |
| <th class="DocTable-cell" width="20%">Function</th> |
| <th class="DocTable-cell">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#DB.QueryRow">DB.QueryRow</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#DB.QueryRowContext">DB.QueryRowContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a single-row query in isolation.</td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Tx.QueryRow">Tx.QueryRow</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#Tx.QueryRowContext">Tx.QueryRowContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a single-row query inside a larger transaction. For more, see |
| <a href="/doc/database/execute-transactions">Executing transactions</a>. |
| </td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Stmt.QueryRow">Stmt.QueryRow</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#Stmt.QueryRowContext">Stmt.QueryRowContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a single-row query using an already-prepared statement. For more, |
| see <a href="/doc/database/prepared-statements">Using prepared statements</a>. |
| </td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Conn.QueryRowContext">Conn.QueryRowContext</a></code> |
| </td> |
| <td class="DocTable-cell">For use with reserved connections. For more, see |
| <a href="/doc/database/manage-connections">Managing connections</a>. |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| |
| ### Querying for multiple rows {#multiple_rows} |
| |
| You can query for multiple rows using `Query` or `QueryContext`, which return |
| a `Rows` representing the query results. Your code iterates over the returned |
| rows using [`Rows.Next`](https://pkg.go.dev/database/sql#Rows.Next). Each |
| iteration calls `Scan` to copy column values into variables. |
| |
| `QueryContext` works like `Query` but with a `context.Context` argument. For |
| more, see [Canceling in-progress operations](/doc/database/cancel-operations). |
| |
| The following example executes a query to return the albums by a specified |
| artist. The albums are returned in an `sql.Rows`. The code uses |
| [`Rows.Scan`](https://pkg.go.dev/database/sql#Rows.Scan) to copy column values |
| into variables represented by pointers. |
| |
| ``` |
| func albumsByArtist(artist string) ([]Album, error) { |
| rows, err := db.Query("SELECT * FROM album WHERE artist = ?", artist) |
| if err != nil { |
| return nil, err |
| } |
| defer rows.Close() |
| |
| // An album slice to hold data from returned rows. |
| var albums []Album |
| |
| // Loop through rows, using Scan to assign column data to struct fields. |
| for rows.Next() { |
| var alb Album |
| if err := rows.Scan(&alb.ID, &alb.Title, &alb.Artist, |
| &alb.Price, &alb.Quantity); err != nil { |
| return albums, err |
| } |
| albums = append(albums, alb) |
| } |
| if err = rows.Err(); err != nil { |
| return albums, err |
| } |
| return albums, nil |
| } |
| ``` |
| |
| Note the deferred call to [`rows.Close`](https://pkg.go.dev/database/sql#Rows.Close). |
| This releases any resources held by the rows no matter how the function |
| returns. Looping all the way through the rows also closes it implicitly, |
| but it is better to use `defer` to make sure `rows` is closed no matter what. |
| |
| **Note:** Parameter placeholders in prepared statements vary depending on |
| the DBMS and driver you're using. For example, the |
| [pq driver](https://pkg.go.dev/github.com/lib/pq) for Postgres requires a |
| placeholder like `$1` instead of `?`. |
| |
| #### Handling errors {#multiple_rows_errors} |
| |
| Be sure to check for an error from `sql.Rows` after looping over query results. |
| If the query failed, this is how your code finds out. |
| |
| #### Functions for returning multiple rows {#multiple_rows_functions} |
| |
| <table id="multiple-row-functions-list" class="DocTable"> |
| <thead> |
| <tr class="DocTable-head"> |
| <th class="DocTable-cell" width="20%">Function</th> |
| <th class="DocTable-cell">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#DB.Query">DB.Query</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#DB.QueryContext">DB.QueryContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a query in isolation.</td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Tx.Query">Tx.Query</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#Tx.QueryContext">Tx.QueryContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a query inside a larger transaction. For more, see |
| <a href="/doc/database/execute-transactions">Executing transactions</a>. |
| </td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Stmt.Query">Stmt.Query</a></code><br /> |
| <code><a href="https://pkg.go.dev/database/sql#Stmt.QueryContext">Stmt.QueryContext</a></code> |
| </td> |
| <td class="DocTable-cell">Run a query using an already-prepared statement. For more, see |
| <a href="/doc/database/prepared-statements">Using prepared |
| statements</a>. |
| </td> |
| </tr> |
| <tr class="DocTable-row"> |
| <td class="DocTable-cell"> |
| <code><a href="https://pkg.go.dev/database/sql#Conn.QueryContext">Conn.QueryContext</a></code> |
| </td> |
| <td class="DocTable-cell">For use with reserved connections. For more, see |
| <a href="/doc/database/manage-connections">Managing connections</a>. |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| |
| ### Handling nullable column values {#nullable_columns} |
| |
| The `database/sql` package provides several special types you can use as |
| arguments for the `Scan` function when a column's value might be null. Each |
| includes a `Valid` field that reports whether the value is non-null, and a |
| field holding the value if so. |
| |
| Code in the following example queries for a customer name. If the name value |
| is null, the code substitutes another value for use in the application. |
| |
| ``` |
| var s sql.NullString |
| err := db.QueryRow("SELECT name FROM customer WHERE id = ?", id).Scan(&s) |
| if err != nil { |
| log.Fatal(err) |
| } |
| |
| // Find customer name, using placeholder if not present. |
| name := "Valued Customer" |
| if s.Valid { |
| name = s.String |
| } |
| ``` |
| |
| See more about each type in the `sql` package reference: |
| |
| * [`NullBool`](https://pkg.go.dev/database/sql#NullBool) |
| * [`NullFloat64`](https://pkg.go.dev/database/sql#NullFloat64) |
| * [`NullInt32`](https://pkg.go.dev/database/sql#NullInt32) |
| * [`NullInt64`](https://pkg.go.dev/database/sql#NullInt64) |
| * [`NullString`](https://pkg.go.dev/database/sql#NullString) |
| * [`NullTime`](https://pkg.go.dev/database/sql#NullTime) |
| |
| ### Getting data from columns {#column_data} |
| |
| When looping over the rows returned by a query, you use `Scan` to copy a row’s |
| column values into Go values, as described in the |
| [`Rows.Scan`](https://pkg.go.dev/database/sql#Rows.Scan) reference. |
| |
| There is a base set of data conversions supported by all drivers, such as |
| converting SQL `INT` to Go `int`. Some drivers extend this set of conversions; |
| see each individual driver's documentation for details. |
| |
| As you might expect, `Scan` will convert from column types to Go types that |
| are similar. For example, `Scan` will convert from SQL `CHAR`, `VARCHAR`, and |
| `TEXT` to Go `string`. However, `Scan` will also perform a conversion to |
| another Go type that is a good fit for the column value. For example, if the |
| column is a `VARCHAR` that will always contain a number, you can specify a |
| numeric Go type, such as `int`, to receive the value, and `Scan` will convert |
| it using `strconv.Atoi` for you. |
| |
| For more detail about conversions made by the `Scan` function, see the [`Rows.Scan`](https://pkg.go.dev/database/sql#Rows.Scan) reference. |
| |
| ### Handling multiple result sets {#multiple_result_sets} |
| |
| When your database operation might return multiple result sets, you can |
| retrieve those by using |
| [`Rows.NextResultSet`](https://pkg.go.dev/database/sql#Rows.NextResultSet). |
| This can be useful, for example, when you're sending SQL that separately queries |
| multiple tables, returning a result set for each. |
| |
| `Rows.NextResultSet` prepares the next result set so that a call to |
| `Rows.Next` retrieves the first row from that next set. It returns a boolean |
| indicating whether there is a next result set at all. |
| |
| Code in the following example uses `DB.Query` to execute two SQL statements. |
| The first result set is from the first query in the procedure, retrieving all |
| of the rows in the `album` table. The next result set is from the second query, |
| retrieving rows from the `song` table. |
| |
| ``` |
| rows, err := db.Query("SELECT * from album; SELECT * from song;") |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer rows.Close() |
| |
| // Loop through the first result set. |
| for rows.Next() { |
| // Handle result set. |
| } |
| |
| // Advance to next result set. |
| rows.NextResultSet() |
| |
| // Loop through the second result set. |
| for rows.Next() { |
| // Handle second set. |
| } |
| |
| // Check for any error in either result set. |
| if err := rows.Err(); err != nil { |
| log.Fatal(err) |
| } |
| ``` |