Як перейменувати стовпець у таблиці бази даних SQLite?


296

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

З документації на SQLite для ALTER TABLE я розумію, що таке "легко" зробити неможливо (тобто один оператор ALTER TABLE).

Мені було цікаво, що хтось знає про загальний спосіб SQL робити таку річ із SQLite.


Зробити це можна за допомогою браузера db для sqlite досить легко
Matt G

1
Розгляньте, як позначити цю відповідь прийнятою stackoverflow.com/a/52346199/124486
Еван Керролл

Відповіді:


66

Це було щойно виправлено у 2018-09-15 (3.25.0)

Удосконалює ALTER TABLEкоманду:

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

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

RENAME COLUMN TOСинтаксис змінює ім'я-стовпця таблиці ім'я-таблиці в новій-ім'я стовпця. Назва стовпця змінюється як у самому визначенні таблиці, так і в усіх індексах, тригерах та видах, на які посилається стовпець. Якщо зміна імені стовпця призведе до смислової неоднозначності в тригері або перегляді, то RENAME COLUMNпомилка з помилкою і зміни не застосовуються.

введіть тут опис зображення Джерело зображення: https://www.sqlite.org/images/syntax/alter-table-stmt.gif

Приклад:

CREATE TABLE tab AS SELECT 1 AS c;

SELECT * FROM tab;

ALTER TABLE tab RENAME COLUMN c to c_new;

SELECT * FROM tab;

демонстрація db-fiddle.com


Підтримка Android

На момент написання, в API 27 для Android використовується пакет SQLite версії 3.19 .

Виходячи з поточної версії, яку використовує Android, і що це оновлення надходить у версії 3.25.0 SQLite, я б сказав, що ви трохи зачекали (приблизно API 33), перш ніж підтримка цього буде додана до Android.

І навіть тоді, якщо вам потрібно буде підтримувати будь-які версії, старші за API 33, ви не зможете цим скористатися.


8
Я реалізую для міграції Android, і, на жаль, IntelliJ видає попередження, що це не дійсна команда SQL. database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount"). COLUM виділений червоним кольором, на якому написано TO очікувано, отримано "COLUMN" . На жаль, Android все ще перебуває на версії SQLite 3.19 , тому це не працює для мене.
Адам Гурвіц

1
відредаговано: Я знайшов на system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q1 , що 1.0.109.x) насправді використовує SQLite 3.24 та System.Data.SQLite використання SQLite 3.25 планується відновити в цьому місяці.
rychlmoj

1
FYI, на жаль, це ще не було впроваджено бібліотекою SQLite Android . Сподіваємось, вони незабаром оновляться.
Адам Гурвіц

3
Я додав розділ для Android Support, щоб запобігти іншим сподіватися. На основі поточного використання Android 27 SQLite 3.19, нам доведеться почекати, поки приблизно API 33, перш ніж ця функція буде додана до Android, і навіть тоді вона підтримуватиметься лише в останніх версіях. Зітхнути.
Джошуа Пінтер

1
@JoshuaPinter Дякую за поширення моєї відповіді.
Лукаш Шозда

448

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


51
І не забувайте своїх показників.
Том Мейфілд

11
Дуже важливо, що в наведеному вище прикладі коду відсутня транзакція. Ви повинні загортати все в ПОЧАТОК / КІН (або ROLLBACK), щоб переконатися, що перейменування або завершено успішно, або зовсім не буде.
Роджер Біннс

4
Усі бажаючі зробити це в android можуть здійснювати транзакції за допомогою SQLiteDatabase.beginTransaction ()
bmaupin

7
У відповіді немає нічого, що копіює індекси. Створення порожньої таблиці та введення в неї даних лише копіює структуру та дані. Якщо ви хочете метадані (індекси, зовнішні ключі, обмеження тощо), вам також доведеться видати оператори, щоб створити їх у заміненій таблиці.
Том Мейфілд

17
.schemaКоманда SQLite зручна для показу CREATE TABLEоператора, який складає існуючу таблицю. Ви можете взяти його вихід, змінити за потребою та виконати його для створення нової таблиці. Ця команда також показує необхідні CREATE INDEXкоманди для створення індексів, які повинні охоплювати занепокоєння Томаса. Звичайно, обов'язково виконайте цю команду, перш ніж щось змінювати.
Майк Десимоне

56

Розкопавшись, я знайшов цей мультиплатформенний (Linux | Mac | Windows) графічний інструмент під назвою браузер DB для SQLite, який фактично дозволяє перейменувати стовпці дуже зручним для користувача способом!

