这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

更改表定义

可以使用 ALTER TABLE 修改表的定义,以响应不断变化的数据库架构要求。更改表定义通常比在临时表中暂存数据更有效,它消耗的资源和存储空间更少。

另请参阅

1 - 添加表列

可以使用 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 语句,直到操作完成。

向表添加列并不会影响 物理架构设计的 K-safety

您可以在节点下线时添加列。

向投影添加新列

向表添加列时,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)

更新关联的表视图

将新列添加到具有关联视图的表时,系统不会更新视图的结果集,即便该视图使用了通配符 (*) 来表示所有表列。要整合新列,您必须重新创建视图

2 - 删除表列

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 强制删除

如果要删除的表列具有依赖项,则必须使用 CASCADE 选项来限定 DROP COLUMN 子句。例如,目标列可能会按投影排序顺序进行指定。在这种情况和其他情况下,DROP COLUMN...CASCADE 将通过重组编录定义或删除投影来处理依赖项。在所有情况下,CASCADE 将执行删除列所需的最低水平的重组。

使用 CASCADE 删除具有以下依赖项的列:

删除作为默认值引用的列

您可能要删除被另一列作为其默认值引用的表列。例如,下表定义为具有两个列 ab,其中 b 将从列 a 获取其默认值。

=> CREATE TABLE x (a int) UNSEGMENTED ALL NODES;
CREATE TABLE
=> ALTER TABLE x ADD COLUMN b int DEFAULT a;
ALTER TABLE

这种情况下,删除列 a 需要执行以下过程:

  1. 通过 ALTER COLUMN..DROP DEFAULT 移除默认依赖项:

    => ALTER TABLE x ALTER COLUMN b DROP DEFAULT;
    
  2. 如果以下条件中的一条或两条为 true,则为目标表创建替换超投影:

    • 目标列为表的第一个排序顺序列。如果表没有显式排序顺序,则默认表排序顺序将第一个表列指定为第一个排序顺序列。在这种情况下,新的超投影必须指定排除目标列的排序顺序。

    • 如果将表分段,则在分段表达式中指定目标列。在这种情况下,新的超投影必须指定排除目标列的分段表达式。

    假定上一个示例中表 x 具有默认排序顺序 (a,b)。由于列 a 为该表的第一个排序顺序列,因此必须创建对列 b 进行排序的替换超投影:

    => CREATE PROJECTION x_p1 as select * FROM x ORDER BY b UNSEGMENTED ALL NODES;
    
  3. 运行 START_REFRESH

    
    => SELECT START_REFRESH();
                  START_REFRESH
    ----------------------------------------
     Starting refresh background process.
    
    (1 row)
    
  4. 运行 MAKE_AHM_NOW

    => SELECT MAKE_AHM_NOW();
             MAKE_AHM_NOW
    -------------------------------
     AHM set (New AHM Epoch: 1231)
    (1 row)
    
  5. 删除列:

    => 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;

3 - 更改约束强制实施

ALTER TABLE...ALTER CONSTRAINT 可以启用或禁用主键唯一检查约束的强制实施。必须使用关键字 ENABLEDDISABLED 来限定此子句:

  • ENABLED 强制实施指定的约束。

  • DISABLED 禁用指定约束的强制实施。

例如:

ALTER TABLE public.new_sales ALTER CONSTRAINT C_PRIMARY ENABLED;

有关详细信息,请参阅约束强制执行

4 - 重命名表

ALTER TABLE...RENAME TO 重命名一个或多个表。重命名的表保留其原始 OID。

可以通过提供两个逗号分隔的列表来重命名多个表。Vertica 根据两个列表中的顺序映射这些名称。只有第一个列表可以使用架构限定表名。例如:

=> ALTER TABLE S1.T1, S1.T2 RENAME TO U1, U2;

RENAME TO 参数将以原子方式应用:重命名所有表,或不重命名任何表。例如,如果要重命名的表数量与新名称数量不匹配,则所有表都不会被重命名。

使用重命名在架构内交换表

可以使用 ALTER TABLE...RENAME TO 在同一架构内交换表,而无需实际移动数据。不能跨架构交换表。

以下示例通过中间表 temp 交换表 T1T2 中的数据:

  1. t1temp

  2. t2t1

  3. tempt2

=> 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)

5 - 将表移动到另一个架构

ALTER TABLE...SET SCHEMA 可以将表从一个架构移动到另一个架构。Vertica 会自动将锚定到源表的所有投影移动到目标架构。它还会将所有 IDENTITYAUTO_INCREMENT 列移动到目标架构。

在架构之间移动表需要对当前架构具有 USAGE 权限,并对目标架构具有 CREATE 权限。一次只能在架构之间移动一个表。不能在架构之间移动临时表。

名称冲突

如果新架构中已经存在要移动的同名表或任何投影,该语句将回退并且不会移动该表或任何投影。要解决名称冲突:

  1. 重命名要移动的任何冲突表或投影。

  2. 再次运行 ALTER TABLE...SET SCHEMA

示例

以下示例将表 T1 从架构 S1 移至架构 S2。锚定到表 T1 的所有投影都会自动移至架构 S2

=> ALTER TABLE S1.T1 SET SCHEMA S2;

6 - 更改表所有权

作为超级用户或表所有者,可以使用 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)