ALTER TABLE

ALTER TABLE

更改一个表的定义。

概要

ALTER TABLE [IF EXISTS] [ONLY] name 
    action [, ... ]

ALTER TABLE [IF EXISTS] [ONLY] name 
    RENAME [COLUMN] column_name TO new_column_name

ALTER TABLE [ IF EXISTS ] [ ONLY ] name 
    RENAME CONSTRAINT constraint_name TO new_constraint_name

ALTER TABLE [IF EXISTS] name 
    RENAME TO new_name

ALTER TABLE [IF EXISTS] name 
    SET SCHEMA new_schema

ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
    SET TABLESPACE new_tablespace [ NOWAIT ]

ALTER TABLE [IF EXISTS] [ONLY] name SET 
     WITH (REORGANIZE=true|false)
   | DISTRIBUTED BY ({column_name [opclass]} [, ... ] )
   | DISTRIBUTED RANDOMLY
   | DISTRIBUTED REPLICATED 

ALTER TABLE name
   [ ALTER PARTITION { partition_name | FOR (RANK(number)) 
   | FOR (value) } partition_action [...] ] 
   partition_action

其中 action 是下列之一:
                        
  ADD [COLUMN] column_name data_type [ DEFAULT default_expr ]
      [column_constraint [ ... ]]
      [ COLLATE collation ]
      [ ENCODING ( storage_directive [,...] ) ]
  DROP [COLUMN] [IF EXISTS] column_name [RESTRICT | CASCADE]
  ALTER [COLUMN] column_name [ SET DATA ] TYPE type [COLLATE collation] [USING expression]
  ALTER [COLUMN] column_name SET DEFAULT expression
  ALTER [COLUMN] column_name DROP DEFAULT
  ALTER [COLUMN] column_name { SET | DROP } NOT NULL
  ALTER [COLUMN] column_name SET STATISTICS integer
  ALTER [COLUMN] column SET ( attribute_option = value [, ... ] )
  ALTER [COLUMN] column RESET ( attribute_option [, ... ] )
  ADD table_constraint [NOT VALID]
  ADD table_constraint_using_index
  VALIDATE CONSTRAINT constraint_name
  DROP CONSTRAINT [IF EXISTS] constraint_name [RESTRICT | CASCADE]
  DISABLE TRIGGER [trigger_name | ALL | USER]
  ENABLE TRIGGER [trigger_name | ALL | USER]
  CLUSTER ON index_name
  SET WITHOUT CLUSTER
  SET WITH OIDS
  SET WITHOUT OIDS
  SET (storage_parameter = value)
  RESET (storage_parameter [, ... ])
  INHERIT parent_table
  NO INHERIT parent_table
  OF type_name
  NOT OF
  OWNER TO new_owner
  SET TABLESPACE new_tablespace

where partition_action is one of:

  ALTER DEFAULT PARTITION
  DROP DEFAULT PARTITION [IF EXISTS]
  DROP PARTITION [IF EXISTS] { partition_name | 
      FOR (RANK(number)) | FOR (value) } [CASCADE]
  TRUNCATE DEFAULT PARTITION
  TRUNCATE PARTITION { partition_name | FOR (RANK(number)) | 
      FOR (value) }
  RENAME DEFAULT PARTITION TO new_partition_name
  RENAME PARTITION { partition_name | FOR (RANK(number)) | 
      FOR (value) } TO new_partition_name
  ADD DEFAULT PARTITION name [ ( subpartition_spec ) ]
  ADD PARTITION [partition_name] partition_element
     [ ( subpartition_spec ) ]
  EXCHANGE PARTITION { partition_name | FOR (RANK(number)) | 
       FOR (value) } WITH TABLE table_name
        [ WITH | WITHOUT VALIDATION ]
  EXCHANGE DEFAULT PARTITION WITH TABLE table_name
   [ WITH | WITHOUT VALIDATION ]
  SET SUBPARTITION TEMPLATE (subpartition_spec)
  SPLIT DEFAULT PARTITION
    {  AT (list_value)
     | START([datatype] range_value) [INCLUSIVE | EXCLUSIVE] 
        END([datatype] range_value) [INCLUSIVE | EXCLUSIVE] }
    [ INTO ( PARTITION new_partition_name, 
             PARTITION default_partition_name ) ]
  SPLIT PARTITION { partition_name | FOR (RANK(number)) | 
     FOR (value) } AT (value) 
    [ INTO (PARTITION partition_name, PARTITION partition_name)]  

