Sunday, March 12, 2023
HomeGolangGo (Golang) MySQL tutorial to pick single and a number of rows

Go (Golang) MySQL tutorial to pick single and a number of rows


MySQL Collection Index

Connecting to MySQL and making a Database
Making a Desk and Inserting Rows
Deciding on Single Row and A number of rows
Ready statements – WIP
Updating rows – WIP
Deleting rows – WIP

Welcome to tutorial no. 3 in our MySQL tutorial sequence. Within the earlier tutorial, we mentioned making a desk and inserting rows into the desk. On this tutorial, we are going to discover ways to choose a single row in addition to a number of rows from a desk.

Deciding on a single row

The product desk we created within the earlier tutorial has three rows. Working choose * from product; on the desk returns the next rows.

On this part of the tutorial, we are going to write code to pick a single row from this desk. We’ll write a operate that may return the product value when the product identify is given because the enter. The question to do that is supplied under.

choose product_price from product the place product_name = "iphone";  

The above question will return one row and can return the product_price column from that row. The above question will return 950

Now that we have now the question prepared, let’s go forward and code it.

Step one is to create a ready assertion. Ready statements are used to parametrize a SQL question in order that the identical question might be run with totally different arguments effectively. It additionally prevents sql injection.

The template for the ready assertion is supplied under.

choose product_price from product the place product_name = ?  

We’ve got changed iphone with ? to create the ready assertion template.

The subsequent step is to create the ready assertion. That is carried out utilizing the PrepareContext methodology.

func selectPrice(db *sql.DB, productName string) (int, error) {  
    question := `choose product_price from product the place product_name = ?`
    ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancelfunc()
    stmt, err := db.PrepareContext(ctx, question)
    if err != nil {
        log.Printf("Error %s when making ready SQL assertion", err)
        return 0, err
    }
    defer stmt.Shut()
    ...
}

We move a context with a 5 second timeout to the PrepareContext methodology in line no. 5. This methodology returns a ready assertion. We defer closing the assertion in line no. 10.

The subsequent step is to execute this ready assertion. That is carried out utilizing the QueryRowContext methodology.

var value int  
row := stmt.QueryRowContext(ctx, productName)  
if err := row.Scan(&value); err != nil {  
    return 0, err
}

The QueryRowContext methodology is named on the ready assertion stmt. This methodology takes a context and a variadic record of arguments as parameter. In our case, we have now just one argument within the question which is the product identify and we move this because the argument to this methodology.

The QueryRowContext returns a single row. We then have to name Scan on the row to repeat the columns returned by the question to the pointer handed to the Scan methodology. Right here we move an integer pointer in line no. 3 of the above code snippet to which the worth might be saved. If the question returns multiple row, the Scan methodology will return solely the primary row and there might be no error. If there are not any rows returned, Scan will return an error. We’ll focus on error dealing with within the subsequent part.

The entire operate is supplied under.

func selectPrice(db *sql.DB, productName string) (int, error) {  
    log.Printf("Getting product value")
    question := `choose product_price from product the place product_name = ?`
    ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancelfunc()
    stmt, err := db.PrepareContext(ctx, question)
    if err != nil {
        log.Printf("Error %s when making ready SQL assertion", err)
        return 0, err
    }
    defer stmt.Shut()
    var value int
    row := stmt.QueryRowContext(ctx, productName)
    if err := row.Scan(&value); err != nil {
        return 0, err
    }
    return value, nil
}

Error dealing with

The Scan methodology utilized in line no. 14 of the above operate will return error ErrNoRows when no rows are returned by the question. Let’s name our selectPrice operate from important the place will deal with errors.

func important() {  
...
    productName := "iphone"
    value, err := selectPrice(db, productName)
    change {
    case err == sql.ErrNoRows:
        log.Printf("Product %s not present in DB", productName)
    case err != nil:
        log.Printf("Encountered err %s when fetching value from DB", err)
    default:
        log.Printf("Worth of %s is %d", productName, value)
    }
}

We move product identify as iphone to selectPrice after which change case on the error. If the error is of sort ErrNoRows we print a message saying that the product will not be discovered. In case of another error, we print the error message. And within the default case we print the end result.

