在sqlite的表中插入新列?


354

我有一个列的表nameqtyrate。现在,我需要COLNewnameqty列之间添加一个新列。如何在两列之间添加新列?

Answers:


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 2013年

5
顺便说一句:对于某些字段类型,不能在ALTER TABLE中添加默认值:sqlite.org/lang_altertable.html
michel.iamit 2013年

9
别忘了重新创建索引
JanTuroň2014年

5
您还需要重新创建触发器
Christopher K.

7
不要忘记由外键引起的潜在约束违规:“ ...但可能会调用外键动作或约束违规。” (请参见sqlite.org/foreignkeys.html#fk_schemacommands);:作为一个变通方法,您可以同时禁用外键PRAGMA foreign_keys = ON;(见sqlite.org/foreignkeys.html#fk_enable
Trinimon

112

您无需在SQL的其他列之间添加列,而只需添加它们即可。它们的放置位置完全取决于DBMS。确保列以正确的顺序出现的正确位置是在您输入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 2014年

如果不在新列的现有行中指定默认值,该设置的默认值是什么?
雅各布

12
几乎没有用例,您根本应该做select *。对于想要发现表的程序来说,这有时很方便,但是对于绝大多数用途,您应该明确指定所需的内容以及所需的顺序。
paxdiablo 2014年

4
这不是“可接受的答案”真是疯了。原始问题本身表明完全不了解RDBMS的工作原理。
VadaPoché17年

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 '18

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 temptableRENAME tableCREATE,那么如果不小心处理(例如在电池快要用完时进行交易的情况下),很有可能会丢失数据。


4

我遇到了同样的问题,正如注释中所述,在接受的答案中提出的第二种方法在处理外键时可能会出现问题。

我的解决方法是将数据库导出到sql文件,确保INSERT语句包含列名。我使用用于SQLite的数据库浏览器来完成此任务,该浏览器具有相应的便捷功能。之后,您只需要编辑create table语句,并在所需的位置插入新列,然后重新创建数据库。

在* nix之类的系统中,

cat db.sql | sqlite3 database.db

我不知道对于大型数据库来说这是多么可行,但是对于我来说,它确实可行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.