where partition_element is:

    VALUES (list_value [,...] )
  | START ([datatype] 'start_value') [INCLUSIVE | EXCLUSIVE]
     [ END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE] ]
  | END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE]
[ WITH ( partition_storage_parameter=value [, ... ] ) ]
[ TABLESPACE tablespace ]

where subpartition_spec is:

subpartition_element [, ...]

and subpartition_element is:

   DEFAULT SUBPARTITION subpartition_name
  | [SUBPARTITION subpartition_name] VALUES (list_value [,...] )
  | [SUBPARTITION subpartition_name] 
     START ([datatype] 'start_value') [INCLUSIVE | EXCLUSIVE]
     [ END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE] ]
     [ EVERY ( [number | datatype] 'interval_value') ]
  | [SUBPARTITION subpartition_name] 
     END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE]
     [ EVERY ( [number | datatype] 'interval_value') ]
[ WITH ( partition_storage_parameter=value [, ... ] ) ]
[ TABLESPACE tablespace ]

where storage_parameter is:

   appendoptimized={TRUE|FALSE}
   blocksize={8192-2097152}
   orientation={COLUMN|ROW}
   compresstype={ZLIB|ZSTD|QUICKLZ|RLE_TYPE|NONE}
   compresslevel={0-9}
   fillfactor={10-100}
   oids[=TRUE|FALSE]

描述

