Вставити новий стовпець у таблицю в sqlite?


354

У мене є таблиця зі стовпцями name, qty, rate. Тепер мені потрібно додати новий стовпчик COLNewміж стовпцями nameта qtyстовпцями. Як додати новий стовпець між двома стовпцями?

Відповіді:


677

У вас є два варіанти. По-перше, ви можете просто додати новий стовпець із наступним:

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

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

ALTER TABLE {tableName} RENAME TO TempOldTable;

Потім створіть нову таблицю з стовпцем, що відсутній:

CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);

І заповнити його старими даними:

INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;

Потім видаліть стару таблицю:

DROP TABLE TempOldTable;

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


26
Я б пішов на перший варіант і скористався параметром за замовчуванням з окремої опції ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Більш важливо: (думаючи про те, чому ви хочете замовити стовпчики ..), використовуйте в кожній дії запису (наприклад, вставити або додати) завжди назви стовпців, таким чином, ви ніколи не помилитесь у коді після зміни таблиці.
michel.iamit

5
До речі: значення "за замовчуванням" не можна додавати в ALTER TABLE для деяких типів поля: sqlite.org/lang_altertable.html
michel.iamit

9
не забудьте знову створити індекси
Jan Turoň

5
вам також потрібно буде відтворити тригери
Крістофер К.

7
Не забувайте про можливі порушення обмежень, спричинені зовнішніми ключами: "... але можуть викликати дії зовнішнього ключа або порушення обмежень." (див. sqlite.org/foreignkeys.html#fk_schemacommands ); як вирішення, тим часом ви можете відключити сторонні ключі: PRAGMA foreign_keys = ON;(див. sqlite.org/foreignkeys.html#fk_enable )
Тринімон

112

Ви не додаєте стовпчики між іншими стовпцями в SQL, ви просто додаєте їх. Де вони розміщені, повністю залежить від СУБД. Правильне місце для того, щоб стовпці виходили у правильному порядку, - це коли ви selectїх.

Іншими словами, якщо ви хочете, щоб вони були в порядку {name,colnew,qty,rate}, ви використовуєте:

select name, colnew, qty, rate from ...

Для SQLite потрібно використовувати alter table, наприклад:

alter table mytable add column colnew char(50)

2
SELECT * FROM mytable?
EML

Яке значення за замовчуванням встановлено, якщо ми не вкажемо його в існуючих рядках нового стовпця?
Яків

12
Є дуже мало випадків використання, коли вам взагалі слід займатися select *. Іноді це зручно для програм, які хочуть виявляти таблиці, але для переважної більшості застосувань вам слід чітко вказати, що ви хочете, а отже, і порядок, у якому ви цього хочете.
paxdiablo

4
Божевільно, як це не "прийнята відповідь". Первісне запитання само по собі демонструє повне нерозуміння того, як працює RDBMS.
Vada Poché

12

Ви можете додати новий стовпець із запитом

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Але він буде доданий наприкінці, а не між існуючими стовпцями.


11

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

Якщо ви хочете внести більш складні зміни в структуру таблиці, вам доведеться відтворити таблицю. Ви можете зберегти наявні дані до тимчасової таблиці, скинути стару таблицю, створити нову таблицю, а потім скопіювати дані назад з тимчасової таблиці.

Наприклад, припустимо, у вас є таблиця з назвою "t1" із назвами стовпців "a" і "c" і що ви хочете вставити стовпчик "b" з цієї таблиці. Наступні кроки ілюструють, як це можна зробити:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,c);
INSERT INTO t1_backup SELECT a,c FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b, c);
INSERT INTO t1 SELECT a,c FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;

Тепер ви готові вставити нові дані на зразок:

UPDATE t1 SET b='blah' WHERE a='key'

У моїх тестах рядок INSERT INTO t1 SELECT a,c FROM t1_backup;викликає помилку: "таблиця t1 має 3 стовпчики, але було надано 2 значення: ВСТАВИТЬСЯ В t1 SELECT a, c ВІД t1_backup;". Правильна лінія повинна бутиINSERT INTO t1 (a,c) SELECT a,c FROM t1_backup;
JnLlnd

5
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};

Це оновлення потрібно для обробки нульового значення, вводячи значення за замовчуванням, як потрібно. Як і у вашому випадку, вам потрібно зателефонувати за SELECTзапитом, і ви отримаєте порядок стовпців, як уже написано paxdiablo :

SELECT name, colnew, qty, rate FROM{tablename}

і на мій погляд, назва вашого стовпця, щоб отримати значення від курсору:

private static final String ColNew="ColNew";
String val=cursor.getString(cursor.getColumnIndex(ColNew));

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

Це безпечний шлях в тому сенсі , що в іншому випадку, якщо ви використовуєте CREATE temptableабо RENAME tableабо CREATE, там буде висока ймовірність втрати даних , якщо не звертатися обережно, наприклад , в тому випадку , якщо ваші транзакції відбуваються в той час як батарея на кінець.


4

Я зіткнувся з тією ж проблемою, і другий метод, запропонований у прийнятій відповіді, як зазначено в коментарях, може бути проблематичним при роботі з іноземними ключами.

Моє вирішення полягає в тому, щоб експортувати базу даних у файл sql, переконуючись, що оператори INSERT містять назви стовпців. Я роблю це за допомогою браузера DB для SQLite, який має для цього зручну функцію. Після цього вам просто потрібно відредагувати оператор створення таблиці та вставити новий стовпець там, де ви хочете, і відтворити db.

У * nix подібних системах - це лише щось, що відповідає лінії

cat db.sql | sqlite3 database.db

Я не знаю, наскільки це можливо при дуже великих базах даних, але в моєму випадку це спрацювало.

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