Как переименовать столбец в таблице базы данных SQLite? - PullRequest
273 голосов
/ 30 апреля 2009

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

Из документации SQLite для ALTER TABLE я понял, что невозможно сделать это "легко" (т. Е. Одним оператором ALTER TABLE).

Мне было интересно, кто-то знал об общем способе SQL сделать такое с SQLite.

Ответы [ 15 ]

433 голосов
/ 30 апреля 2009

Скажем, у вас есть таблица и вам нужно переименовать "colb" в "col_b":

Сначала вы переименуете старую таблицу:

ALTER TABLE orig_table_name RENAME TO tmp_table_name;

Затем создайте новую таблицу на основе старой таблицы, но с обновленным именем столбца:

CREATE TABLE orig_table_name (
  col_a INT
, col_b INT
);

Затем скопируйте содержимое напротив исходной таблицы.

INSERT INTO orig_table_name(col_a, col_b)
SELECT col_a, colb
FROM tmp_table_name;

Наконец, отбросьте старую таблицу.

DROP TABLE tmp_table_name;

Заключение всего этого в BEGIN TRANSACTION; и COMMIT; также, вероятно, хорошая идея.

53 голосов
/ 13 июля 2011

Хотя верно то, что ALTER COLUMN отсутствует, если вы хотите переименовать только столбец, удалить ограничение NOT NULL или изменить тип данных, вы можете использовать следующий набор команд:

Примечание. Эти команды могут повредить вашу базу данных, поэтому убедитесь, что у вас есть резервная копия

PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;

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

Например:

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
Error: BOOKS.publication_date may not be NULL  
sqlite> PRAGMA writable_schema = 1; 
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';  
sqlite> PRAGMA writable_schema = 0;  
sqlite> .q  

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
sqlite> .q  

ССЫЛКИ НА СЛЕДУЮЩУЮ:


Прагма Writable_schema
Когда эта прагма включена, таблицы SQLITE_MASTER, в которых база данных может быть изменена с помощью обычных операторов UPDATE, INSERT и DELETE. Предупреждение: неправильное использование этой прагмы может легко привести к повреждению файла базы данных.

изменить таблицу
SQLite поддерживает ограниченное подмножество ALTER TABLE. Команда ALTER TABLE в SQLite позволяет пользователю переименовать таблицу или добавить новый столбец в существующую таблицу. Невозможно переименовать столбец, удалить столбец или добавить или удалить ограничения из таблицы.

ALTER TABLE SYNTAX

53 голосов
/ 30 апреля 2009

Покопавшись, я нашел этот мультиплатформенный (Linux | Mac | Windows) графический инструмент под названием DB Browser для SQLite , который фактически позволяет переименовывать столбцы очень удобным для пользователя способом!

Редактировать | Изменить таблицу | Выберите таблицу | Редактировать поле. Нажмите, нажмите! Voila!

Однако, если кто-то хочет поделиться программным способом сделать это, я был бы рад узнать!

36 голосов
/ 15 сентября 2018

Это было исправлено с помощью 2018-09-15 (3.25.0)

Улучшает команду ALTER TABLE:

  • Добавлена ​​поддержка переименования столбцов в таблице с использованием ALTER TABLE table RENAME COLUMN oldname TO newname.
  • Исправлена ​​функция переименования таблицы, чтобы она также обновляла ссылки на переименованную таблицу в триггерах и представлениях.

Вы можете найти новый синтаксис, задокументированный под ALTER TABLE

Синтаксис RENAME COLUMN TO изменяет имя столбца таблицы table-name на new-column-name. Имя столбца изменяется как в самом определении таблицы, так и во всех индексах, триггерах и представлениях, которые ссылаются на столбец. Если изменение имени столбца приведет к семантической неоднозначности в триггере или представлении, то RENAME COLUMN завершится неудачно с ошибкой, и изменения не будут применены.

enter image description here Источник изображения: https://www.sqlite.org/images/syntax/alter-table-stmt.gif

Пример:

CREATE TABLE tab AS VALUES(1);

SELECT * FROM tab;

ALTER TABLE tab RENAME TO tab_new;

SELECT * FROM tab_new;

Демоверсия db-fiddle.com


Поддержка Android

На момент написания статьи API Android 27 использует пакет SQLite версии 3.19 .

Исходя из текущей версии, которую использует Android, и того, что это обновление будет выпущено в версии 3.25.0 SQLite, я бы сказал, что вам нужно немного подождать (примерно API 33), прежде чем поддержка этого будет добавлена ​​в Android. 1054 *

И даже в этом случае, если вам потребуется поддерживать какие-либо версии, более старые, чем API 33, вы не сможете использовать это.

18 голосов
/ 17 октября 2011