ALTER TABLE 更改一个表的定义。下文描述了几种形式:

  • ADD COLUMN — 向表中增加一个新列,使用和CREATE TABLE相同的语义。ENCODING 子句只有在追加和列存储表中有效
  • DROP COLUMN [IF EXISTS] — 从表中删除列。 请注意,如果删除用作Greenplum数据库分配键的表列,则表的分配策略将更改为DISTRIBUTED RANDOMLY.。 涉及该列的索引和表约束也会自动删除。 如果表外的任何内容都取决于列(例如视图),则需要指定CASCADE。 如果指定了IF EXISTS且该列不存在,则不会引发任何错误; 而是发出通知。
  • IF EXISTS — 如果表不存在,请不要抛出错误。 在这种情况下发出通知。
  • SET DATA TYPE — 此表单更改表的列的数据类型。 请注意,您不能更改用作分发键或分区键的列数据类型。 通过重新解析最初提供的表达式,涉及该列的索引和简单表约束将自动转换为使用新的列类型。 可选的COLLATE子句为新列指定排序规则,如果省略,则排序规则是新列类型的默认排序规则。 可选的USING子句指定如何从旧的值计算新的列值。 如果省略,则默认转换与从旧数据类型到新数据类型的转换相同。 如果没有从旧类型转换为新类型的隐式或赋值,则必须提供USING子句。
    Note: 仅当查询中的所有列使用相同的排序规则时,GPORCA才支持排序规则。 如果查询中的列使用不同的排序规则,则Greenplum使用Postgres Planner。
  • SET/DROP DEFAULT — 设置或删除列的默认值。 默认值仅适用于后续的INSERTUPDATE命令。 它们不会导致表中已有的行发生更改。
  • SET/DROP NOT NULL — 更改是将列标记为允许空值还是拒绝空值。 当列不包含空值时,只能使用SET NOT NULL
  • SET STATISTICS — 为后续的ANALYZE操作设置每个列的统计信息收集目标。 可以在100到10000的范围内设置目标,也可以设置为-1以使用系统默认统计信息目标(default_statistics_target)恢复为目标。
  • SET ( attribute_option = value [, ... ])

    RESET ( attribute_option [, ...] )— 设置或重置每个属性选项。当前,唯一定义的按属性的选项是 n_distinctn_distinct_inherited,它们覆盖了后续 ANALYZE 操作所做的不同值估计数。 n_distinct 影响表本身的统计信息,而n_distinct_inherited影响表及其继承子级收集的统计信息。当设置为正值时,ANALYZE将假定该列恰好包含指定数量的不同非空值。当设置为负值(必须大于或等于-1)时,ANALYZE将假定列中不同的非空值的数量在表的大小中是线性的;确切的计数应通过将估计的表大小乘以给定数字的绝对值来计算。例如,值-1表示该列中的所有值都是不同的,而值-0.5表示每个值平均出现两次。当表的大小随时间变化时,这很有用,因为直到查询计划时间才执行表中行数的乘法。将值指定为0可恢复为通常估计不同值的数量

  • ADD table_constraint [NOT VALID] — 使用与CREATE TABLE相同的语法向表(不仅仅是分区)添加新约束。 当前仅将NOT VALID选项用于外键和CHECK约束。 如果约束标记为NOT VALID,则Greenplum数据库将跳过可能冗长的初始检查,以验证表中的所有行均满足约束。 约束将仍然针对后续的插入或更新(即,对于外键而言,除非在引用表中有匹配的行,否则它们将失败;对于外键,除非新行与指定的检查匹配,否则它们将失败) 约束)。 但是,除非使用VALIDATE CONSTRAINT选项对其进行验证,否则数据库将不假定该约束对表中的所有行均有效。 创建表时将跳过约束检查,因此CREATE TABLE语法不包括此选项。
  • VALIDATE CONSTRAINT — 该形式通过扫描表以确保没有不满足该约束的行,从而验证了以前创建为NOT VALID的外键约束。 如果约束已被标记为有效,则什么也不会发生。 将验证与约束的初始创建分开的好处是,与约束创建相比,验证对表的锁定更少。
  • ADD table_constraint_using_index — 根据现有的唯一索引将新的 PRIMARY KEYUNIQUE 约束添加到表中。 索引的所有列都将包含在约束中。 索引不能具有表达式列,也不能是部分索引。 另外,它必须是具有默认排序顺序的b树索引。 这些限制确保索引等于由常规ADD PRIMARY KEYADD UNIQUE命令建立的索引。

    如果指定了 PRIMARY KEY,并且索引的列尚未标记为NOT NULL,则此命令将尝试对每个此类列执行ALTER COLUMN SET NOT NULL。 这需要全表扫描,以验证列不包含空值。 在所有其他情况下,这是一个快速的操作。

    如果提供了约束名称,那么索引将被重命名以匹配约束名称。 否则,约束将被命名为与索引相同。

    执行此命令后,索引将由约束“拥有”,就像使用常规 ADD PRIMARY KEYADD UNIQUE命令构建索引一样。 特别是,删除约束将使索引也消失。

    Note: 在需要添加新约束而不长时间阻止表更新的情况下,使用现有索引添加约束可能会有所帮助。 为此,请使用 CREATE INDEX CONCURRENTLY 创建索引,然后使用此语法将其安装为正式约束。 请参见下面的示例。
  • DROP CONSTRAINT [IF EXISTS] — 将指定的约束放在表上。 如果指定了IF EXISTS且该约束不存在,则不会引发任何错误。 在这种情况下,将发出通知。
  • DISABLE/ENABLE TRIGGER — 禁用或启用属于该表的触发器。 禁用的触发器对于系统仍然是已知的,但是在其触发事件发生时不会执行。 对于延迟的触发器,将在事件发生时而不是在实际执行触发器功能时检查启用状态。 可以禁用或启用由名称指定的单个触发器,或表上的所有触发器,或仅由用户创建的触发器。 禁用或启用约束触发器需要超级用户特权。
    Note: Greenplum数据库中不支持触发器。 由于Greenplum数据库的并行性,触发器通常具有非常有限的功能。
  • CLUSTER ON/SET WITHOUT CLUSTER — 选择或删除默认索引以用于将来的CLUSTER操作。 它实际上并没有重新群集表。 请注意,建议不要使用CLUSTER对Greenplum数据库中的表进行物理重新排序,因为它会花费很长时间。 最好使用CREATE TABLE AS重新创建表并按索引列对其进行排序。
    Note: 追加优化表不支持CLUSTER ON
  • SET WITH OIDS — 往表中添加一个系统列 oid。如果表中已有OID列则不会做任何操作, 这与ADD COLUMN oid oid的操作并不相等,ADD COLUMN oid oid会增加一个正常的名为oid的正常列,而不是增加一个系统列。OIDs不允许增加在分区表或者追加优化列组织表。
    Warning: Greenplum强烈建议您在创建表时不要启用OIDS。 在大型表(例如典型的Greenplum数据库系统中的表)上,对表行使用OID可能会导致32位OID计数器的折回。 一旦计数器回绕,就不能再认为OID是唯一的,这不仅使OID对用户应用程序无用,而且还会在Greenplum数据库系统目录表中引起问题。 此外,从表中排除OID会使每行将表存储在磁盘上所需的空间减少了每行4个字节,从而略微提高了性能。
  • SET WITHOUT OIDS — 从表中删除OID系统列。
  • SET ( FILLFACTOR = value) / RESET (FILLFACTOR) — 更改表的填充因子。 表格的填充系数是10到100之间的百分比。默认值为100(完全打包)。 当指定较小的填充因子时,INSERT操作仅将表页面打包到指定的百分比; 每个页面上的剩余空间都保留用于更新该页面上的行。 这样,UPDATE就有机会将行的更新副本与原始副本放置在同一页面上,这比将其放置在另一页面上更为有效。 对于一个条目从不更新的表,完全打包是最佳选择,但在更新频繁的表中,较小的填充因子是合适的。 请注意,此命令不会立即修改表内容。 您将需要重写表以获得所需的效果。 可以使用VACUUM或强制表重写的ALTER TABLE形式之一来完成。
  • SET DISTRIBUTED — 更改表的分配策略。 更改哈希分发策略,或更改为复制策略或从复制策略更改将导致表数据在磁盘上进行物理重新分发,这可能会占用大量资源。
  • INHERIT parent_table / NO INHERIT parent_table — 添加或删除目标表作为指定父表的子表。 对父级的查询将包括其子表的记录。 要作为子项添加,目标表必须已经包含与父项相同的所有列(它也可以具有其他列)。 这些列必须具有匹配的数据类型,并且如果它们在父级中具有NOT NULL约束,那么它们在子级中也必须具有NOT NULL约束。 对于父级的所有CHECK约束,还必须有匹配的子表约束,但在父级中标记为不可继承的(即用ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT创建)的约束除外。 匹配的所有子表约束均不得标记为不可继承。 当前不考虑UNIQUE, PRIMARY KEYFOREIGN KEY约束,但是将来可能会改变。
  • OF type_name — 这种形式将表链接到复合类型,就像CREATE TABLE OF已经形成了它一样。 该表的列名和类型列表必须与组合类型的列表完全匹配; oid系统列的存在可以不同。 该表不得从任何其他表继承。 这些限制确保 CREATE TABLE OF将允许等效的表定义。
  • NOT OF — 这种形式将类型化表与其类型分离。
  • OWNER — 将表,序列或视图的所有者更改为指定的用户。
  • SET TABLESPACE — 将表的表空间更改为指定的表空间,并将与表关联的数据文件移动到新表空间。表中的索引(如果有)不会移动;但是可以使用其他SET TABLESPACE命令分别移动它们。可以使用ALL IN TABLESPACE表单移动表空间中当前数据库中的所有表,该表单将锁定所有要先移动的表,然后再移动每个表。此表单还支持OWNED BY,该操作仅移动指定角色所拥有的表。如果指定了NOWAIT选项,则如果该命令无法立即获取所有必需的锁,则该命令将失败。请注意,此命令不会移动系统目录,请根据需要使用ALTER DATABASE或显式ALTER TABLE调用。 information_schema关系不视为系统目录的一部分,将被移动。另请参见CREATE TABLESPACE。如果更改分区表的表空间,则所有子表分区也将移至新表空间。
  • RENAME — 更改表(或索引,序列或视图)的名称,表中单个列的名称或表的约束的名称。 对存储的数据没有影响。 请注意,Greenplum数据库分发密钥列不能重命名。
  • SET SCHEMA — 将表移到另一个架构。 表列拥有的关联索引,约束和序列也将移动。
  • ALTER PARTITION | DROP PARTITION | RENAME PARTITION | TRUNCATE PARTITION | ADD PARTITION | SPLIT PARTITION | EXCHANGE PARTITION | SET SUBPARTITION TEMPLATE — 更改分区表的结构。 在大多数情况下,您必须遍历父表才能更改其子表分区之一。