This program will print

Worth of iphone is 950  


Deciding on a number of rows

On this part, we are going to discover ways to choose a number of rows from a desk. We’ll write a operate that may take minimal value and most value as parameters and return the identify and value of the merchandise that match the question.

The question that does that’s supplied under.

choose product_name, product_price from product the place product_price >= 900 && product_price <= 1000;  

The above question will return the identify and value of all merchandise whose costs fall between 900 and 1000.

A lot of the steps for choosing a number of rows are just like choosing a single row which we mentioned within the earlier part. I’ve supplied the entire operate to pick a number of rows under.

func selectProductsByPrice(db *sql.DB, minPrice int, maxPrice int) ([]product, error) {  
    log.Printf("Getting merchandise by value")
    question := `choose product_name, product_price from product the place product_price >= ? && product_price <= ?;`
    ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancelfunc()
    stmt, err := db.PrepareContext(ctx, question)
    if err != nil {
        log.Printf("Error %s when making ready SQL assertion", err)
        return []product{}, err
    }
    defer stmt.Shut()
    rows, err := stmt.QueryContext(ctx, minPrice, maxPrice)
    if err != nil {
        return []product{}, err
    }
    defer rows.Shut() 
    var merchandise = []product{}
    for rows.Subsequent() {
        var prd product
        if err := rows.Scan(&prd.identify, &prd.value); err != nil {
            return []product{}, err
        }
        merchandise = append(merchandise, prd)
    }
    if err := rows.Err(); err != nil {
        return []product{}, err
    }
    return merchandise, nil
}

Just like the earlier part, we first created a ready assertion in line no. 6 of the above operate. After that we name QueryContext methodology on the ready assertion stmt in line no. 12. This methodology will return the record of rows chosen by the question. We defer closing the rows in line no. 16.

After getting the row record, we name Subsequent methodology on rows in line no. 18. This prepares the end result for studying utilizing the Scan methodology. If there’s any error when calling Subsequent(), it’s going to return false and the for loop will terminate. In case of error, Err() methodology on rows will return a non nil worth and we have to name that to search out out if there was any error when Subsequent() was known as. That is carried out in line no. 25.

If there isn’t any error when fetching the rows, rows is closed mechanically by the Subsequent() methodology name in line no. 18. If there’s any error, it’s essential to name Shut explicitly. For the reason that name to Shut() is idempotent, it is alright to name it twice i.e as soon as through the efficiently Subsequent() name and once more throughout defer in line no. 16. Therefore we have now deferred the rows shut in line no. 16.

In line no. 19 we create prd of sort product to retailer the end result.

In case you do not bear in mind, product struct has the next fields.

sort product struct {  
    identify  string
    value int
}

In line no. 20, the end result columns are copied to the identify and value fields of the prd struct and in line no. 23, prd is appended to the merchandise slice.

merchandise is returned in line no. 28.

The subsequent step is to name this operate from important.

func important() {  
...
    minPrice := 900
    maxPrice := 1000
    merchandise, err := selectProductsByPrice(db, minPrice, maxPrice)
    if err != nil {
        log.Printf("Error %s when choosing product by value", err)
        return
    }
    for _, product := vary merchandise {
        log.Printf("Title: %s Worth: %d", product.identify, product.value)
    }

We move 900 and 1000 because the minimal and most value to the selectProductsByPrice operate in line no. 5.

If there’s any error, we return after printing the error.

If there isn’t any error, the identify and value of the merchandise matching the question are printed in line no. 11.

This program will print,

2021/10/16 21:10:52 Getting merchandise by value  
2021/10/16 21:10:52 Title: iphone Worth: 950  
2021/10/16 21:10:52 Title: Galaxy Worth: 990  

This brings us to the top of this tutorial. Please share your priceless suggestions within the feedback.

The whole code is out there at https://github.com/golangbot/mysqltutorial/blob/grasp/choose/important.go

If you want to promote on this web site, rent me, or when you have another improvement necessities, please e mail to naveen[at]golangbot[dot]com.

Like my tutorials? Please present your assist by donating. Your donations will assist me create extra superior tutorials.

Earlier tutorial – Making a Desk and Inserting Rows

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments