ALTER TABLE
SQL如SQLite所理解
[Top]
改变表
alter-table-stmt:
隐藏
column-def:
show
列约束:
显示
冲突条款:
展示
expr:
show
raise-function:
show
select-stmt:
show
common-table-expression:
show
复合操作符:
显示
连接子句:
显示
join-constraint:
show
join-operator:
show
订货期:
展示
结果列:
显示
表或子查询:
显示
foreign-key-clause:
show
literal-value:
show
signed-number:
show
type-name:
show
signed-number:
show
SQLite 支持 ALTER TABLE 的有限子集。SQLite 中的 ALTER TABLE 命令允许用户重命名表或将新列添加到现有表中。
RENAME TO 语法将表名的名称更改为新表名。该命令不能用于在连接的数据库之间移动表格,只能重命名同一数据库中的表格。
如果正在重命名的表具有触发器或索引,那么它们在重命名后仍保留附加到表。但是,如果有任何视图定义或由触发器执行的引用表的表被重命名的语句,则这些表不会自动修改为使用新表名。如果这是必需的,则必须删除并重新创建触发器或视图定义以手动使用新的表名称。
重要说明:
'ALTER TABLE ... RENAME TO ...'命令不会更新视图内触发器或 SELECT 语句内的动作语句。如果正在重命名的表是从触发器或视图中引用的,那么这些触发器和视图必须由应用程序单独删除和重新创建。
如果在重命名表时启用了外键约束,那么引用被重命名表的任何表中的任何 REFERENCES 子句(表中被重命名或某个其他表)都会被修改,以通过其新名称引用重命名的表。
ADD COLUMN 语法用于将新列添加到现有表中。新列总是附加到现有列列表的末尾。column-def 规则定义了新列的特征。新列可以采用 CREATE TABLE 语句中允许的任何形式,并具有以下限制:
- 该列可能没有 PRIMARY KEY 或 UNIQUE 约束。
- 该列可能没有默认值 CURRENT_TIME,CURRENT_DATE,CURRENT_TIMESTAMP 或括号中的表达式。
- 如果指定了 NOT NULL 约束,那么该列必须具有非 NULL 的默认值。
- 如果启用了外键约束并添加了带有 REFERENCES 子句的列,则该列必须具有 NULL 的默认值。
另请注意,添加 CHECK 约束时,CHECK 约束不会针对表的预先存在的行进行测试。这可能会导致包含违反 CHECK 约束的数据的表。未来版本的 SQLite 可能会更改为在添加它们时验证 CHECK 约束。
ALTER TABLE 命令的执行时间与表中的数据量无关。ALTER TABLE 命令在具有1000万行的表上运行速度与在具有1行的表上运行速度相同。
在数据库上运行 ADD COLUMN 之后,SQLite 版本3.1.3(2005-02-20)及更早版本将无法读取该数据库。
制作其他种类的表格模式变更
SQLite 直接支持的唯一模式更改命令是上面显示的“重命名表”和“添加列”命令。但是,应用程序可以使用简单的操作顺序对表格的格式进行其他任意更改。对某些表 X 的模式设计进行任意更改的步骤如下所示:
- 如果启用了外键约束,则使用PRAGMA foreign_keys = OFF禁用它们。
2. 开始交易。
3. 请记住与表X相关的所有索引和触发器的格式。下面的步骤8中将需要此信息。一种方法是运行如下所示的查询:SELECT type,sql FROM sqlite_master WHERE tbl_name ='X'。
4. 使用CREATE TABLE构造一个新表格“new_X”,该表格处于表格X的所需修改格式中。确保名称“new_X”当然不会与任何现有表格名称相冲突。
5. 使用如下语句将内容从X传输到new_X:INSERT INTO new_X SELECT ... FROM X.
6. 删除旧表X:DROP TABLE X.
7. 使用以下命令将new_X的名称更改为X:ALTER TABLE new_X RENAME TO X.
8. 使用CREATE INDEX和CREATE TRIGGER重建与表X相关联的索引和触发器。也许使用上面步骤3中保存的旧格式的触发器和索引作为指导,根据更改情况进行适当更改。
9. 如果任何视图以受模式更改影响的方式引用表X,则使用DROP VIEW删除这些视图,然后重新创建它们,以便使用CREATE VIEW适应模式更改所需的任何更改。
10. 如果最初启用了外键约束,则运行PRAGMA foreign_key_check以验证模式更改没有破坏任何外键约束。
11. 提交在第2步中开始的事务。
12. 如果外键约束最初启用,现在重新启用它们。
上述过程是完全一般的,并且即使模式更改导致存储在表中的信息发生变化,也会工作。因此,例如,上面的完整过程适用于删除列,更改列的顺序,添加或删除UNIQUE约束或PRIMARY KEY,添加CHECK或FOREIGN KEY或NOT NULL约束或更改列的数据类型。但是,可以选择使用更简单,更快的过程进行某些不会以任何方式影响磁盘上内容的更改。以下更简单的过程适用于删除CHECK或FOREIGN KEY或NOT NULL约束,重命名列或添加或删除或更改列上的默认值。
- 开始交易。
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语句。
- 如果对表X的更改也影响其他表或索引,或者触发器是模式中的视图,则运行UPDATE语句以修改其他表索引和视图。例如,如果列的名称发生更改,则必须修改引用该列的所有FOREIGN KEY约束,触发器,索引和视图。
警告:
再次,像这样更改sqlite_master表将导致数据库损坏,如果更改包含错误,则不可读。在使用包含重要数据的数据库之前,在单独的测试数据库上仔细测试整个过程,并/或在运行此过程之前制作重要数据库的备份副本。
2. 使用PRAGMA schema_version = X增加架构版本号,其中X比上面步骤2中找到的旧架构版本号多一个。
- 使用PRAGMA writable_schema = OFF禁用模式编辑。
- (Optional)运行PRAGMA integrity_check以验证架构更改没有损坏数据库。
2. 提交上面第1步开始的事务。
如果某些未来版本的SQLite添加新的ALTER TABLE功能,那么这些功能很可能会使用上述两个过程之一。