更改一个表的定义。
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] name
SET (encodechain=new_encodechain)
ALTER TABLE [IF EXISTS] [ONLY] name SET
WITH (REORGANIZE=true|false)
| DISTRIBUTED BY ({column_name [opclass]} [, ... ] )
| DISTRIBUTED RANDOMLY
| DISTRIBUTED REPLICATED
ALTER TABLE [IF EXISTS] [ONLY] name SET SEGMENT_SET segment_set_name
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 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
其中 table_constraint_using_index 是:
[ CONSTRAINT constraint_name ]
{ UNIQUE | PRIMARY KEY } USING INDEX index_name
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
partition_action 是:
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]
[[SEGMENT_SET segment_set_name]] }
[ 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)]
其中 partition_element 如下:
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 ]
其中 subpartition_spec 是:
subpartition_element [, ...]
其中 subpartition_element 是:
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 ]
其中 storage_parameter 是:
appendoptimized={TRUE|FALSE}
blocksize={8192-2097152}
orientation={COLUMN|ROW}
compresstype={ZLIB|ZSTD|QUICKLZ|RLE_TYPE|NONE|MXCUSTOM}
// 当 compresstype=MXCUSTOM,需指定具体的 encodechain
encodechain={LZ4|ZSTD|DELTADELTA(缩放位数)|DELTAZIGZAG|GORILLA|FLOATINT|SIMPLE8B|AUTO}
/* 当 compresstype=MXCUSTOM,且 encodechain=AUTO 时,支持在表级别指定自适应编码模式:
* automode=1 表示压缩率优先,automode=2 表示速度优先
*/
automode={1|2}
compresslevel={0-9}
fillfactor={10-100}
oids[FALSE]
ALTER TABLE 更改一个表的定义。下文描述了几种形式:
注意:如果将分区添加到具有子分区编码的表中,则新分区将继承该子分区的存储指令。
除 RENAME 和 SET SCHEMA 之外,所有作用于单个表的 ALTER TABLE 形式都可以组合成多个更改列表以一起应用。 例如,可以在单个命令中添加几列和/或更改几列的类型。 这对于大型表尤其有用,因为只需要对表进行一次遍历。
您必须拥有该表才能使用 ALTER TABLE。 要更改表的架构或表空间,您还必须对新架构或表空间具有 CREATE 特权。 要将表添加为父表的新子级,您还必须拥有父表。 要更改所有者,您还必须是新拥有角色的直接或间接成员,并且该角色必须对表的架构具有 CREATE 特权。 要添加列或更改列类型或使用 OF 子句,您还必须对数据类型具有 USAGE 特权。 超级用户自动具有这些特权。
注意:如果表具有多个分区,表具有压缩功能或表的块大小很大,则内存使用量会显着增加。 如果与该表关联的关系的数量很大,则这种情况可能会迫使对该表进行的操作使用更多的内存。 例如,如果该表是一个 CO 表并具有大量列,则每个列都是一个关系。 诸如 ALTER TABLE ALTER COLUMN 之类的操作将打开表中的所有列,以分配关联的缓冲区。 如果 CO 表具有 40 列和 100 个分区,并且这些列被压缩并且块大小为 2MB(系统系数为 3),则系统尝试分配 24 GB,即(40 × 100)×(2 × 3)MB 或 24GB。
ONLY
name
column_name
new_column_name
new_name
type
table_constraint
constraint_name
CASCADE
RESTRICT
trigger_name
ALL
USER
index_name
FILLFACTOR
value
DISTRIBUTED BY ({column_name [opclass]}) | DISTRIBUTED RANDOMLY | DISTRIBUTED REPLICATED
REORGANIZE=true|false
parent_table
new_owner
new_tablespace
new_schema
parent_table_name
ALTER [DEFAULT] PARTITION
DROP [DEFAULT] PARTITION
TRUNCATE [DEFAULT] PARTITION
RENAME [DEFAULT] PARTITION
ADD DEFAULT PARTITION
ADD PARTITION
EXCHANGE [DEFAULT] PARTITION
SET SUBPARTITION TEMPLATE
SPLIT DEFAULT PARTITION
SPLIT PARTITION
partition_name
FOR (RANK(number))
FOR ('value')
ALTER TABLE 命令中指定的表名不能是一个表中的分区名。
在修改或者删除作为 YMatrix 数据库分布键一部分的列时要特别小心,因为这可能会改变表的分布策略。.
YMatrix 数据库当前不支持外键约束。对于要在 YMatrix 数据库中实施的唯一约束,表必须被哈希分布(不能用DISTRIBUTED RANDOMLY),并且所有的分布键列必须和唯一约束列中前部的列相同。
增加 CHECK 或者 NOT NULL 约束要求扫描表以验证现有的行是否符合约束。
当使用 ADD COLUMN 添加列时,表中的所有现有行都使用该列的默认值初始化,如果未指定 DEFAULT 子句,则初始化为 NULL。添加具有非空默认值的列或更改现有列的类型将需要重写整个表和索引。作为例外,如果 USING 子句不更改列的内容,并且旧类型可以强制转换为新类型或新类型不受限制的域,则不需要重写表,但是受影响列上的任何索引都必须仍在重建中。添加或删除系统 oid 列还需要重写整个表。对于大型表,表和索引的重建可能会花费大量时间;并且暂时需要多达两倍的磁盘空间。
您可以在单个 ALTER TABLE 命令中指定多个更改,这些更改将在表上一次传递。
DROP COLUMN 表单不会物理删除列,而只是使它对 SQL 操作不可见。表中随后的插入和更新操作将为该列存储一个空值。因此,删除列很快,但是不会立即减小表的磁盘大小,因为删除的列所占用的空间不会被回收。随着现有行的更新,空间将随着时间的推移而回收。但是,如果删除系统 oid 列,则表将立即被重写。
要强制立即回收被删除的列占用的空间,您可以执行 ALTER TABLE 的一种形式来重写整个表。这将导致重建的每一行,并将删除的列替换为空值。
ALTER TABLE 的重写形式不是 MVCC 安全的。在表重写之后,如果并发事务使用的是在重写发生之前拍摄的快照,则该表将对并发事务显示为空。
SET DATA TYPE 的 USING 选项实际上可以指定涉及该行的旧值的任何表达式。也就是说,它可以引用其他列以及要转换的列。这允许使用 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, OWNER 和 TABLESPACE 操作永远不会递归到后代表。也就是说,它们始终像指定 ONLY 那样起作用。仅对未标记为 NO INHERIT 的 CHECK 约束重复添加约束。
如果包含已被交换以使用外部表的叶子分区的分区表上的数据没有更改,则支持这些 ALTER PARTITION 操作。否则,将返回错误。
分区表不支持这些 ALTER PARTITION 操作,该分区表包含已被交换以使用外部表的叶子分区:
不允许更改系统目录表的任何部分。
YMatrix 支持建表后利用 SQL 语句再次修改编码链压缩算法。
向列中添加列:
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;
修改已创建分区表的 SEGMENT_SET
对象:
## 在三节点集群中创建 SEGMENT_SET 对象 ss1,ss2
CREATE SEGMENT_SET ss1 SEGMENTS('0,2');
CREATE SEGMENT_SET ss2 SEGMENTS('1,2');
## 创建普通表 t1 和分区表 t2
CREATE TABLE t1(a int, b int) DISTRIBUTED BY(a) SEGMENT_SET ss1;
CREATE TABLE t2(a int, b int) DISTRIBUTED BY(a) PARTITION BY RANGE(b) (DEFAULT PARTITION others SEGMENT_SET ss1);
# 修改普通表 t1 的 SEGMENT_SET 对象。
ALTER TABLE t1 SET SEGMENT_SET ss2;
## 修改分区表 t2 的 SEGMENT_SET 对象,t2 所有子分区的 SEGMENT_SET 也会被修改。
ALTER TABLE t2 SET SEGMENT_SET ss2;
只修改某个分区的 SEGMENT_SET:
ALTER TABLE t2_prt_1_others SET SEGMENT_SET ss1;
ALTER TABLE t2 ALTER DEFAULT PARTITION SET SEGMENT_SET ss1;
指定新分区的 SEGMENT_SET
对象:
ALTER TABLE t2 ADD PARTITION START(6) END(10) SEGMENT_SET ss2;
将新分区添加到分区表:
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;
修改表级别压缩算法为自适应编码:
ALTER TABLE t SET (encodechain=auto);
ADD (不包含 USING INDEX),DROP,SET DEFAULT和 SET DATA TYPE (不包含 USING) 符合 SQL 标准。 其他形式是 SQL 标准的 YMatrix 数据库扩展。 同样,在单个 ALTER TABLE 命令中指定多个操纵的功能也是一种扩展。
ALTER TABLE DROP COLUMN 可用于删除表的唯一列,而保留零列表。 这是 SQL 的扩展,不允许使用零列表。