Cегодня столкнулся с тем, что нужно было изменить уже созданные таблицы в базе данных SQLite. Поскольку понтовых менеждеров под рукой у меня нет, да я и не знаю об их существовании, пришлось все делать ручками, по старинке.
Для того, чтобы было понятно, что нужно было делать, приведу пример. Дана таблица, созданная следующим образом:
1 |
CREATE TABLE A (pk INTEGER PRIMARY KEY, name TEXT, cnt INTEGER); |
А теперь мы решили сделать поле count NOT NULL. Вопрос: как изменить таблицу «А» без потери данных?
Я нашел только «ручной» и «муторный» способ. Он заключается в следующем: создаем буферную таблицу temp1 нужным нам образом, т.е. как
1 |
CREATE TABLE temp1 (pk INTEGER PRIMARY KEY, name TEXT, cnt INTEGER NOT NULL); |
и перегоняем в нее данные через
1 |
INSERT INTO temp1 SELECT * FROM A; |
После этого можно удалить таблицу «А»:
1 |
DROP TABLE A; |
И переименовать temp в «A»:
1 |
ALTER TABLE temp1 RENAME TO A; |
Вроде бы все хорошо, но что делать, если в исходной таблице в нужном поле все-таки были значения NULL? Ведь тогда новая таблица останется пустой! (У меня кстати и никакого сообщения об ошибке не было – просто транзакция не проходила. Молча.)
Я нашел решение в создании еще одной буферной таблицы «temp2» с заданным для изменяемого поля значением по умолчанию. Создавалась она как:
1 |
CREATE TABLE temp2 (pk INTEGER PRIMARY KEY, name TEXT, cnt INTEGER NOT NULL DEFAULT 0); |
Соответственно, теперь нужно перегнать данные из таблицы А сначала в «temp2», где некорректные строчки превратятся в «подходящие», а уже потом в «temp1». После этого опять занимаемся переименованием последней :). Да, некоторые стоки данных изменятся, но зато основная информация сохранится. Естественно, хорошо бы не забыть удалить уже две лишние таблицы («А», и «temp2»).
Аналогичным образом можно поступить, если нужно будет добавить новое поле в таблицу, только INSERT в новую таблицу делать уже конкретных полей, а SELECT – по всей таблице.
P.S.: Наверняка, я изобрел свой велосипед с квадратными колесами, поэтому буду рад услышать, как выглядят «классические» решения для этих задач, если кто знает. А может даже и об удобных менеджерах для SQLite, чтобы не делать в следующий раз все «ручками».
Полезная статья? Их будет больше, если вы поддержите меня!