Note: 如果将分区添加到具有子分区编码的表中,则新分区将继承该子分区的存储指令。 有关压缩设置优先级的更多信息,请参阅Greenplum Database Administrator Guide中的“使用压缩”。

RENAMESET SCHEMA之外,所有作用于单个表的ALTER TABLE形式都可以组合成多个更改列表以一起应用。 例如,可以在单个命令中添加几列和/或更改几列的类型。 这对于大型表尤其有用,因为只需要对表进行一次遍历。

您必须拥有该表才能使用ALTER TABLE。 要更改表的架构或表空间,您还必须对新架构或表空间具有CREATE特权。 要将表添加为父表的新子级,您还必须拥有父表。 要更改所有者,您还必须是新拥有角色的直接或间接成员,并且该角色必须对表的架构具有CREATE特权。 要添加列或更改列类型或使用OF子句,您还必须对数据类型具有USAGE特权。 超级用户自动具有这些特权。

Note: 如果表具有多个分区,表具有压缩功能或表的块大小很大,则内存使用量会显着增加。 如果与该表关联的关系的数量很大,则这种情况可能会迫使对该表进行的操作使用更多的内存。 例如,如果该表是一个CO表并具有大量列,则每个列都是一个关系。 诸如ALTER TABLE ALTER COLUMN之类的操作将打开表中的所有列,以分配关联的缓冲区。 如果CO表具有40列和100个分区,并且这些列被压缩并且块大小为2 MB(系统系数为3),则系统尝试分配24 GB,即(40×100)×(2× 3)MB或24 GB。