Редагувати | Змінити таблицю | Виберіть Таблиця | Поле редагування. Клацніть натисніть! Вуаля!

Однак, якщо хтось хоче поділитися програмним способом цього, я би радий знати!


1
Також є доповнення для Firefox, яке робить те саме , клацніть правою кнопкою миші стовпець, який потрібно перейменувати, та виберіть "Редагувати стовпчик".
Якоб Хакер

1
Навіть у openSUSE він доступний у вигляді пакету: software.opensuse.org/package/sqlitebrowser

Дивно, що у нього стільки голосів. Ми говоримо про програмування тут (код). Чому ви навіть опублікували цю відповідь тут?
користувач25

2
У моєму питанні не згадується, як це зробити з кодом. Мені просто хотілося знати, як перейменувати стовпець у БД SQLite.
joce

@joce я тебе люблю !!! (як брат) застав мене в зміненому полі, вуаля. Я експортував таблицю MS Access на SQLite, і в одному з полі була цифра попереду: 3YearLetterSent. Visual Studio склав клас із таблиці, але захлинувся цифрою "3" в передній частині назви поля. Я це знаю, просто не дивився.
JustJohn

53

Хоча це правда, що 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. Попередження: неправильне використання цієї прагми може легко призвести до пошкодження файлу бази даних.

Таблиця alter
SQLite підтримує обмежений підмножина ALTER TABLE. Команда ALTER TABLE в SQLite дозволяє користувачеві перейменувати таблицю або додати новий стовпець до вже наявної таблиці. Не можна перейменувати стовпчик, видалити стовпчик або додати чи видалити обмеження з таблиці.

АЛЬТЕР ТАБЛИЧНИЙ СИНТАКС


3
Небезпечна, але все ж, мабуть, найпростіша відповідь imo.
Тек

2
Так надзвичайно швидко - небезпечно означає лише "Переконайтеся, що у вас є резервна копія"
Ной

6
Формат файлу sqlite дуже простий, і тому ця операція дійсна. Формат файлу містить лише два набори інформації про таблицю: Фактична команда CREATE TABLE у вигляді простого тексту та рядки, значення яких відображаються у порядку полів з команди CREATE. Що означає, що код sqlite відкриває базу даних, вона аналізує кожну команду CREATE та динамічно будує інформацію своєї колонки в пам'яті. Отже, будь-яка команда, яка змінює команду CREATE таким чином, що закінчується однаковою кількістю стовпців, буде працювати, навіть якщо ви зміните їх тип або обмеження.
Томас Темпельман

3
@ThomasTempelmann Однак додавання обмежень, які не виконуються набором даних, спричинить проблеми, оскільки планувальник запитів передбачає, що обмеження мають місце.
фуз

2
@ThomasTempelmann Видалення обмежень завжди добре. Додавання обмежень нормально, якщо обмеження задовольняють усі рядки, але ви, звичайно, повинні це перевірити.
фуз

18

Нещодавно мені довелося це зробити в SQLite3 із таблицею з іменами пунктів з colunms id, lon, lat . Помилково, коли таблиця була імпортована, значення широти, де зберігаються у стовпці " lon " та "viceversa", то очевидним виправленням буде перейменування цих стовпців. Тож фокус був:

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;

Я сподіваюся, що це було б вам корисно!


Цей метод не копіює значення ПК належним чином і автоматично створює прихований рядовий стовпець. Це не обов'язково було проблемою, але я хотів це зазначити, тому що це стало проблемою для мене.
TPoschel

4
Чи не було б простіше зробити "ОНОВЛЕННЯ точок SET lon = lat, lat = lon;"
kstep

1
Ця відповідь робить процес у правильному ЗАМОВЛЕННІ. Спочатку створіть таблицю темпів та заповніть її, а потім знищить оригінал .
Xeoncross

14

Цитуючи документацію sqlite :

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

Звичайно, можна створити нову таблицю з новим макетом SELECT * FROM old_tableта заповнити нову таблицю значеннями, які ви отримаєте.


7

По-перше, це одна з тих речей, яка мене здивує в обличчя: перейменування стовпця вимагає створення абсолютно нової таблиці та копіювання даних зі старої таблиці в нову таблицю ...

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

Базове вікно журналу

Потім їх можна легко скопіювати та вставити туди, де вони можуть знадобитися. Для мене це в міграційному файлі ActiveAndroid . Приємним штрихом є також те, що скопійовані дані включають лише команди SQLite, а не часові позначки тощо.

