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

时间:2009-04-30 04:43:45

标签: sqlite alter-table

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

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

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

15 个答案:

答案 0 :(得分:433)

假设您有一张桌子并需要将“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;中也可能是一个好主意。

答案 1 :(得分:53)

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

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

然而,如果有人想分享一种程序化的方式,我很乐意知道!

答案 2 :(得分: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
启用此pragma时,可以使用普通的UPDATE,INSERT和DELETE语句更改数据库的SQLITE_MASTER表。警告:滥用此pragma很容易导致数据库文件损坏。

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

ALTER TABLE SYNTAX

答案 3 :(得分:34)

此问题已通过2018-09-15 (3.25.0)

修复
  

增强了ALTER TABLE命令:

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

您可以找到ALTER TABLE

下记录的新语法
  

RENAME COLUMN TO语法将表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支持

撰写本文时, Android's API 27 is using SQLite package version 3.19

基于Android当前使用的版本以及SQLite 3.25.0版本中的此更新,我想您需要等待一段时间(大约API 33),然后才能将此功能添加到Android中。 / p>

而且,即使那样,如果您需要支持API 33之前的任何版本,您将无法使用它。

答案 4 :(得分: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;

我希望这对你有用!

答案 5 :(得分:12)

引用sqlite documentation

  

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

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

答案 6 :(得分:7)

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

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

Base log window

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

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

答案 7 :(得分:3)

更改表格列&lt; id&gt;到&lt; _id&gt;

 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");

答案 8 :(得分:2)

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

答案 9 :(得分:2)

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

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

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

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

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

答案 10 :(得分: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步开始的交易。

答案 11 :(得分:1)

一个选项,如果您需要在紧要关头完成,并且如果您的初始列是使用默认创建的,则创建所需的新列,将内容复制到其中,基本上&#34;放弃&# 34;旧栏目(它保持存在,但你只是不使用/更新它等)。

例如:

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

答案 12 :(得分:0)

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

https://sqlite.org/changes.html

答案 13 :(得分:0)

案例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)

第3步::将数据从原始表复制到新表:

INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;

注意:上面的命令应全部为一行。

步骤4:删除原始表格:

DROP TABLE student_temp;

通过这四个步骤,您可以手动更改任何SQLite表。 请记住,您还需要在新表上重新创建任何索引,查看器或触发器。

答案 14 :(得分:-3)

sqlite3 yourdb .dump&gt; /tmp/db.txt
编辑/tmp/db.txt更改创建行中的列名
sqlite2 yourdb2&lt; /tmp/db.txt
mv / move yourdb2 yourdb