参数

ONLY
仅对指定的表名执行操作。 如果不使用 ONLY关键字,则将在命名表以及与该表关联的任何子表分区上执行该操作。
Note: 只允许在父表或子表中添加或删除列,或更改列的类型。 父表及其后代必须始终具有相同的列和类型。
name
要更改的现有表的名称(可能是模式限定的)。 如果ONLY指定,则仅更改该表。 如果未指定ONLY,则更新表及其所有后代表(如果有)。
Note: 约束只能添加到整个表,不能添加到分区。 由于该限制,name参数只能包含表名,而不能包含分区名。
column_name
新列或现有列的名称。 请注意,Greenplum数据库分发键列必须格外小心。 更改或删除这些列可以更改表的分发策略。
new_column_name
现有列的新名称。
new_name
表的新名称。
type
新列的数据类型,或现有列的新数据类型。 如果更改Greenplum分布键列的数据类型,则只能将其更改为兼容类型(例如,textvarchar可以,但textint则不能)。
table_constraint
表的新表约束。 请注意,Greenplum数据库当前不支持外键约束。 此外,表仅允许一个唯一约束,并且唯一性必须在Greenplum数据库分发密钥内。
constraint_name
要删除的现有约束的名称。
CASCADE
自动删除依赖于已删除列或约束的对象(例如,引用该列的视图)。
RESTRICT
如果有任何相关对象,则拒绝删除列或约束。 这是默认行为。
trigger_name
要禁用或启用的单个触发器的名称。 请注意,Greenplum数据库不支持触发器。
ALL
禁用或启用属于该表的所有触发器,包括与约束相关的触发器。 如果任何触发器是内部生成的约束触发器(例如用于实现外键约束或可延迟的唯一性和排除约束的触发器),则这需要超级用户特权。
USER
禁用或启用属于该表的所有触发器,但内部生成的约束触发器(例如用于实现外键约束或可延迟的唯一性和排除约束的触发器除外)除外。
index_name
表应标记为集群的索引名称。 请注意,建议不要使用CLUSTER对Greenplum数据库中的表进行物理重新排序,因为它会花费很长时间。 最好使用CREATE TABLE AS重新创建表并按索引列对其进行排序。
FILLFACTOR
设置表格的填充系数百分比。
value
FILLFACTOR参数的新值,介于10到100之间的百分比。默认值为100。
DISTRIBUTED BY ({column_name [opclass]}) | DISTRIBUTED RANDOMLY | DISTRIBUTED REPLICATED
指定表的分发策略。 更改哈希分发策略会导致物理上重新分配表数据,这可能会占用大量资源。 如果声明相同的哈希分配策略或从哈希更改为随机分配,则除非声明SET WITH (REORGANIZE=true),否则不会重新分配数据。
更改为复制的分发策略或从复制的分发策略更改将导致表数据被重新分发。
REORGANIZE=true|false
当哈希分配策略未更改或从哈希更改为随机分配,并且无论如何都希望重新分配数据时,请使用REORGANIZE=true
parent_table
父表要与此表关联或取消关联。
new_owner
表的新所有者的角色名称。
new_tablespace
该表将被移动到的表空间的名称。
new_schema
表将被移动到的模式的名称。
parent_table_name
更改分区表时,顶级父表的名称。
ALTER [DEFAULT] PARTITION
如果要更改的分区比第一级分区深,请使用ALTER PARTITION子句指定要更改层次结构中的哪个子分区
DROP [DEFAULT] PARTITION
删除指定的分区。 如果分区具有子分区,则子分区也会自动删除。
TRUNCATE [DEFAULT] PARTITION
截断指定的分区。 如果分区具有子分区,则子分区也会自动被截断。
RENAME [DEFAULT] PARTITION
更改分区的分区名称(而不是关系名称)。 分区表是使用以下命名约定创建的: <parentname>_<level>_prt_<partition_name>.
ADD DEFAULT PARTITION
将默认分区添加到现有分区设计中。 当数据与现有分区不匹配时,会将其插入默认分区。 没有默认分区的分区设计将拒绝与现有分区不匹配的传入行。 必须为默认分区指定名称。
ADD PARTITION
partition_element - 使用表(范围或列表)的现有分区类型,定义要添加的新分区的边界。
name - 此新分区的名称。
VALUES - 对于列表分区,定义分区将包含的值。
START - 对于范围分区,定义分区的起始范围值。 默认情况下,起始值为INCLUSIVE。 例如,如果您声明开始日期为“ 2016-01-01”,则分区将包含所有大于或等于“ 2016-01-01”的日期。 通常,START表达式的数据类型与分区键列的类型相同。 如果不是这种情况,则必须显式转换为预期的数据类型。
END - 对于范围分区,定义分区的结束范围值。 默认情况下,最终值为EXCLUSIVE。 例如,如果您声明结束日期为“ '2016-02-01”,则分区将包含所有小于但不等于“ '2016-02-01”的日期。 通常, END表达式的数据类型与分区键列的类型相同。 如果不是这种情况,则必须显式转换为预期的数据类型。
WITH - 设置分区的表存储选项。 例如,您可能希望将较旧的分区作为追加优化表,而将较新的分区作为常规堆表。 有关存储选项的说明,请参见CREATE TABLE
TABLESPACE - 要在其中创建分区的表空间的名称。
subpartition_spec - 仅允许在没有子分区模板的情况下创建的分区设计。 声明要添加的新分区的子分区规范。 如果分区表最初是使用子分区模板定义的,则该模板将用于自动生成子分区。
EXCHANGE [DEFAULT] PARTITION
将另一个表交换到分区层次结构中,替换为现有分区的位置。 在多级分区设计中,您只能交换最低级别的分区(包含数据的分区)。
Greenplum数据库服务器配置参数gp_enable_exchange_default_partition控制EXCHANGE DEFAULT PARTITION子句的可用性。 该参数的默认值是off。 该子句不可用,如果在ALTER TABLE命令中指定了该子句,则Greenplum数据库将返回错误。
有关该参数的信息,请参阅服务器配置参数.
Warning: 交换默认分区之前,必须确保要交换的表中的数据(新的默认分区)对默认分区有效。 例如,新的默认分区中的数据不得包含在分区表的其他叶子分区中有效的数据。 否则,由GPORCA执行的具有交换的默认分区的分区表查询可能会返回错误的结果。
WITH TABLE table_name - 您要交换到分区设计中的表的名称。 您可以交换一个表,其中表数据存储在数据库中。 例如,该表是使用CREATE TABLE命令创建的。 该表必须具有与父表相同的列数,列顺序,列名,列类型和分发策略。
使用EXCHANGE PARTITION子句,您还可以将可读的外部表(使用CREATE EXTERNAL TABLE命令创建)交换到分区层次结构中,而不是现有的叶子子分区。 如果您指定了可读的外部表,则还必须指定WITHOUT VALIDATION子句,以针对要交换的分区的 CHECK约束跳过表验证。
如果分区表包含具有检查约束或NOT NULL约束的列,则不支持与外部表交换叶子分区。
您无法与复制表交换分区。 不支持将分区与分区表或分区表的子分区交换。
WITH | WITHOUT VALIDATION - 验证表中的数据是否与您要交换的分区的CHECK约束相匹配。 默认设置是根据CHECK约束验证数据。
Warning: 如果指定WITHOUT VALIDATION子句,则必须确保针对现有子叶分区交换的表中的数据对于分区上的CHECK约束是有效的。
SET SUBPARTITION TEMPLATE
修改现有分区的子分区模板。 设置新的子分区模板后,所有添加的新分区将具有新的子分区设计(现有分区不会被修改)。
SPLIT DEFAULT PARTITION
分割默认分区。 在多级分区中,只能拆分范围分区,而不能拆分列表分区,并且只能拆分最低级别的默认分区(包含数据的分区)。 拆分默认分区将创建一个包含指定值的新分区,并保留默认分区,其中包含与现有分区不匹配的任何值。
AT - 对于列表分区表,指定一个列表值,该值应用作拆分条件。
START - 对于范围分区表,指定新分区的起始值。
END - 对于范围分区表,指定新分区的结束值。
INTO - 允许您为新分区指定名称。 使用INTO子句拆分默认分区时,指定的第二个分区名称应始终为现有默认分区的名称。 如果您不知道默认分区的名称,则可以使用pg_partitions视图进行查找。
SPLIT PARTITION
将现有分区分为两个分区。 在多级别分区中,只能拆分范围分区,而不能拆分列表分区,并且只能拆分最低级别的分区(包含数据的分区)。
AT - 指定一个单一值,该值应用作分割条件。 该分区将分为两个新分区,指定的分割值是后一个分区的起始范围。
INTO - 允许用户为分裂创建两个新分区指定名字。
partition_name
给定的分区名称。
FOR (RANK(number))
对于范围分区,分区在范围中的排名。
FOR ('value')
通过声明一个落在分区边界说明中的值来指定一个分区。如果用FOR声明的值匹配一个分区和它的一个子分区(例如,如果值是一个日期并且表先按月分区然后按日分区),那么FOR将在第一个找到匹配的层次上操作(例如,每月的分区)。如果用户的目的是在子分区上操作,则必须按如下的方式声明:ALTER TABLE name ALTER PARTITION FOR ('2016-10-01') DROP PARTITION FOR ('2016-10-01');

