Почему я получаю ErrNoRows («sql: нет строк в наборе результатов») после вставки в postgres, даже если вставка была действительно успешной? - PullRequest
0 голосов
/ 27 ноября 2018

Я работаю с golang-postgres:

"database/sql"
_ "github.com/lib/pq"

Что я делаю:

Я запускаю запрос на выборку.Если я не получу ни одной записи по выбору, я добавлю ее.Иначе, обновить или что-то еще ...

Проблема , каждый раз, когда вставка возвращает ErrNoRows ("sql: нет строк в наборе результатов") , дажекогда я вижу в базе данных, что INSERT был успешным, и была добавлена ​​строка.

Также lastInsertID всегда остается 0, а если я проверяю в БД, он имеет фактическое значение (скажем, 131)

Кажется, что ошибка около комментария 2 ниже в коде, где-то кешируется и снова появляется.

// 1. Select first
sQueryStmt, sPrepErr := db.Prepare(selectQuery)
    if sPrepErr != nil {
        glog.V(3).Infof("selectQuery prepare failed. err: %v", sPrepErr)
        return sPrepErr
    }

    queryErr := sQueryStmt.QueryRow(today, itemID).Scan(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j)
    if queryErr != nil {

// 2. Getting ErrNoRows here is expected, for the first entry
        if queryErr == sql.ErrNoRows {
            glog.V(3).Infof("selectQuery returned no results. err: %v", queryErr)

            var lastInsertID int
            iQueryStmt, iPrepErr := db.Prepare(insertQuery)
            if iPrepErr != nil {
                glog.V(3).Infof("insertQuery prepare failed. err: %v", iPrepErr)
                return iPrepErr
            }
            insertErr := iQueryStmt.QueryRow(today, today, today, taskID).Scan(&lastInsertID)
            if insertErr != nil {
                // 3. Somehow, even after row is correctly being created, I am getting insertErr as "sql: no rows in result set" here
                glog.V(3).Infof("insertQuery failed. err: %v", insertErr)
            } else {
// control never comes to this part.
                glog.V(3).Infof("insertQuery Successful. lastInsertID: %v", lastInsertID)
            }
        } else {
            glog.V(3).Infof("Couldn't run query on Postgres database. err: %v", queryErr)
            return queryErr
        }
}

Отладка внутри database / sql , показывает, что возвращает эту ошибку в приведенном ниже блоке кода:

    if !r.rows.Next() {
        if err := r.rows.Err(); err != nil {
            return err
        }
        return ErrNoRows
    }

Но каждый раз, когда я проверяю в БД, данные всегда уже вставляются .

Редактировать:

selectQuery = `select task_id, creation_date, times_x_ran,
                        a_count, b_count, c_count, d_count, e_count 
                        from reports where creation_date = $1 and task_id = $2`

insertQuery = `insert into reports 
                (creation_date, creation_time, last_modified, task_id, times_x_ran, times_y_ran, a, b, c, d, e, x_errors, y_errors) 
                    values 
                    ($1, $2, $3, $4,
                    1, 0, 
                    0, 0, 0, 0, 0, 
                    '', '' )`

1 Ответ

0 голосов
/ 28 ноября 2018

Вы фактически задали два вопроса, поэтому я отвечу на оба:

  1. Почему ErrNoRows даже при успешной вставке?

    Это ожидаемое поведение, потому что по умолчанию INSERT не возвращает строк.Ваша "ошибка" на самом деле не является проблемой.Если вы хотите, чтобы INSERT возвращал строки, вы должны использовать предложение «RETURNING» в конце.

    Тот факт, что состояние «Нет строк в наборе результатов» сообщается из-за ошибки, может быть причинойдля вашего замешательства.Но это следует считать ошибкой , если вы ожидали строки .

  2. Также lastInsertID всегда остается 0.

    ЭтоТакже ожидается поведение.Как задокументировано :

    pq не поддерживает метод LastInsertId () типа Result в базе данных / sql.Чтобы вернуть идентификатор INSERT (или UPDATE или DELETE), используйте предложение Postgres RETURNING со стандартным вызовом Query или QueryRow:

...