在sqlite中修改列

102

如何在sqlite中修改列?

这是在Postgresql中的内容。

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

我相信在sqlite中根本没有ALTER COLUMN语句,仅支持ALTER TABLE语句。

有什么想法吗?谢谢!


你要求一个ALTER COLUMN语法,但是你没有说你想要做什么。这让我觉得这太宽泛了。ALTER COLUMN可以做很多事情,你是想像pg示例中那样删除非空约束吗? - Evan Carroll
如果您使用IntelliJ DB工具,当您更改列时,它会为您的SQLite生成命令。 - foolcage
7个回答

137

SQLite中没有ALTER COLUMN。

我认为你唯一的选择是:

  • 将表重命名为临时名称
  • 创建一个没有NOT NULL约束的新表
  • 将旧表的内容复制到新表中
  • 删除旧表

这个Stackoverflow答案详细解释了该过程。


当其他表依赖于被修改的表时,如果存在外键约束,则此答案会遇到额外的挑战。 - Eric Walker
虽然从技术上讲是正确的,但有更简单的工具可以做到这一点。请查看我的回复。 - undefined

68

尽管 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;
你需要关闭并重新打开你的连接或者对数据库进行vacuum操作,以便将更改重新加载到架构中。
例如:
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](来自http://www.sqlite.org/lang_altertable.html
SQLite 支持 ALTER TABLE 的有限子集。在 SQLite 中,ALTER TABLE 命令允许用户重命名表或向现有表添加新列。无法重命名列、删除列或从表中添加或删除约束。

ALTER TABLE SYNTAX


7
这个方法对我起了作用,但为了避免列的顺序可能不同(例如来自先前的ADD COLUMN命令),我使用了以下语句:UPDATE SQLITE_MASTER SET SQL = replace(SQL, '[MyColumn] integer NOT NULL', '[MyColumn] integer NULL') WHERE NAME = 'MyTable'。此外,请注意不要将其作为事务的一部分运行 - 这可能会阻止一些早期的事务命令运行。 - Ross

34

SQLite支持有限的ALTER TABLE子集。在SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列。不可能重命名列,删除列或添加或删除表上的约束。但是您可以按照以下步骤更改表列数据类型或其他属性。

  1. BEGIN TRANSACTION;
  2. CREATE TEMPORARY TABLE t1_backup(a,b);
  3. INSERT INTO t1_backup SELECT a,b FROM t1;
  4. DROP TABLE t1;
  5. CREATE TABLE t1(a,b);
  6. INSERT INTO t1 SELECT a,b FROM t1_backup;
  7. DROP TABLE t1_backup;
  8. COMMIT

欲了解更多详情,请参考链接


重命名数据库表:ALTER TABLE table1 RENAME TO table2; - live-love
不要忘记索引。运行.schema以生成带有索引的创建语句。 - live-love

4
  1. 创建临时表temp_Table(x,y[,等]);

  2. 插入数据到临时表temp_Table:INSERT INTO temp_Table SELECT * FROM Table;

  3. 删除原表Table:DROP TABLE Table;

  4. 将临时表temp_Table重命名为Table:ALTER TABLE temp_Table RENAME TO Table;

感谢您帮助我找到确切的方法!


1

0
我建议你使用DB Browser for SQLite。你可以很容易地通过它来更改约束条件。例如,在DB Browser for SQLite中,你可以进入数据库结构 -> 右键点击你的表 -> 点击修改表 -> 取消勾选NN(非空)列,然后点击确定。

enter image description here


0
如果你只是改变列的类型,那么通常情况下你不需要修改列,因为SQLite是动态类型的,你可以放入与列类型不同的数据;列类型更多的是一种建议而不是强制要求。虽然列的类型会带来一些怪异的问题(强制转换规则),你可能需要解决这些问题,但数据库会欣然接受“错误”类型的数据。
实际上,你通常不会大幅度改变列的类型(在典型的数据库中,你通常只会改变类型的大小-例如 VARCHAR(16) -> VARCHAR(32) - 而不是类型的类别),所以唯一需要解决的问题是非空约束-在这种情况下,你可以使用其他有用的答案来实现你想要的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接