Сподіваємось, це економить час деяким людям.


FYI, якщо ви будете з допомогою ActiveAndroid , ви можете опустити BEGIN TRANSACTION;і COMMIT;лінії, а ActiveAndroid ручки , що сам по собі.
Джошуа Пінтер

6

СЛУЧАЙ 1: SQLite 3.25.0+

Тільки версія 3.25.0 SQLite підтримує перейменування стовпців. Якщо ваш пристрій відповідає цій вимозі, все відбувається досить просто. Нижче наведений запит вирішить вашу проблему:

ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";

СЛУЧАЙ 2: Старі версії SQLite

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

Наприклад, якщо у вас є така таблиця:

CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)

І якщо ви хочете змінити назву стовпця Location

Крок 1: Перейменуйте початкову таблицю:

ALTER TABLE student RENAME TO student_temp;

Крок 2. Тепер створіть нову таблицю studentз правильною назвою стовпця:

CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)

Крок 3: Скопіюйте дані з початкової таблиці в нову таблицю:

INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;

Примітка. Вищенаведена команда повинна містити один рядок.

Крок 4: Видаліть початкову таблицю:

DROP TABLE student_temp;

За допомогою цих чотирьох кроків ви можете вручну змінити будь-яку таблицю SQLite. Майте на увазі, що вам також потрібно буде відтворити будь-які індекси, глядачі або тригери на новій таблиці.


1
Як оновити версію бази даних sqllite до 3.29.0 в студії Android, я використовую api рівень 28.
Програмне забезпечення

Версія SQLite визначається пристроєм, на якому працює програма. Це залежить від пристрою.
Фебін Матвій

1
Для людей, які використовують старий sqlite, чотири кроки вище не рекомендується. Дивіться розділ "Обережність" на сайті sqlite.org/lang_altertable.html .
Джефф

3

змінити стовпчик таблиці <id> на <_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");

3

Створіть новий стовпець із потрібною назвою стовпця: COLNew.

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

Скопіюйте вміст старого стовпця COLOld у новий стовпець COLNew.

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

Примітка: дужки потрібні у верхньому рядку.


2

Як згадувалося раніше, існує інструмент браузера баз даних SQLite, який робить це. На щастя, цей інструмент веде журнал усіх операцій, які виконує користувач або програма. Зробивши це один раз і переглянувши журнал додатків, ви побачите код, що займається. Скопіюйте запит та вставте, якщо потрібно. Працювали для мене. Сподіваюсь, це допомагає


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 введіть = 'table' AND name = 'X';

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

  5. Якщо зміна таблиці X також впливає на інші таблиці або індекси, або тригери є переглядами в межах схеми, тоді запустіть оператори UPDATE, щоб також змінити індекси та представлення інших таблиць. Наприклад, якщо ім'я стовпця змінюється, всі обмеження, тригери, індекси та представлення, які посилаються на цей стовпець, повинні бути змінені.

    Попередження: Ще раз внесення змін до таблиці sqlite_master, як це, призведе до пошкодження та нечитабельності бази даних, якщо зміна містить помилку. Ретельно протестуйте всю цю процедуру на окремій тестовій базі даних перед її використанням у базі даних, що містить важливі дані та / або роблять резервні копії важливих баз даних перед запуском цієї процедури.

  6. Збільшити номер версії схеми за допомогою PRAGMA schema_version = X, де X є на один більше, ніж номер версії старої схеми, знайдений на кроці 2 вище.

  7. Вимкнути редагування схеми за допомогою PRAGMA writable_schema = OFF.

  8. (Необов’язково) Запустіть PRAGMA цілісність_чек, щоб переконатися, що зміни схеми не пошкодили базу даних.

  9. Здійсніть транзакцію, розпочату на кроці 1 вище.


PRAGMA цілісність_чек не збирає помилок зі схемою.
Graymatter

і в чому проблема?
Мохаммед Яхіа

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



-3

sqlite3 yourdb .dump> /tmp/db.txt
редагувати /tmp/db.txt змінити назву стовпця у Створити рядок
sqlite2 yourdb2 </tmp/db.txt
mv / перемістити yourdb2 yourdb


3
ти відповідь не надає ніякої інформації, купа коду / інструкцій виплює без зайвої інформації про те, чому ти думаєш, що це спрацює або що припустимо, що станеться, якщо запустити його
RGLSV
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.