Как проверить наличие данных в таблице по конкретному параметру? (язык GO)
На данный момент имею следующую таблицу:
merchant_id | order_id | amount
Логика приложения заключается в том, что я создаю мерчантов с уникальным именем, затем эти мерчанты создают неограниченное количество ордеров, id которых может иметь одинаковое значение
На данный момент я создаю мерчантов и имею этот код
row := db.QueryRow("select * from deals where merchant_id = $1", mr.MerchantID)
err = row.Scan(&mr.MerchantID)
if err != nil {
result1, _ := db.Exec("insert into deals (merchant_id, order_id, blocked_amount, charged_amount) values ($1, $2, $3, $4)",
mr.MerchantID, "", 0, 0)
fmt.Println(result1.RowsAffected())
} else {
fmt.Println("merchantID exists, try another")
Я рассчитывал на то, что Query поможет мне определить есть ли данный мерчант в таблице, если есть - он говори что такой уже существует, если нет - он создает его и записывает в таблицу, но на данный момент этот код регистрирует мерчантов с одинаковым именем
Сначала думал поставить ограничение уникальности на мерчантов, но это тогда дальше не смогу сделать неуникальные ордеры и к тому же мне не нужна паника
Видел что люди пользуются exists, но как применить его в GO в VisualStudio не понял
Ответы (1 шт):
Если бы вы распечатали текст ошибки внутри if-а, то увидели бы, что ошибка вовсе не sql.ErrNoRows. Вам select возвращает три значения, а в Scan вы запрашиваете всего один. Соответственно, у вас там ошибка sql: expected 3 destination arguments in Scan, not 1
Либо в select запрашивайте одно значение (например, "select merchant_id from deals where merchant_id = $1"), либо в Scan передавайте три параметра.
Работающий пример
package main
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
func main() {
database, err :=
sql.Open("sqlite3", "./some.db")
if err != nil {
panic(err)
}
statement, _ :=
database.Prepare("CREATE TABLE IF NOT EXISTS deals (merchant_id varchar, order_id varchar, amount real)")
statement.Exec()
statement, _ =
database.Prepare("INSERT INTO deals VALUES (?, ?,?)")
statement.Exec("Merchant", "order112345", 123.45)
row := database.QueryRow("SELECT merchant_id FROM deals where merchant_id = ?", "Merchant")
var mrchnt string
// var orderid string
// var amnt float64
err = row.Scan(&mrchnt)
if err == sql.ErrNoRows {
fmt.Println("No rows: ", err.Error())
} else if err != nil {
fmt.Println("Unexpected error: ", err.Error())
} else {
fmt.Println(mrchnt)
}
row = database.QueryRow("SELECT merchant_id FROM deals where merchant_id = ?", "Merchant2")
err = row.Scan(&mrchnt)
if err == sql.ErrNoRows {
fmt.Println("No rows: ", err.Error())
} else if err != nil {
fmt.Println("Unexpected error: ", err.Error())
} else {
fmt.Println(mrchnt)
}
}
Вывод:
Merchant
No rows: sql: no rows in result setMerchant
Функция для проверки существования кортежаза по значеню одного из полей:
func CheckRowExists(db *sql.DB, table, column string, value interface{}) (bool, error) {
query := fmt.Sprintf("SELECT %s FROM %s where %s = ? limit 1", column, table, column)
row := db.QueryRow(query, value)
var tmp interface{}
err := row.Scan(&tmp)
if err == sql.ErrNoRows {
return false, nil
}
if err == nil {
return true, nil
}
return false, err
}
Для параметров используется знак ?. Это нотация sqlite. Вам в постгресе нужно использовать $1.