注解

ALTER TABLE 命令中指定的表名不能是一个表中的分区名。

在修改或者删除作为Greenplum数据库分布键一部分的列时要特别小心,因为这可能会改变表的分布策略。.

Greenplum数据库当前不支持外键约束。对于要在Greenplum数据库中实施的唯一约束,表必须被哈希分布(不能用DISTRIBUTED RANDOMLY),并且所有的分布键列必须和唯一约束列中前部的列相同。

增加CHECK或者NOT NULL约束要求扫描表以验证现有的行是否符合约束。

当使用ADD COLUMN添加列时,表中的所有现有行都使用该列的默认值初始化,如果未指定DEFAULT子句,则初始化为NULL。添加具有非空默认值的列或更改现有列的类型将需要重写整个表和索引。作为例外,如果USING子句不更改列的内容,并且旧类型可以强制转换为新类型或新类型不受限制的域,则不需要重写表,但是受影响列上的任何索引都必须仍在重建中。添加或删除系统oid列还需要重写整个表。对于大型表,表和/或索引的重建可能会花费大量时间;并且暂时需要多达两倍的磁盘空间。

您可以在单个ALTER TABLE命令中指定多个更改,这些更改将在表上一次传递。

DROP COLUMN 表单不会物理删除列,而只是使它对SQL操作不可见。表中随后的插入和更新操作将为该列存储一个空值。因此,删除列很快,但是不会立即减小表的磁盘大小,因为删除的列所占用的空间不会被回收。随着现有行的更新,空间将随着时间的推移而回收。但是,如果删除系统oid列,则表将立即被重写。

