我需要重命名 SQLite 数据库中某些表中的一些列。我知道之前在stackoverflow上问过一个similar question,但它一般是针对SQL的,没有提到SQLite的情况。
从 ALTER TABLE 的 SQLite 文档中,我了解到不可能“轻松”地做这样的事情(即单个 ALTER TABLE 语句)。
我想知道有人知道用 SQLite 做这种事情的通用 SQL 方式。
请注意,从版本 3.25.0 released September 2018 开始,您现在可以使用 ALTER TABLE
到 rename a column。
下面的原始“创建新表和删除旧表”答案。
假设您有一个表,需要将“colb”重命名为“col_b”:
首先根据旧表定义创建具有临时名称的新表,但使用更新的列名:
CREATE TABLE tmp_table_name (
col_a INT
, col_b INT
);
然后从原始表中复制内容。
INSERT INTO tmp_table_name(col_a, col_b)
SELECT col_a, colb
FROM orig_table_name;
放下旧桌子。
DROP TABLE orig_table_name;
最后您将临时表重命名为原始表:
ALTER TABLE tmp_table_name RENAME TO orig_table_name;
不要忘记重新创建索引、触发器等。The documentation 更全面地说明了问题和注意事项。
将所有这些包装在 BEGIN TRANSACTION;
和 COMMIT;
中也可能是一个好主意。
刚刚用 2018-09-15 (3.25.0) 解决了这个问题
增强 ALTER TABLE 命令:添加对使用 ALTER TABLE table RENAME COLUMN oldname TO newname 重命名表中的列的支持。修复表重命名功能,以便它还更新触发器和视图中对重命名表的引用。
您可以在 ALTER TABLE
下找到记录的新语法
RENAME COLUMN TO 语法将表 table-name 的 column-name 更改为 new-column-name。列名在表定义本身以及引用该列的所有索引、触发器和视图中都发生了更改。如果列名更改会导致触发器或视图中的语义模糊,则 RENAME COLUMN 会失败并出现错误,并且不会应用任何更改。
https://i.stack.imgur.com/0P4ZG.gif
例子:
CREATE TABLE tab AS SELECT 1 AS c;
SELECT * FROM tab;
ALTER TABLE tab RENAME COLUMN c to c_new;
SELECT * FROM tab;
安卓支持
在撰写本文时,Android's API 27 is using SQLite package version 3.19.
基于 Android 正在使用的当前版本以及此更新将在 SQLite 版本 3.25.0 中提供,我会说您需要等待(大约 API 33)才能将对此的支持添加到 Android。
而且,即便如此,如果您需要支持任何早于 API 33 的版本,您将无法使用它。
database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount")
。 COLUM 以红色突出显示,并显示 TO expected, got 'COLUMN'。不幸的是,Android 仍在 SQLite 版本 3.19 上,这就是为什么这对我不起作用。
仔细研究,我发现了这个名为 DB Browser for SQLite 的多平台(Linux | Mac | Windows)图形工具,它实际上允许以非常用户友好的方式重命名列!
编辑 |修改表 |选择表 |编辑字段。点击点击!瞧!
但是,如果有人想分享一种编程方式,我很高兴知道!
虽然确实没有 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
alter table
SQLite 支持 ALTER TABLE 的有限子集。 SQLite 中的 ALTER TABLE 命令允许用户重命名表或向现有表添加新列。无法重命名列、删除列或在表中添加或删除约束。
https://i.stack.imgur.com/y3xIP.png
最近我不得不在 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;
我希望这对你有用!
案例 1:SQLite 3.25.0+
只有 SQLite 3.25.0 版支持重命名列。如果你的设备满足这个要求,事情就很简单了。以下查询将解决您的问题:
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)
第三步:将原表中的数据复制到新表中:
INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;
注意:上面的命令应该是一行。
第 4 步:删除原始表:
DROP TABLE student_temp;
通过这四个步骤,您可以手动更改任何 SQLite 表。请记住,您还需要在新表上重新创建任何索引、查看器或触发器。
SQLite 支持有限的 ALTER TABLE 子集。 SQLite 中的 ALTER TABLE 命令允许用户重命名表或向现有表添加新列。无法重命名列、删除列或在表中添加或删除约束。
当然,您可以使用新布局创建一个新表格 SELECT * FROM old_table
,然后用您将收到的值填充新表格。
首先,这是让我大吃一惊的事情之一:重命名列需要创建一个全新的表并将数据从旧表复制到新表......
我用来执行 SQLite 操作的 GUI 是 Base。它有一个漂亮的日志窗口,显示所有已执行的命令。通过 Base 重命名列会使用必要的命令填充日志窗口:
https://i.stack.imgur.com/fVVWs.png
然后可以轻松地将这些复制并粘贴到您可能需要它们的地方。对我来说,这是一个 ActiveAndroid 迁移文件。一个很好的感觉是,复制的数据只包括 SQLite 命令,而不包括时间戳等。
希望这可以节省一些人的时间。
BEGIN TRANSACTION;
和 COMMIT;
行,因为 ActiveAndroid 会自行处理。
将表列
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");
使用所需的列名称创建一个新列:COLNew。
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
将旧列 COLOld 的内容复制到新列 COLNew。
INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}
注意:上面一行需要括号。
如前所述,有一个工具 SQLite Database Browser 可以执行此操作。 Lyckily,这个工具会记录用户或应用程序执行的所有操作。这样做一次并查看应用程序日志,您将看到所涉及的代码。根据需要复制查询并粘贴。为我工作。希望这可以帮助
From the official documentation
对于不以任何方式影响磁盘内容的某些更改,可以选择使用更简单和更快的过程。以下更简单的过程适用于删除 CHECK 或 FOREIGN KEY 或 NOT NULL 约束、重命名列或添加或删除或更改列的默认值。
开始交易。运行 PRAGMA schema_version 以确定当前模式版本号。下面的第 6 步将需要此编号。使用 PRAGMA writable_schema=ON 激活模式编辑。运行 UPDATE 语句更改 sqlite_master 表中表 X 的定义: UPDATE sqlite_master SET sql=... WHERE type='table' AND name='X';注意:如果更改包含语法错误,则像这样对 sqlite_master 表进行更改将导致数据库损坏且不可读。建议在将 UPDATE 语句用于包含重要数据的数据库之前,对单独的空白数据库进行仔细测试。如果对表 X 的更改也影响其他表或索引或触发器是模式中的视图,则运行 UPDATE 语句来修改那些其他表的索引和视图。例如,如果列的名称发生更改,则必须修改引用该列的所有 FOREIGN KEY 约束、触发器、索引和视图。警告:再一次,如果更改包含错误,则像这样对 sqlite_master 表进行更改将导致数据库损坏且不可读。在将整个过程用于包含重要数据的数据库之前,请在单独的测试数据库上仔细测试整个过程和/或在运行此过程之前制作重要数据库的备份副本。使用 PRAGMA schema_version=X 增加模式版本号,其中 X 比上面步骤 2 中找到的旧模式版本号大一。使用 PRAGMA writable_schema=OFF 禁用模式编辑。 (可选)运行 PRAGMA integrity_check 以验证架构更改没有损坏数据库。提交在上述第 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 创建但没有默认值,那么将来忽略它的插入可能会失败),但如果它只是一个一次性表,则权衡可能是可以接受的。否则,请使用此处提到的其他答案之一,或使用允许重命名列的其他数据库。
需要重命名某些表中的一些列
另一种方法是使用多个 SQLite3 命令来“重命名”一列,在“一些”表中,根据需要重复:
.output tmp
SELECT "ALTER TABLE """|| sqlite_master.name ||""" RENAME COLUMN old_name TO new_name;" FROM sqlite_master
WHERE type = "table" AND sqlite_master.name NOT LIKE 'sqlite_%';
.read tmp
sqlite3 yourdb .dump > /tmp/db.txt edit /tmp/db.txt 在 Create line sqlite2 yourdb2 < /tmp/db.txt mv/move yourdb2 yourdb 中更改列名
.schema
命令可方便地显示创建现有表的CREATE TABLE
语句。您可以获取其输出,根据需要进行修改,然后执行它以创建新表。该命令还显示了创建索引所必需的CREATE INDEX
命令,这应该涵盖了 Thomas 的关注点。当然,请务必在更改任何内容之前运行此命令。