Как я могу игнорировать сбои вставки sqlite3, чтобы позволить сценарию tcl продолжить работу после сбоя?

#sqlite #try-catch #tcl

#sqlite #попробуйте-catch #tcl

Вопрос:

Урезанный, что я пытаюсь сделать, это следующее

 set selectQuery "SELECT col1, col2 FROM tableName" 

db1 eval $selectQuery {
   set insertQuery "INSERT INTO tableName VALUES($col1, $col2)"
   db2 eval $insertQuery {
      # Do trivial stuff to show progress
   }
}
  

который в основном копирует содержимое db1.tableName в db2.tableName.
Проблема в том, что в моем случае большая часть содержимого db1.tableName уже существует в db2.tableName. Итак, в принципе, я просто хочу скопировать то, что еще не существует, поэтому я подумал, что просто вставлю все и позволю вставкам завершиться неудачно, когда данные уже есть. Это не работает, потому что весь скрипт останавливается, как только одна вставка завершается неудачей. Я пытался использовать catch, чтобы проигнорировать сбой и разрешить сценарию продолжить, но у меня не получилось. Есть идеи?

Кроме того, может быть лучший способ скопировать содержимое db1.tableName в db2.tableName без копирования того, что там уже есть… Любая помощь будет оценена!

Шон

P.S Если у вас есть идеи для лучшего названия, это также было бы полезно..

Комментарии:

1. Не можете ли вы просто [catch] выполнить оценку команды вставки? Смотрите wiki.tcl.tk/catch

2. Пожалуйста, заключите ваш SQL в {фигурные скобки}. Это позволяет SQLite автоматически использовать подготовленные инструкции, что повышает как безопасность, так и скорость.

3. @Donal Fellows: Спасибо, мне действительно нужна скорость в этом конкретном случае, поэтому я попробую!

4. @Donal Fellows: Я только что прочитал, что использование фигурных скобок не приведет к замене. Мне нужна замена, поэтому, я думаю, я должен придерживаться кавычек?

Ответ №1:

В Sqlite есть конструкция INSERT ИЛИ REPLACE INTO, которая может быть полезна в этом случае.

http://www.sqlite.org/lang_insert.html

Ответ №2:

Хотя я не знаком с вашими командами API базы данных, поэтому я не могу прокомментировать, как вы просматриваете результаты запроса, но я могу предложить несколько вещей.

Сначала попробуйте перехватить еще раз. Я всегда нахожу такое использование немного странным, но в конце концов вы к нему привыкаете. Вот пример:

 if { [catch { db2 eval $insertQuery} errmsg] } {
    #There was an error - it is stored in $errmsg"
} else {
    #success! Congratulations.
}
  

В вашем случае, я полагаю, вы просто хотите игнорировать любые ошибки вставки, поэтому вы можете просто сделать:

 set selectQuery "SELECT col1, col2 FROM tableName" 

db1 eval $selectQuery {
   set insertQuery "INSERT INTO tableName VALUES($col1, $col2)"
   if { ![catch { db2 eval $insertQuery} errmsg] } {
      # Do trivial stuff to show progress
   }
}
  

Вы также могли бы попробовать сначала выполнить запрос и поместить результаты запроса в список TCL (или список списков) — затем выполните foreach в списке, выполнив вставки. Иногда базы данных могут быть забавными по поводу изменения данных, хотя в вашем случае это совсем не похоже на то, что происходит.

Комментарии:

1. SQL должен быть в {фигурных скобках}, а не в «кавычках», чтобы избежать неприятных цитат SQL. Избавьте себя от лишних хлопот и сделайте это прямо сейчас. 🙂