Удалить текущую строку в sqlite3 при переборе набора результатов - PullRequest
3 голосов
/ 08 февраля 2011

Можно ли выполнить итерацию по набору результатов и, если условие выполнено, удалить текущую строку?

т.е. что-то вроде

int rc;
sqlite3_stmt* statement;
sqlite3_exec(db, "BEGIN", 0, 0, 0);

sqlite3_prepare_v2(_db, "SELECT id,status,filename,del FROM mytable", -1, &statement, NULL);

rc = sqlite3_step(statement);
while (rc == SQLITE_ROW){
  int id = sqlite3_column_int(statement, 1);
  int status = sqlite3_column_int(statement, 2);
  const unsigned char* filename = sqlite3_column_int(statement, 3);
  int del = sqlite3_column_int(statement, 4);

  if (status == 0 || del > 0){
    int rc = unlink(filename);
    if (rc == 0)
      // Now delete the current row
    else 
      // unlink failed, find out why, try again or ... ?
  } 

  rc = sqlite3_step(statement);
}
sqlite3_finalize(statement);
sqlite3_exec(db, "COMMIT", 0, 0, 0);

Я мог бы просто вызвать один SQL-оператор, чтобы удалить все строки, которые соответствуют критериям, но я не хочу этого делать, если по какой-то причине не удастся отсоединиться.

Можно ли вызвать операцию для удаления текущей строки?

EDIT: Так что есть специальный столбец под названием rowid. Должен ли я просто добавить это как столбец в предыдущий оператор и создайте другой оператор типа "удалить из таблицы, где rowid =?" и передать текущий rowid?

Это должно работать правильно? Это лучший способ сделать это?

1 Ответ

3 голосов
/ 08 февраля 2011

С точки зрения эффективности, это, вероятно, не самый эффективный. Если вы делаете это для чего-то на уровне тысяч или более строк, вам следует рассмотреть возможность выполнения одного (или комбинации) из следующих действий:

  • Измените ваш запрос, чтобы он учитывал только те строки, у которых del> 0 (SELECT id,status,filename,del FROM mytable WHERE del > 0). Вы выполняете сканирование таблицы с помощью вашего текущего метода, который вы всегда должны избегать. Также убедитесь, что у вас есть индекс в столбце del.

  • Создайте промежуточный массив идентификаторов строк, а затем выполните запрос следующей формы: DELETE FROM table WHERE id IN (?), и параметризованным значением будут ваши собранные идентификаторы строк, объединенные в строку через запятую. В зависимости от количества строк, с которыми вы работаете, вы можете установить удаление в пакетном режиме (удаление в пакетном размере 1000, 5000 и т. Д.); так как это SQLite, настройтесь на устройство, с которым вы работаете.

  • Зарегистрируйте пользовательскую функцию SQLite во время создания соединения, используя форму:

    void deleteFileFunc(sqlite3_context * context, int argc, sqlite3_value ** argv) {
      assert(argc == 1);
      const char * fileName = sqlite3_value_text(argv[0]);
      int rc = unlink(fileName);
      sqlite3_result_int(context, rc);
    }
    sqlite3_create_function(db, "delete_file", 1, SQLITE3_UTF8, NULL, &deleteFileFunc, NULL, NULL);
    

и измените запрос к базе данных на форму DELETE FROM mytable WHERE del > 0 AND delete_file(filename) == 0. Строка будет удалена только в том случае, если удаление выполнено успешно, и вам не нужно перебирать набор результатов. Страница создания функции SQLite 3: http://www.sqlite.org/c3ref/create_function.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...