Функция SQLite changes () сообщает о 0 изменениях строк в определенных операторах удаления - PullRequest
2 голосов
/ 23 марта 2012

Недавно я обнаружил функцию CHANGES(), доступную внутри SQLite .Я делаю что-то вроде следующего в моем коде Android:

db.execSQL(sqlStatement, argumentArray);
int result;
SQLiteStatement stmt = db.compileStatement("SELECT CHANGES()");
try {
    return stmt.simpleQueryForLong();
} finally {
    stmt.close();
}

Что я вижу, что я получаю хорошие данные для всех утверждений, таких как:

UPDATE `footable` SET `stuff` = 'fepojefpjo'   (returns 1 row updated)
DROP TABLE `footable`                          (returns 2 rows dropped)
DELETE FROM `footable` WHERE `id` IN (?,?)     (returns 2 rows deleted)

Но явсегда получаю 0 измененных строк, когда я выполняю следующую инструкцию - даже если есть определенные строки, которые были удалены:

DELETE FROM `footable`                         (always returns 0)

Поскольку я удаляю все из таблицы, мне интересно, выполняет ли SQLite какой-либо видоперации усечения под крышками.Если я просто добавлю мусор WHERE 1 в конец оператора, он вернёт нужное количество строк.

DELETE FROM `footable` WHERE 1                 (works)

Вопросы:

  1. Можеткто-нибудь подтверждает это поведение?Можно ли этого ожидать?
  2. Обрезает ли SQLite таблицу здесь?
  3. Помимо подсчета строк до DELETE, есть ли способ обойти эту проблему??

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Я думаю, что это, скорее всего, связано с так называемой Truncate Optimization (я говорю, скорее всего, потому что я не уверен, какую версию SQLite вы используете). Когда нет условия WHERE, SQLite использует оптимизацию для удаления всего содержимого таблицы без необходимости посещения каждой строки таблицы по отдельности. См. справочные документы для DELETE .

Обратите внимание, что это поведение исправлено начиная с 3.6.5.

1 голос
/ 23 марта 2012

От: веб-сайт SQLite

Когда WHERE опущен в операторе DELETE, а в удаляемой таблице нет триггеров, SQLite использует оптимизацию для удаления всего содержимого таблицы без необходимости посещения каждой строки таблицы по отдельности. Эта «усеченная» оптимизация делает удаление намного быстрее. До SQLite версии 3.6.5 оптимизация усечения также означала, что интерфейсы sqlite3_changes () и sqlite3_total_changes () и прагма count_changes фактически не будут возвращать количество удаленных строк. Эта проблема была исправлена ​​в версии 3.6.5.

Оптимизацию усечения можно навсегда отключить для всех запросов, перекомпилировав SQLite с переключателем времени компиляции SQLITE_OMIT_TRUNCATE_OPTIMIZATION.

Оптимизацию усечения также можно отключить во время выполнения с помощью интерфейса sqlite3_set_authorizer (). Если обратный вызов Authorizer возвращает SQLITE_IGNORE для кода действия SQLITE_DELETE, то операция DELETE будет продолжена, но оптимизация усечения будет обойдена, и строки будут удалены одна за другой.

...