如何重命名SQLite数据库表中的列?

问题描述 投票:273回答:14

我需要在SQLite数据库的某些表中重命名几列。我知道之前已经在stackoverflow上询问过similar question,但它一般用于SQL,并且没有提到SQLite的情况。

ALTER TABLE的SQLite文档中,我认为不可能“轻松”地做这样的事情(即单个ALTER TABLE语句)。

我想知道有人知道用SQLite做这种事情的通用SQL方法。

sqlite alter-table
14个回答
38
投票

这只是用2018-09-15 (3.25.0)修复的

增强ALTER TABLE命令:

  • 使用ALTER TABLERENAME COLUMN oldname TO newname添加对表中列重命名的支持。
  • 修复表重命名功能,以便它还更新对触发器和视图中重命名的表的引用。

您可以在ALTER TABLE下找到记录的新语法

RENAME COLUMN TO语法将table table-name的列名更改为new-column-name。列名在表定义本身内以及引用该列的所有索引,触发器和视图中都会更改。如果列名称更改将导致触发器或视图中出现语义歧义,则RENAME COLUMN将失败并显示错误,并且不会应用任何更改。

enter image description here图片来源:https://www.sqlite.org/images/syntax/alter-table-stmt.gif

例:

CREATE TABLE tab AS VALUES(1);

SELECT * FROM tab;

ALTER TABLE tab RENAME TO tab_new;

SELECT * FROM tab_new;

db-fiddle.com demo


Android Support

截至写作,Android's API 27 is using SQLite package version 3.19

根据Android正在使用的当前版本以及此更新将在SQLite版本3.25.0中发布,我会说你有一点等待(大约是API 33),然后才会将对此的支持添加到Android。

即便如此,如果您需要支持任何早于API 33的版本,您将无法使用它。


2
投票

使用所需的列名创建一个新列:COLNew。

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

将旧列COLOld的内容复制到新列COLNew。

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

注意:上面一行需要括号。


2
投票

From the official documentation

可以选择使用更简单,更快速的过程进行一些不会以任何方式影响磁盘内容的更改。以下更简单的过程适用于删除CHECK或FOREIGN KEY或NOT NULL约束,重命名列,或添加或删除或更改列上的默认值。

  1. 开始交易。
  2. 运行PRAGMA schema_version以确定当前架构版本号。下面的步骤6将需要此编号。
  3. 使用PRAGMA writable_schema = ON激活模式编辑。
  4. 运行UPDATE语句以更改sqlite_master表中表X的定义:UPDATE sqlite_master SET sql = ... WHERE type ='table'AND name ='X'; 警告:如果更改包含语法错误,则对此类sqlite_master表进行更改将导致数据库损坏且无法读取。建议在将UPDATE语句用于包含重要数据的数据库之前,对单独的空白数据库进行仔细测试。
  5. 如果对表X的更改也影响其他表或索引或触发器是模式中的视图,则运行UPDATE语句以修改其他表索引和视图。例如,如果列名称发生更改,则必须修改引用该列的所有FOREIGN KEY约束,触发器,索引和视图。 警告:再次,如果更改包含错误,对此类sqlite_master表进行更改将导致数据库损坏且无法读取。在运行此过程之前,在包含重要数据的数据库上使用它并/或制作重要数据库的备份副本之前,请在单独的测试数据库上仔细测试整个过程。
  6. 使用PRAGMA schema_version = X增加架构版本号,其中X比上面步骤2中找到的旧架构版本号多一个。
  7. 使用PRAGMA writable_schema = OFF禁用模式编辑。
  8. (可选)运行PRAGMA integrity_check以验证架构更改是否损坏数据库。
  9. 提交在上面的步骤1开始的事务。

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创建但没有默认值,那么将来忽略它的插入可能会失败),但如果它只是一次性表,那么权衡可能是可以接受的。否则,请使用此处提到的其他答案之一,或使用允许重命名列的其他数据库。


1
投票

案例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表。请记住,您还需要在新表上重新创建任何索引,查看器或触发器。


0
投票

从版本2018-09-15(3.25.0)开始,sqlite支持重命名列

https://sqlite.org/changes.html


-3
投票

sqlite3 yourdb .dump> /tmp/db.txt 编辑/tmp/db.txt更改“创建”行中的列名称 sqlite2 yourdb2 </tmp/db.txt mv / move yourdb2 yourdb


434
投票

假设您有一个表,需要将“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;中包装所有这些也可能是一个好主意。


54
投票

四处搜索,我发现这个名为DB Browser for SQLite的多平台(Linux | Mac | Windows)图形工具实际上允许用户以非常友好的方式重命名列!

编辑|修改表|选择表|编辑字段。点击!瞧!

但是,如果有人想分享这样做的程序化方式,我很高兴知道!


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
When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file.

alter table SQLite支持ALTER TABLE的有限子集。 SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列。无法重命名列,删除列,或从表中添加或删除约束。


18
投票

最近我不得不在SQLite3中使用一个名为points的表,其中包含colunms 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;

我希望这对你有用!


12
投票

引用sqlite documentation

SQLite支持ALTER TABLE的有限子集。 SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列。无法重命名列,删除列,或从表中添加或删除约束。

你当然可以做的是,使用新的布局创建一个新表格SELECT * FROM old_table,并用你将收到的值填充新表格。


7
投票

首先,这是让我惊讶的事情之一:重命名列需要创建一个全新的表并将数据从旧表复制到新表...

我已经登陆进行SQLite操作的GUI是Base。它有一个漂亮的日志窗口,显示已执行的所有命令。通过Base重命名列会使用必要的命令填充日志窗口:

然后可以轻松地将它们复制并粘贴到您可能需要的位置。对我来说,这是一个ActiveAndroid迁移文件。同样好的一点是,复制的数据只包括SQLite命令,而不包括时间戳等。

希望这能节省一些人的时间。


3
投票

change table column < id > to < _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");

2
投票

如前所述,有一个工具SQLite数据库浏览器,它可以做到这一点。 Lyckily,这个工具记录了用户或应用程序执行的所有操作。执行此操作并查看应用程序日志,您将看到所涉及的代码。根据需要复制查询和粘贴。为我工作。希望这可以帮助

© www.soinside.com 2019 - 2024. All rights reserved.