可以使用
ALTER TABLE
修改表的定义,以响应不断变化的数据库架构要求。更改表定义通常比在临时表中暂存数据更有效,它消耗的资源和存储空间更少。
另请参阅
-
对于列级别更改,请参阅管理表列。
-
有关更改和重新组织表分区的详细信息,请参阅对现有表数据进行分区。
可以使用
ALTER TABLE
修改表的定义,以响应不断变化的数据库架构要求。更改表定义通常比在临时表中暂存数据更有效,它消耗的资源和存储空间更少。
对于列级别更改,请参阅管理表列。
有关更改和重新组织表分区的详细信息,请参阅对现有表数据进行分区。
可以使用 ALTER TABLE..ADD COLUMN 将列添加到持久表:
ALTER TABLE
...
ADD COLUMN [IF NOT EXISTS] column datatype
[column‑constraint]
[ENCODING encoding‑type]
[PROJECTIONS (projections‑list) | ALL PROJECTIONS ]
当使用 ADD COLUMN 更改表时,Vertica 会对该表采用 O 锁,直到操作完成。该锁可防止 DELETE、UPDATE、INSERT 和 COPY 语句访问表。该锁还会阻止在 SERIALIZABLE 隔离级别发出的 SELECT 语句,直到操作完成。
您可以在节点下线时添加列。
向表添加列时,Vertica 会自动将该列添加到该表的 超投影。ADD..COLUMN 子句还可以使用以下选项之一指定将列添加到一个或多个非超投影:
PROJECTIONS (projections-list
):将新列添加到该表的一个或多个投影,以投影基本名称的逗号分隔列表形式指定。Vertica 会将该列添加到每个投影的所有伙伴实例。投影列表不能包含具有预聚合数据的投影,例如实时聚合投影;否则,Vertica 会回退 ALTER TABLE 语句。
ALL PROJECTIONS
会将列添加到该表的所有投影,不包括具有预聚合数据的投影。
例如,store_orders
表有两个投影:超投影 store_orders_super
和用户创建的投影 store_orders_p
。以下 ALTER TABLE..ADD COLUMN 语句将列 expected_ship_date
添加到 store_orders
表。由于该语句省略了 PROJECTIONS
选项,因此 Vertica 仅将该列添加到表的超投影:
=> ALTER TABLE public.store_orders ADD COLUMN expected_ship_date date;
ALTER TABLE
=> SELECT projection_column_name, projection_name FROM projection_columns WHERE table_name ILIKE 'store_orders'
ORDER BY projection_name , projection_column_name;
projection_column_name | projection_name
------------------------+--------------------
order_date | store_orders_p_b0
order_no | store_orders_p_b0
ship_date | store_orders_p_b0
order_date | store_orders_p_b1
order_no | store_orders_p_b1
ship_date | store_orders_p_b1
expected_ship_date | store_orders_super
order_date | store_orders_super
order_no | store_orders_super
ship_date | store_orders_super
shipper | store_orders_super
(11 rows)
以下 ALTER TABLE...ADD COLUMN 语句包括 PROJECTIONS 选项。这指定在添加操作中包含投影 store_orders_p
。Vertica 将新列添加到此投影和表的超投影:
=> ALTER TABLE public.store_orders ADD COLUMN delivery_date date PROJECTIONS (store_orders_p);
=> SELECT projection_column_name, projection_name FROM projection_columns WHERE table_name ILIKE 'store_orders'
ORDER BY projection_name, projection_column_name;
projection_column_name | projection_name
------------------------+--------------------
delivery_date | store_orders_p_b0
order_date | store_orders_p_b0
order_no | store_orders_p_b0
ship_date | store_orders_p_b0
delivery_date | store_orders_p_b1
order_date | store_orders_p_b1
order_no | store_orders_p_b1
ship_date | store_orders_p_b1
delivery_date | store_orders_super
expected_ship_date | store_orders_super
order_date | store_orders_super
order_no | store_orders_super
ship_date | store_orders_super
shipper | store_orders_super
(14 rows)
将新列添加到具有关联视图的表时,系统不会更新视图的结果集,即便该视图使用了通配符 (*) 来表示所有表列。要整合新列,您必须重新创建视图。
ALTER TABLE...DROP COLUMN 会删除指定的表列以及与已删除的列对应的 ROS 容器:
ALTER TABLE [schema.]table DROP [ COLUMN ] [IF EXISTS] column [CASCADE | RESTRICT]
删除操作完成后,将恢复自当前时期起备份的数据,但不包含列。从当前时期之前的备份恢复的数据将重新添加表列。由于删除操作会从表中物理清除对象存储和编录定义(表历史记录),AT EPOCH(历史)查询对于已删除的列不返回任何内容。
更改的表保留其对象 ID。
不能删除或更改主键列或参与表分区子句的列。
不能删除任何投影排序顺序中的第一列,或参与投影分段表达式的列。
在企业模式下,所有节点必须都处于启动状态。此限制不适用于 Eon 模式。
不能删除与访问策略关联的列。尝试删除可能会导致以下错误:ERROR 6482: Failed to parse Access Policies for table "t1"
如果要删除的表列具有依赖项,则必须使用 CASCADE 选项来限定 DROP COLUMN 子句。例如,目标列可能会按投影排序顺序进行指定。在这种情况和其他情况下,DROP COLUMN...CASCADE 将通过重组编录定义或删除投影来处理依赖项。在所有情况下,CASCADE 将执行删除列所需的最低水平的重组。
使用 CASCADE 删除具有以下依赖项的列:
您可能要删除被另一列作为其默认值引用的表列。例如,下表定义为具有两个列 a
和 b
,其中 b
将从列 a
获取其默认值。
=> CREATE TABLE x (a int) UNSEGMENTED ALL NODES;
CREATE TABLE
=> ALTER TABLE x ADD COLUMN b int DEFAULT a;
ALTER TABLE
这种情况下,删除列 a
需要执行以下过程:
通过 ALTER COLUMN..DROP DEFAULT 移除默认依赖项:
=> ALTER TABLE x ALTER COLUMN b DROP DEFAULT;
如果以下条件中的一条或两条为 true,则为目标表创建替换超投影:
目标列为表的第一个排序顺序列。如果表没有显式排序顺序,则默认表排序顺序将第一个表列指定为第一个排序顺序列。在这种情况下,新的超投影必须指定排除目标列的排序顺序。
如果将表分段,则在分段表达式中指定目标列。在这种情况下,新的超投影必须指定排除目标列的分段表达式。
假定上一个示例中表 x
具有默认排序顺序 (a,b)。由于列 a
为该表的第一个排序顺序列,因此必须创建对列 b
进行排序的替换超投影:
=> CREATE PROJECTION x_p1 as select * FROM x ORDER BY b UNSEGMENTED ALL NODES;
运行
START_REFRESH
:
=> SELECT START_REFRESH();
START_REFRESH
----------------------------------------
Starting refresh background process.
(1 row)
运行 MAKE_AHM_NOW:
=> SELECT MAKE_AHM_NOW();
MAKE_AHM_NOW
-------------------------------
AHM set (New AHM Epoch: 1231)
(1 row)
删除列:
=> ALTER TABLE x DROP COLUMN a CASCADE;
Vertica 将实施 CASCADE 指令,如下所示:
删除表 x
的原始超投影 (x_super
)。
通过删除列 a
更新替换超投影 x_p1
。
下面的一系列命令成功删除了 BYTEA 数据类型列:
=> CREATE TABLE t (x BYTEA(65000), y BYTEA, z BYTEA(1));
CREATE TABLE
=> ALTER TABLE t DROP COLUMN y;
ALTER TABLE
=> SELECT y FROM t;
ERROR 2624: Column "y" does not exist
=> ALTER TABLE t DROP COLUMN x RESTRICT;
ALTER TABLE
=> SELECT x FROM t;
ERROR 2624: Column "x" does not exist
=> SELECT * FROM t;
z
---
(0 rows)
=> DROP TABLE t CASCADE;
DROP TABLE
下面的一系列命令尝试删除 FLOAT(8) 列,但失败,因为没有足够的投影来维持 K-safety。
=> CREATE TABLE t (x FLOAT(8),y FLOAT(08));
CREATE TABLE
=> ALTER TABLE t DROP COLUMN y RESTRICT;
ALTER TABLE
=> SELECT y FROM t;
ERROR 2624: Column "y" does not exist
=> ALTER TABLE t DROP x CASCADE;
ROLLBACK 2409: Cannot drop any more columns in t
=> DROP TABLE t CASCADE;
ALTER TABLE...ALTER CONSTRAINT
可以启用或禁用主键、唯一和检查约束的强制实施。必须使用关键字 ENABLED
或 DISABLED
来限定此子句:
ENABLED
强制实施指定的约束。
DISABLED
禁用指定约束的强制实施。
例如:
ALTER TABLE public.new_sales ALTER CONSTRAINT C_PRIMARY ENABLED;
有关详细信息,请参阅约束强制执行。
ALTER TABLE...RENAME TO
重命名一个或多个表。重命名的表保留其原始 OID。
可以通过提供两个逗号分隔的列表来重命名多个表。Vertica 根据两个列表中的顺序映射这些名称。只有第一个列表可以使用架构限定表名。例如:
=> ALTER TABLE S1.T1, S1.T2 RENAME TO U1, U2;
RENAME TO
参数将以原子方式应用:重命名所有表,或不重命名任何表。例如,如果要重命名的表数量与新名称数量不匹配,则所有表都不会被重命名。
可以使用 ALTER TABLE...RENAME TO
在同一架构内交换表,而无需实际移动数据。不能跨架构交换表。
以下示例通过中间表 temp
交换表 T1
和 T2
中的数据:
t1
到 temp
t2
到 t1
temp
到 t2
=> DROP TABLE IF EXISTS temp, t1, t2;
DROP TABLE
=> CREATE TABLE t1 (original_name varchar(24));
CREATE TABLE
=> CREATE TABLE t2 (original_name varchar(24));
CREATE TABLE
=> INSERT INTO t1 VALUES ('original name t1');
OUTPUT
--------
1
(1 row)
=> INSERT INTO t2 VALUES ('original name t2');
OUTPUT
--------
1
(1 row)
=> COMMIT;
COMMIT
=> ALTER TABLE t1, t2, temp RENAME TO temp, t1, t2;
ALTER TABLE
=> SELECT * FROM t1, t2;
original_name | original_name
------------------+------------------
original name t2 | original name t1
(1 row)
ALTER TABLE...SET SCHEMA
可以将表从一个架构移动到另一个架构。Vertica 会自动将锚定到源表的所有投影移动到目标架构。它还会将所有 IDENTITY
和 AUTO_INCREMENT
列移动到目标架构。
在架构之间移动表需要对当前架构具有 USAGE
权限,并对目标架构具有 CREATE
权限。一次只能在架构之间移动一个表。不能在架构之间移动临时表。
如果新架构中已经存在要移动的同名表或任何投影,该语句将回退并且不会移动该表或任何投影。要解决名称冲突:
重命名要移动的任何冲突表或投影。
再次运行
ALTER TABLE...SET SCHEMA
。
以下示例将表 T1
从架构 S1
移至架构 S2
。锚定到表 T1
的所有投影都会自动移至架构 S2
:
=> ALTER TABLE S1.T1 SET SCHEMA S2;
作为超级用户或表所有者,可以使用
ALTER TABLE...OWNER TO
重新分配表所有权,如下所示:
ALTER TABLE [schema.]table-name OWNER TO owner-name
将表从一个架构移动到另一个架构时,更改表所有权很有用。当表所有者离职或更换工作职责时,所有权重新分配也很有用。由于可以更改表所有者,因此表无需完全重写,进而可以避免生产率下降。
更改表所有权会自动导致以下更改:
由原始所有者对表进行的授权将被删除,对该表的所有现有权限都将从前一个所有者那里撤销。表所有权的更改对架构权限没有影响。
从属 IDENTITY/AUTO-INCREMENT
序列的所有权随表一起转移。但是,对于使用
CREATE SEQUENCE
创建的指定序列,所有权不会更改。要转移这些序列的所有权,请使用
ALTER SEQUENCE
。
新的表所有权会传播到其投影。
在以下示例中,用户 Bob 连接到数据库,查找表,然后将表 t33
的所有权从自己转移到用户 Alice。
=> \c - Bob
You are now connected as user "Bob".
=> \d
Schema | Name | Kind | Owner | Comment
--------+--------+-------+---------+---------
public | applog | table | dbadmin |
public | t33 | table | Bob |
(2 rows)
=> ALTER TABLE t33 OWNER TO Alice;
ALTER TABLE
当 Bob 再次查找数据库表时,他不再看到表 t33
:
=> \d List of tables
List of tables
Schema | Name | Kind | Owner | Comment
--------+--------+-------+---------+---------
public | applog | table | dbadmin |
(1 row)
当用户 Alice 连接到数据库并查找表时,她将看到她是表 t33
的所有者。
=> \c - Alice
You are now connected as user "Alice".
=> \d
List of tables
Schema | Name | Kind | Owner | Comment
--------+------+-------+-------+---------
public | t33 | table | Alice |
(2 rows)
Alice 或超级用户可以将表所有权转移回 Bob。在以下情况下,超级用户执行转移操作。
=> \c - dbadmin
You are now connected as user "dbadmin".
=> ALTER TABLE t33 OWNER TO Bob;
ALTER TABLE
=> \d
List of tables
Schema | Name | Kind | Owner | Comment
--------+----------+-------+---------+---------
public | applog | table | dbadmin |
public | comments | table | dbadmin |
public | t33 | table | Bob |
s1 | t1 | table | User1 |
(4 rows)
也可以查询系统表
V_CATALOG.TABLES
以查看表和所有者信息。注意,所有权更改不会更改表 ID。
在下面的一系列命令中,超级用户将表所有权更改回 Alice,并查询系统表 TABLES
。
=> ALTER TABLE t33 OWNER TO Alice;
ALTER TABLE
=> SELECT table_schema_id, table_schema, table_id, table_name, owner_id, owner_name FROM tables;
table_schema_id | table_schema | table_id | table_name | owner_id | owner_name
-------------------+--------------+-------------------+------------+-------------------+------------
45035996273704968 | public | 45035996273713634 | applog | 45035996273704962 | dbadmin
45035996273704968 | public | 45035996273724496 | comments | 45035996273704962 | dbadmin
45035996273730528 | s1 | 45035996273730548 | t1 | 45035996273730516 | User1
45035996273704968 | public | 45035996273795846 | t33 | 45035996273724576 | Alice
(5 rows)
现在,超级用户将表所有权更改回 Bob,并再次查询 TABLES
表。除了 owner_name
行从 Alice 更改为 Bob,没有其他改变。
=> ALTER TABLE t33 OWNER TO Bob;
ALTER TABLE
=> SELECT table_schema_id, table_schema, table_id, table_name, owner_id, owner_name FROM tables;
table_schema_id | table_schema | table_id | table_name | owner_id | owner_name
-------------------+--------------+-------------------+------------+-------------------+------------
45035996273704968 | public | 45035996273713634 | applog | 45035996273704962 | dbadmin
45035996273704968 | public | 45035996273724496 | comments | 45035996273704962 | dbadmin
45035996273730528 | s1 | 45035996273730548 | t1 | 45035996273730516 | User1
45035996273704968 | public | 45035996273793876 | foo | 45035996273724576 | Alice
45035996273704968 | public | 45035996273795846 | t33 | 45035996273714428 | Bob
(5 rows)