Недавно мне пришлось сделать это в SQLite3 с таблицей с именем points с столбцами id, lon, lat . Ошибочно, когда таблица была импортирована, значения широты хранятся в столбце lon и наоборот, поэтому очевидным решением будет переименование этих столбцов. Итак, хитрость была:

create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;

Надеюсь, это будет полезно для вас!

12 голосов
/ 30 апреля 2009

Цитирование документации sqlite :

SQLite поддерживает ограниченное подмножество ALTER TABLE. Команда ALTER TABLE в SQLite позволяет пользователю переименовать таблица или добавить новый столбец в существующая таблица. Невозможно переименовать столбец, удалить столбец или добавить или удалить ограничения из таблицы.

Конечно, вы можете создать новую таблицу с новым макетом SELECT * FROM old_table и заполнить новую таблицу значениями, которые вы получите.

7 голосов
/ 03 мая 2014

Во-первых, это одна из тех вещей, которая удивляет меня: переименование столбца требует создания совершенно новой таблицы и копирования данных из старой таблицы в новую таблицу ...

GUI, к которому я подключился для выполнения операций SQLite: Base . У него есть отличное окно журнала, которое показывает все команды, которые были выполнены. При переименовании столбца через Base заполняется окно журнала необходимыми командами:

Base log window

Затем их можно легко скопировать и вставить там, где они могут вам понадобиться. Для меня это файл миграции ActiveAndroid . Приятно также то, что скопированные данные содержат только команды SQLite, а не временные метки и т. Д.

Надеюсь, это экономит время некоторых людей.

3 голосов
/ 24 июня 2015

изменить столбец таблицы на <_id>

 String LastId = "id";

    database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
    +"("
            + PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
            + PhraseContract.COLUMN_PHRASE + " text ,"
            + PhraseContract.COLUMN_ORDER  + " text ,"
            + PhraseContract.COLUMN_FROM_A_LANG + " text"
    +")"
    );
    database.execSQL("INSERT INTO " +
            PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
            " SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
            " FROM " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");
2 голосов
/ 14 января 2018

Из официальной документации

Более простую и быструю процедуру можно при желании использовать для некоторых изменений, которые никак не влияют на содержимое на диске. Следующая более простая процедура подходит для удаления ограничений CHECK, FOREIGN KEY или NOT NULL, переименования столбцов , добавления, удаления или изменения значений по умолчанию для столбца.

  1. Начать транзакцию.

  2. Запустите PRAGMA schema_version, чтобы определить номер текущей версии схемы. Этот номер понадобится для шага 6 ниже.

  3. Активировать редактирование схемы с помощью PRAGMA writable_schema = ON.

  4. Запустите оператор UPDATE, чтобы изменить определение таблицы X в таблице sqlite_master: UPDATE sqlite_master SET sql = ... WHERE type = 'table' AND name = 'X';

    Осторожно: внесение такого изменения в таблицу sqlite_master сделает базу данных поврежденной и нечитаемой, если изменение содержит синтаксическую ошибку. Рекомендуется провести тщательное тестирование оператора UPDATE в отдельной пустой базе данных, прежде чем использовать его в базе данных, содержащей важные данные.

  5. Если изменение таблицы X также влияет на другие таблицы, индексы или триггеры являются представлениями в схеме, то запустите операторы UPDATE, чтобы изменить индексы и представления этих других таблиц. Например, если имя столбца изменяется, все ограничения, триггеры, индексы и представления FOREIGN KEY, которые ссылаются на этот столбец, должны быть изменены.

    Внимание: еще раз внесение изменений в таблицу sqlite_master, как это сделает базу данных поврежденной и нечитаемой, если изменение содержит ошибку. Тщательно протестируйте всю эту процедуру в отдельной тестовой базе данных, прежде чем использовать ее в базе данных, содержащей важные данные, и / или сделайте резервные копии важных баз данных, прежде чем выполнять эту процедуру.

  6. Увеличьте номер версии схемы с помощью PRAGMA schema_version = X, где X на единицу больше, чем номер версии старой схемы, найденный на шаге 2 выше.

  7. Отключить редактирование схемы с помощью PRAGMA writable_schema = OFF.

  8. (Необязательно) Запустите PRAGMA unity_check, чтобы убедиться, что изменения схемы не повредили базу данных.

  9. Подтвердите транзакцию, начатую на шаге 1 выше.

2 голосов
/ 02 августа 2016

Создайте новый столбец с нужным именем столбца: COLNew.

ALTER TABLE {tableName} ADD COLUMN COLNew {type};

Копировать содержимое старого столбца COLOld в новый столбец COLNew.

INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}

Примечание: скобки необходимы в строке выше.

...