ALTER TABLE [ ONLY ] name [ * ] action [, ... ] ALTER TABLE [ ONLY ] name [ * ] RENAME [ COLUMN ] column TO new_column ALTER TABLE name RENAME TO new_name ALTER TABLE name SET SCHEMA new_schema 这里的 action 是下列之一: ADD [ COLUMN ] column type [ column_constraint [ ... ] ] DROP [ COLUMN ] column [ RESTRICT | CASCADE ] ALTER [ COLUMN ] column TYPE type [ USING expression ] ALTER [ COLUMN ] column SET DEFAULT expression ALTER [ COLUMN ] column DROP DEFAULT ALTER [ COLUMN ] column { SET | DROP } NOT NULL ALTER [ COLUMN ] column SET STATISTICS integer ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ADD table_constraint DROP CONSTRAINT constraint_name [ RESTRICT | CASCADE ] DISABLE TRIGGER [ trigger_name | ALL | USER ] ENABLE TRIGGER [ trigger_name | ALL | USER ] CLUSTER ON index_name SET WITHOUT CLUSTER SET WITHOUT OIDS SET ( storage_parameter = value [, ... ] ) RESET ( storage_parameter [, ... ] ) INHERIT parent_table NO INHERIT parent_table OWNER TO new_owner SET TABLESPACE new_tablespace
ALTER TABLE 变更一个现存表的定义。它有好几种子形式:
这种形式使用和 CREATE TABLE 一样的语法向表中增加一个新的字段。
这种形式从表中删除一个字段。和这个字段相关的索引和表约束也会被自动删除。如果任何表之外的对象依赖于这个字段,必须说 CASCADE ,比如外键参考、视图等等。
这种形式改变表中一个字段的类型。该字段涉及的索引和简单的表约束将被自动地转换为使用新的字段类型,方法是重新分析最初提供的表达式。可选的 USING 子句声明如何从旧的字段值里计算新的字段值;如果省略,那么缺省的转换就是从旧类型向新类型的赋值转换。如果从旧数据类型到新类型没有隐含或者赋值的转换,那么必须提供一个 USING
这种形式为一个字段设置或者删除缺省值。请注意缺省值只应用于随后的 INSERT 命令;它们不会修改表中已经存在的行。也可以为视图创建缺省,这个时候它们是在视图的 ON INSERT 规则应用之前插入 INSERT 语句中去的。
这些形式修改一个字段是否允许 NULL 值或者拒绝 NULL 值。如果表在字段中包含非 NULL ,那么你只可以 SET NOT NULL
这个形式为随后的 ANALYZE 操作设置针对每个字段的统计收集目标。目标的范围可以在 0 到 1000 之内设置;设置为 -1 表示重新恢复到使用系统缺省的统计目标(default_statistics_target)。有关 PostgreSQL 查询规划器使用的统计信息的更多信息,请参考节13.2。
这种形式为一个字段设置存储模式。这个设置控制这个字段是内联保存还是保存在一个附属的表里,以及数据是否要压缩。PLAIN 必需用于定长的数值(比如 integer)并且是内联的、不压缩的。MAIN 用于内联、可压缩的数据。EXTERNAL 用于外部保存、不压缩的数据, EXTENDED 用于外部的压缩数据。EXTENDED 是大多数支持非 PLAIN 存储的数据的缺省。使用 EXTERNAL 将令在 text 和 bytea 字段上的子字符串操作更快,但付出的代价是增加了存储空间。请注意 SET STORAGE 本身并不改变表上的任何东西,只是设置将来的表操作时,建议使用的策略。参阅节52.2获取更多信息。
这个形式给表增加一个新的约束,用的语法和 CREATE TABLE 一样。
这个形式删除一个表上的约束。
这个形式关闭或者打开属于该表的触发器。一个被关闭掉的触发器是系统仍然知道的,但是在触发器事件发生的时候不会被执行。对于一个推迟了的触发器,在事件发生的时候会检查打开状态,而不是在函数实际执行的时候。可以通过指定名字的方法打开或者关闭任意一个触发器,或者是该表上的所有触发器,或者只是用户触发器(这个选项排除了那些用于实现外键约束的触发器)。打开或者关闭约束触发器要求超级用户权限;这么做的时候应该小心,因为如果触发器不执行的话,约束保证的数据完整性也就没有办法确保了。
这种形式为将来的 CLUSTER 选项选择缺省索引。它实际上并不对表重新群集。
这种形式从表中删除最新使用的 CLUSTER 索引。这样会影响将来那些没有声明索引的群集操作。
这种形式从表中删除 oid 系统字段。它和 DROP COLUMN oid RESTRICT 完全相同,只不过是如果表上已经没有 oid 字段的时候不会报错。
请注意,不存在某种 ALTER TABLE 的变种可以在删除了 OID 之后再把它们恢复回来。
这种形式修改表的一个或多个存储参数。参见 CREATE TABLE 获取可用参数的细节。需要注意的是表的内容不会被此命令立即修改,根据参数的不同可能需要重写表以获得想要的效果。可以通过 CLUSTER 或某种 ALTER TABLE 重写一个表。
【注意】当 CREATE TABLE 允许用 WITH (storage_parameter) 语法指定 OIDS 的时候,ALTER TABLE 并不将 OIDS 看作存储参数。
这种形式重置表的一个或多个存储参数。与 SET 一样,根据参数的不同可能需要重写表才能获得想要的效果。
这种形式将目标表添加为指定父表的新子表。之后在父表上的查询将包含目标表中的记录。要被添加为一个子表,目标表必须已经包含所有与父表相同的字段(除此之外当然也可以包含一些其它字段),这些字段的数据类型必须匹配,并且如果父表的字段有 NOT NULL 约束的话子表的相应字段也必须有 NOT NULL 约束。
所有父表的 CHECK 约束必须同时与子表的约束匹配。当前 UNIQUE, PRIMARY KEY, FOREIGN KEY 约束不被考虑在内,但是将来可能会有所改变。
这种形式从指定父表的子表列表中删除目标表。这样,在父表上的查询将不再目标表中的记录。
这种形式将表、序列、视图的属主改变成指定的用户。
这种形式将表空间修改为指定的表空间并相关的数据文件移动到新的表空间。但是表上的所有索引都不会被移动,索引可以通过另外一个单独的 SET TABLESPACE 命令移动。参见 CREATE TABLESPACE 。
RENAME 形式改变一个表(或者索引、序列、视图)的名字,或者是表中独立字段的名字。它们对存储的数据没有影响。
这种形式把表移动到另外一个模式。相关的索引、约束、序列都跟着移动。
除了 RENAME 和 SET SCHEMA 之外所有动作都可以捆绑在一个多次修改列表中并行使用。比如,可以在一个命令里增加几个字段和/或修改几个字段的类型。对于大表,这么做特别有用,因为只需要对该表做一次处理。
要使用 ALTER TABLE ,你必须拥有该表。要修改一个表的模式,你还必须在新模式上拥有 CREATE 权限。要把该表添加为一个父表的新子表,你必须同时拥有父表。要修改所有者,你还必须是新的所有角色的直接或间接成员,并且该成员必须在此表的模式上有 CREATE 权限。这些限制强制了修改该所有者不会做任何通过删除和重建表不能做的事情。不过,超级用户可以以任何方式修改任意表的所有权。
试图更改的现存表(可能有模式修饰)的名称。如果声明了 ONLY ,则只更改该表。如果没有声明 ONLY ,则该表及其所有后代表(如果有)都被更新。可以在表名字后面附加一个 * 表示所有后代表都被扫描,但是在目前的版本里,这是缺省行为。缺省可以通过改变配置选项 sql_inheritance 来改变。
现存或新的字段名称
现存字段的新名称
表的新名称
新字段的类型,或者现存字段的新类型。
新的表约束定义
要删除的现有约束的名字
级联删除依赖于被依赖字段或者约束的对象(比如引用该字段的视图)
如果字段或者约束还有任何依赖的对象,则拒绝删除该字段。这是缺省行为。
要打开或者关闭的单个触发器的名字
打开或者关闭属于该表的所有触发器。如果这些触发器中有外键约束,那么就要求超级用户权限。
打开或者关闭所有属于该表的非外键约束触发器
要标记为群集的表上面的索引名字
表的存储参数的名字
表的存储参数的新值,根据参数的不同,可能是一个数字或单词。
将要与该表建立/取消关联的父表
该表的新所有者的用户名
这个表将要移动到的表空间名字
表将前往的新模式的名字
COLUMN 关键字是多余的,可以省略。
如果用 ADD COLUMN 增加一个字段,那么所有表中现有行都初始化为该字段的缺省值(如果没有声明 DEFAULT 子句,那么就是 NULL)。
用一个非空缺省值增加一个字段或者改变一个字段的现有类型会重写整个表。对于大表来说,这个操作可能会花很长时间;并且它还临时需要两倍的磁盘空间。
增加一个 CHECK 或 NOT NULL 约束将会扫描该表以保证现有的行符合约束要求。
提供在一个 ALTER TABLE 里面声明多个修改的主要原因是原先需要的对表的多次扫描和重写可以组合成一个步骤。
DROP COLUMN 命令并不是物理上把字段删除,而只是简单地把它标记为对 SQL 操作不可见。随后对该表的插入和更新将在该字段存储一个 NULL 。因此,删除一个字段是很快的,但是它不会立即释放表在磁盘上的空间,因为被删除了的字段占据的空间还没有回收。这些空间将随着现有的行的更新而得到回收。
ALTER TYPE 要求重写整个表的特性有时候是一个优点,因为重写的过程消除了表中没用的空间。比如,要想立刻回收被一个已经删除的字段占据的空间,最快的方法是
ALTER TABLE table ALTER COLUMN anycol TYPE anytype;
这里的 anycol 是任何在表中还存在的字段,而 anytype 是和该字段的原类型一样的类型。这样的结果是在表上没有任何可见的语意的变化,但是这个命令强迫重写,这样就删除了不再使用的数据。
ALTER TYPE 的 USING 选项实际上可以声明涉及该行旧值的任何表达式;也就是说,它可以引用除了正在被转换的字段之外其它的字段。这样,就可以用 ALTER TYPE 语法做非常普遍性的转换。因为这个灵活性,USING 表达式并没有作用于该字段的缺省值(如果有的话);结果可能不是缺省表达式要求的常量表达式。这就意味着如果从旧类型到新类型没有隐含或者赋值转换的话,那么即使存在 USING 子句,ALTER TYPE 也可能无法把缺省值转换成新的类型。在这种情况下,应该用 DROP DEFAULT 先删除缺省,执行 ALTER TYPE ,然后使用 SET DEFAULT 增加一个合适的新缺省值。类似的考虑也适用于涉及该字段的索引和约束。
如果表有任何后代表,那么如果不在后代表上做同样的修改的话,就不允许在父表上增加、重命名、修改一个字段的类型,也就是说,ALTER TABLE ONLY 将被拒绝。这样就保证了后代表总是有和父表匹配的字段。
一个递归 DROP COLUMN 操作将只有在后代表并不从任何其它父表中继承该字段并且从来没有独立定义该字段的时候才能删除一个后代表的字段。一个非递归的 DROP COLUMN(也就是 ALTER TABLE ONLY ... DROP COLUMN) 从来不会删除任何后代字段,而是把他们标记为独立定义的(而不是继承的)。
TRIGGER, CLUSTER, OWNER, TABLESPACE 行为绝不会递归到后代表;也就是说,它们的行为就像总是声明了 ONLY 一样。添加一个约束只能在 CHECK 约束上递归。
不允许更改系统表结构的任何部分。
请参考 CREATE TABLE 部分获取更多有效参数的描述。章5里有更多有关继承的信息。
向表中增加一个 varchar 列:
ALTER TABLE distributors ADD COLUMN address varchar(30);
从表中删除一个字段:
ALTER TABLE distributors DROP COLUMN address RESTRICT;
在一个操作中修改两个现有字段的类型:
ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER COLUMN name TYPE varchar(100);
使用一个 USING 子句,把一个包含 UNIX 时间戳的 integer 字段转化成 timestamp with time zone 字段:
ALTER TABLE foo ALTER COLUMN foo_timestamp TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second';
同样地,当字段有一个不会自动转换成新类型的缺省值表达式时:
ALTER TABLE foo ALTER COLUMN foo_timestamp DROP DEFAULT, ALTER COLUMN foo_timestamp TYPE timestamp with time zone USING timestamp with time zone 'epoch' + foo_timestamp * interval '1 second', ALTER COLUMN foo_timestamp SET DEFAULT now();
对现存字段改名:
ALTER TABLE distributors RENAME COLUMN address TO city;
更改现存表的名字:
ALTER TABLE distributors RENAME TO suppliers;
给一个字段增加一个非空约束:
ALTER TABLE distributors ALTER COLUMN street SET NOT NULL;
从一个字段里删除一个非空约束:
ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL;
给一个表增加一个检查约束:
ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
删除一个表及其所有子表的监查约束:
ALTER TABLE distributors DROP CONSTRAINT zipchk;
向表中增加一个外键约束:
ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) MATCH FULL;
给表增加一个(多字段)唯一约束:
ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode);
给一个表增加一个自动命名的主键约束,要注意的是一个表只能有一个主键:
ALTER TABLE distributors ADD PRIMARY KEY (dist_id);
把表移动到另外一个表空间:
ALTER TABLE distributors SET TABLESPACE fasttablespace;
把表移动到另外一个模式:
ALTER TABLE myschema.distributors SET SCHEMA yourschema;