要强制立即回收被删除的列占用的空间,您可以执行ALTER TABLE的一种形式来重写整个表。这将导致重建的每一行,并将删除的列替换为空值。

ALTER TABLE的重写形式不是MVCC安全的。在表重写之后,如果并发事务使用的是在重写发生之前拍摄的快照,则该表将对并发事务显示为空。有关更多详细信息,请参见MVCC Caveats

SET DATA TYPEUSING选项实际上可以指定涉及该行的旧值的任何表达式。也就是说,它可以引用其他列以及要转换的列。这允许使用SET DATA TYPE语法完成非常通用的转换。由于具有这种灵活性,因此USING表达式不会应用于列的默认值(如果有);结果可能不是默认值所需的常量表达式。这意味着当没有从旧类型到新类型的隐式或赋值转换时,即使提供了USING子句,SET DATA TYPE也可能无法转换默认值。在这种情况下,请使用DROP DEFAULT删除默认值,执行ALTER TYPE,然后使用SET DEFAULT添加合适的新默认值。类似的考虑适用于涉及该列的索引和约束。

如果表已分区或具有任何后代表,则不允许在父表中添加,重命名或更改列的类型或重命名继承的约束,而无需对后代进行相同的操作。这样可以确保后代始终具有与父代匹配的列。

