Вставить новый столбец в таблицу в 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;

Я бы предпочел второй вариант, так как он позволит вам полностью переименовать все, если это будет необходимо.


27
Я бы выбрал первый вариант и использовал опцию по умолчанию из опции secend. 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 )
Trinimon

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
Безумие, что это не «принятый ответ». Сам исходный вопрос демонстрирует полное отсутствие понимания того, как работает СУБД.
Вада Поче

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 значения: INSERT INTO t1 SELECT a, c FROM 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 Browser для SQLite, который имеет удобную функцию для этого. После этого вам просто нужно отредактировать оператор create table и вставить новый столбец, где вы хотите, и заново создать базу данных.

В * nix-подобных системах это просто нечто вроде

cat db.sql | sqlite3 database.db

Я не знаю, насколько это возможно с очень большими базами данных, но в моем случае это сработало.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.