Ссылка на существующий параметр в подготовленном операторе при upsert

#sql #sqlite #sql-update #prepared-statement #sql-insert

#sql #sqlite #sql-обновление #подготовленный оператор #sql-вставка

Вопрос:

Я вставляю или обновляю строку в базу данных Sqlite с database/sql помощью пакета Go. У меня есть много столбцов для обновления (около 16 столбцов одного элемента). Для использования UPSERT мне нужно дублировать все ? и параметры полей данных оператора, поэтому общее количество параметров оператора составляет около 32:

 // Save item to database using transaction
func (item *Item) Save(tx *sql.Tx) error {
  stmt, err := tx.Prepare(`INSERT INTO "items" (
    id, data1, data2, ..., dataN
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id)
  DO UPDATE SET data1 = ?, data2 = ?, ..., dataN = ?`) // set same values as insert
  // skip checking errors, defer close(), etc
  _, err := stmt.Exec(item.id,
                      item.data1, item.data2, /*...*/ item.dataN,
                      item.data1, item.data2, /*...*/ item.dataN) // duplicates
}
  

Можно ли избежать дублирования и ссылаться на одни и те же параметры из INSERT и DO UPDATE ?

Ответ №1:

В SQLite вы можете использовать псевдотаблицу excluded в DO UPDATE предложении для ссылки на значения, которые были бы вставлены в противном случае:

 INSERT INTO "items" (id, data1, data2, data3)
VALUES (?, ?, ?, ?) 
ON CONFLICT(id) DO UPDATE SET 
    data1 = excluded.data1, 
    data2 = excluded.data2,
    data3 = excluded.data3