Как переименовать столбец в таблице базы данных SQLite?

264

Мне нужно переименовать несколько столбцов в некоторых таблицах в базе данных SQLite. Я знаю, что ранее вопрос https://stackoverflow.com/questions/174582/how-do-i-rename-a-column-in-a-database-table-using-sql

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

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

  • 0
    Вы можете сделать это, используя db browser для sqlite довольно легко
  • 1
    Пожалуйста, пометьте этот ответ как принятый stackoverflow.com/a/52346199/124486
Теги:
alter-table

13 ответов

6
Лучший ответ

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

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

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

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

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

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

  • 5
    Я реализую миграцию на Android и, к сожалению, IntelliJ показывает предупреждение, что это недопустимая команда SQL. database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount") . COLUM выделен красным цветом и говорит, что ожидается, получил «COLUMN» . К сожалению, Android все еще работает на SQLite версии 3.19, поэтому у меня это не работает.
  • 0
    Я опробовал последний пакет NuGet System.Data.SQLite (1.0.109.2) в тестовом консольном приложении .NET (версия 4.7.2), но безуспешно - получил ошибку логики SQL рядом с "COLUMN": синтаксическая ошибка. Разве эта версия 3.25.0 не является частью пакета nuget?
Показать ещё 6 комментариев
402

Скажите, что у вас есть таблица и вам нужно переименовать "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; также, вероятно, хорошая идея.

  • 48
    И не забывайте свои показатели.
  • 9
    Очень важно, что в приведенном выше примере кода отсутствует транзакция. Вы должны обернуть все это в BEGIN / END (или ROLLBACK), чтобы убедиться, что переименование завершено успешно или не завершено вообще.
Показать ещё 15 комментариев
53

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

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

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

  • 1
    Существует также дополнение Firefox, которое делает то же самое : щелкните правой кнопкой мыши столбец, который вы хотите переименовать, и выберите «Редактировать столбец».
  • 1
    Даже в openSUSE он доступен в виде пакета: software.opensuse.org/package/sqlitebrowser
Показать ещё 3 комментария
51

Хотя верно, что нет 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  

ССЫЛКИ ПОСЛЕДУЮЩИЕ:


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

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

Изображение 1119

  • 3
    Опасный, но все же, вероятно, самый прямой ответ ИМО.
  • 1
    Хотя это опасно, будет ли это наиболее эффективным способом переименования столбца (лучше, чем создание новой таблицы, копирование данных и удаление старой таблицы)? Кроме того, это действительно так опасно? Это кажется склонным к ошибкам, но если я не ошибаюсь, оператор UPDATE обернут в транзакцию, поэтому он должен быть защищен от внезапных сбоев питания, исключений нехватки памяти и т. Д.
Показать ещё 6 комментариев
17

Недавно мне пришлось сделать это в 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;

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

  • 0
    Этот метод не копирует значение PK надлежащим образом и автоматически создает скрытый столбец rowid. Не обязательно проблема, но хотел указать на это, потому что это стало проблемой для меня.
  • 3
    Разве не проще было бы сделать «ОБНОВЛЕНИЕ точек: SET lon = lat, lat = lon;»?
Показать ещё 1 комментарий
10

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

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

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

7

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

Графический интерфейс, на который я применил операции SQLite, - Base. Он получил отличное окно журнала, в котором отображаются все команды, которые были выполнены. Выполнение переименования столбца через Base заполняет окно журнала необходимыми командами:

Изображение 1120

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

Надеюсь, это спасет людей.

  • 0
    FYI, если вы используете ActiveAndroid, вы можете опустить BEGIN TRANSACTION; и COMMIT; линии, как ActiveAndroid обрабатывает это самостоятельно.
3

изменить столбец таблицы <id> to < _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

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

Более простая и быстрая процедура может быть произвольно использована для некоторых изменений, которые никак не влияют на содержимое на диске. Следующая упрощенная процедура подходит для удаления ограничений 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 integrity_check, чтобы убедиться, что изменения схемы не повредили базу данных.

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

  • 0
    PRAGMA unity_check не обнаруживает никаких ошибок со схемой.
  • 0
    и в чем проблема с этим?
2

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

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

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

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

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

2

Как упоминалось ранее, есть инструмент SQLite Database Browser, который делает это. Lyckily, этот инструмент хранит журнал всех операций, выполняемых пользователем или приложением. Сделав это один раз и просмотрев журнал приложений, вы увидите код. Скопируйте запрос и вставьте его по мере необходимости. Работал для меня. Надеюсь, что это поможет

1

Один вариант, если вам это нужно сделать, и если ваш начальный столбец был создан по умолчанию, нужно создать новый столбец, который вам нужен, скопировать содержимое на него и в основном "отказаться" от старого столбца (он остается присутствующим, но вы просто не используете/не обновляете его и т.д.)

Пример:

alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically

Это оставляет столбец (и если он был создан с NOT NULL, но без значения по умолчанию, тогда будущие вставки, которые игнорируют его, могут завершиться неудачно), но если это просто таблица с выбросом, компромиссы могут быть приемлемыми. В противном случае используйте один из других ответов, упомянутых здесь, или другую базу данных, которая позволяет переименовывать столбцы.

-4

sqlite3 yourdb.dump > /tmp/db.txt
edit/tmp/db.txt изменить имя столбца в строке Создать sqlite2 yourdb2 </tmp/db.txt
mv/move yourdb2 yourdb

  • 3
    ваш ответ не предоставляет никакой информации, куча кода / инструкций выкладывается без какой-либо дополнительной информации о том, почему вы думаете, что это будет работать или что произойдет, если вы запустите его

Ещё вопросы

Сообщество Overcoder
Наверх
Меню