Мне нужно изменить все содержимое таблицы. Поэтому я оборачиваю изменения внутри транзакции, чтобы гарантировать, что либо все операции пройдут успешно, либо ни одна из них не завершится. Я начинаю модификации с оператора DELETE, за которым следуют INSERT. Я обнаружил, что даже если INSERT завершается неудачно, DELETE все еще выполняется, и база данных не откатывается до состояния до транзакции.

Я создал пример, чтобы продемонстрировать эту проблему. Поместите следующие команды в сценарий под названием EXAMPLE.SQL

CREATE TABLE A(id INT PRIMARY KEY, val TEXT);

INSERT INTO A VALUES(1, “hello”);

BEGIN;
     DELETE FROM A;
     INSERT INTO A VALUES(1, “goodbye”);  
     INSERT INTO A VALUES(1, “world”);
COMMIT;

     SELECT * FROM A;

Если вы запустите сценарий: «sqlite3 a.db

SQL error near line 10: column id is not unique
1|goodbye

Что удивительно, так это то, что в результатах оператора SELECT не было «1 | hello».

Казалось бы, DELETE был успешным, а первый INSERT был успешным. Но когда второй INSERT завершился неудачно (как и предполагалось)… он не ОТКАТИЛ базу данных.

Это ошибка sqlite? Или ошибка в моем понимании того, что должно произойти?

Благодарность

1
user590028 6 Май 2014 в 16:42

2 ответа

Лучший ответ

Работает как надо.

COMMIT совершает все операции в транзакции. Тот, который связан с world, имел проблемы, поэтому он не был включен в транзакцию.

Чтобы отменить транзакцию, используйте ROLLBACK, а не COMMIT. Нет автоматического ROLLBACK, если вы не укажете его как разрешение конфликта, например, INSERT OR ROLLBACK INTO ....

И используйте одинарные кавычки ' вместо для строковых литералов.

3
laalto 6 Май 2014 в 12:47

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

SQLITE_FULL: database or disk full
SQLITE_IOERR: disk I/O error
SQLITE_BUSY: database in use by another process
SQLITE_NOMEM: out or memory
SQLITE_INTERRUPT: processing interrupted by application request 

Для других типов ошибок вам нужно будет отловить ошибку и выполнить откат, подробнее об этом рассказывается в этот ТАК вопрос.

0
Community 23 Май 2017 в 10:32