要查看分区表的结构,可以使用视图pg_partitions。该视图可以帮助您识别您可能要更改的特定分区。

仅当后代不从任何其他父级继承该列并且从未对该列进行独立定义时,递归DROP COLUMN操作才会删除后代表的列。非递归DROP COLUMN(仅ALTER TABLE ONLY ... DROP COLUMN)从不删除任何后代列,而是将它们标记为独立定义而不是继承。

TRIGGER, CLUSTER, OWNERTABLESPACE操作永远不会递归到后代表。也就是说,它们始终像指定ONLY那样起作用。仅对未标记为NO INHERITCHECK约束重复添加约束。

如果包含已被交换以使用外部表的叶子分区的分区表上的数据没有更改,则支持这些ALTER PARTITION操作。否则,将返回错误。
  • Adding or dropping a column.
  • Changing the data type of column.
分区表不支持这些ALTER PARTITION操作,该分区表包含已被交换以使用外部表的叶子分区:
  • Setting a subpartition template.
  • Altering the partition properties.
  • Creating a default partition.
  • Setting a distribution policy.
  • Setting or dropping a NOT NULL constraint of column.
  • Adding or dropping constraints.
  • Splitting an external partition.

不允许更改系统目录表的任何部分。

Examples

向列中添加列:

ALTER TABLE distributors ADD COLUMN address varchar(30);

重命名现有列:

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 RENAME CONSTRAINT zipchk TO zip_check;

向表及其所有子级添加检查约束:

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK 
(char_length(zipcode) = 5);

要将检查约束仅添加到表而不是其子表,请执行以下操作:

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT;

(检查约束也不会被将来的子代继承。)

从表及其所有子级中删除检查约束:

ALTER TABLE distributors DROP CONSTRAINT zipchk;

仅从一个表中删除检查约束:

ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk;

(对于任何继承distributors的子表,检查约束仍然存在。)

将表移动到不同的模式:

ALTER TABLE myschema.distributors SET SCHEMA yourschema;

将表的分发策略更改为已复制:

ALTER TABLE myschema.distributors SET DISTRIBUTED REPLICATED;

将新分区添加到分区表:

ALTER TABLE sales ADD PARTITION 
            START (date '2017-02-01') INCLUSIVE 
            END (date '2017-03-01') EXCLUSIVE;

向现有分区设计添加默认分区:

ALTER TABLE sales ADD DEFAULT PARTITION other;

重命名分区:

ALTER TABLE sales RENAME PARTITION FOR ('2016-01-01') TO 
jan08;

删除范围序列中的第一个(最旧的)分区:

ALTER TABLE sales DROP PARTITION FOR (RANK(1));

将表交换到用户的分区设计中:

ALTER TABLE sales EXCHANGE PARTITION FOR ('2016-01-01') WITH 
TABLE jan08;

拆分默认分区(现有的默认分区名称other)为2017年1月添加新的每月分区:

ALTER TABLE sales SPLIT DEFAULT PARTITION 
START ('2017-01-01') INCLUSIVE 
END ('2017-02-01') EXCLUSIVE 
INTO (PARTITION jan09, PARTITION other);

将每月分区分成两个分区,第一个分区包含日期1月1日至15日,第二个分区包含日期1月16日至31日:

ALTER TABLE sales SPLIT PARTITION FOR ('2016-01-01')
AT ('2016-01-16')
INTO (PARTITION jan081to15, PARTITION jan0816to31);

要重新创建主键约束,而在重建索引时不阻止更新:

CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id);
ALTER TABLE distributors DROP CONSTRAINT distributors_pkey,
ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx;
                        

兼容性

ADD (不包含 USING INDEX), DROP, SET DEFAULTSET DATA TYPE (不包含 USING) 符合SQL标准。 其他形式是SQL标准的Greenplum数据库扩展。 同样,在单个ALTER TABLE命令中指定多个操纵的功能也是一种扩展。

ALTER TABLE DROP COLUMN可用于删除表的唯一列,而保留零列表。 这是SQL的扩展,不允许使用零列表。