
# 扩展DDL语法
#### 前提条件
需已存在Iceberg表，例如，执行以下命令创建表：
```
CREATE TABLE prod.db.sample (id bigint, data string, category string, ts timestamp, ts_day timestamp) USING iceberg PARTITIONED BY (category);
```
#### 基本语法
在Spark中使用Iceberg SQL扩展时，可使用以下命令：
```
ALTER TABLE ... ADD PARTITION FIELD;
```
#### ALTER TABLE ADD/REPLACE/DROP PARTITION FIELD
- ADD PARTITION FIELD Iceberg支持通过**ADD PARTITION FIELD**向分区规范中添加新的分区字段：
  ```
  ALTER TABLE prod.db.sample ADD PARTITION FIELD id;
  ```
  同时支持分区转换操作：
  - 示例一：
    ```
    ALTER TABLE prod.db.sample ADD PARTITION FIELD bucket(16, id);
    ```
    
  
  - 示例二：
    ```
    ALTER TABLE prod.db.sample ADD PARTITION FIELD truncate(4, data);
    ```
    
  
  - 示例三：
    ```
    ALTER TABLE prod.db.sample ADD PARTITION FIELD year(ts);
    ```
    
  
  
  添加分区字段属于元数据操作，不会更改任何现有表数据。新数据将按照新的分区方式写入，但现有数据仍保持原有的分区布局。在元数据表中，旧数据文件的新分区字段值将为null。
  当表的分区方式发生变化时，动态分区覆盖行为也会随之改变，因为动态覆盖会隐式替换分区。
  
- DROP PARTITION FIELD 可使用**DROP PARTITION FIELD**移除分区字段。即使分区被移除，对应的列仍会保留在表的Schema 中。
  删除分区字段属于元数据操作，不会更改任何现有表数据。新数据将按照新的分区方式写入，但现有数据仍保持原有的分区布局。
  - 移除分区字段：
    - 示例一：
      ```
      ALTER TABLE prod.db.sample DROP PARTITION FIELD category;
      ```
      
    
    - 示例二：
      ```
      ALTER TABLE prod.db.sample DROP PARTITION FIELD bucket(16, id);
      ```
      
    
    - 示例三：
      ```
      ALTER TABLE prod.db.sample DROP PARTITION FIELD truncate(4, data);
      ```
      
    
    - 示例四：
      ```
      ALTER TABLE prod.db.sample DROP PARTITION FIELD year(ts);
      ```
      
     
   
- REPLACE PARTITION FIELD 通过**REPLACE PARTITION FIELD**可在单次元数据更新中，用新的分区字段ts_day替换原有分区字段year(ts)：
  - 示例一：
    ```
    ALTER TABLE prod.db.sample REPLACE PARTITION FIELD year(ts) WITH ts_day;
    ```
    
  
  - 示例二：
    ```
    ALTER TABLE prod.db.sample REPLACE PARTITION FIELD year(ts) WITH ts_day AS day_of_ts;
    ```
    
   
 
#### ALTER TABLE WRITE/LOCALLY ORDERED BY
- WRITE ORDERED BY Iceberg表可配置排序规则，部分引擎会依据该规则，在向表写入数据时自动对数据进行排序。例如，Spark中的MERGE INTO操作会使用表的排序规则。
  可使用**WRITE ORDERED BY**子句为表设置写入排序规则，示例如下：
  - 示例一：
    ```
    ALTER TABLE prod.db.sample WRITE ORDERED BY category, id;
    ```
    
  
  - 示例二：
    ```
    ALTER TABLE prod.db.sample WRITE ORDERED BY category ASC, id DESC;
    ```
    
  
  - 示例三：
    ```
    ALTER TABLE prod.db.sample WRITE ORDERED BY category ASC NULLS LAST, id DESC NULLS FIRST;
    ```
    
  
  
  **WRITE ORDERED BY** 用于设置全局排序规则，会对跨任务的行进行排序，类似于在INSERT命令中使用ORDER BY，例如：
  ```
  INSERT INTO prod.db.sample SELECT id, data, category, ts FROM {其他表} ORDER BY ts, category;
  ```
  若只需在每个任务内排序（而非跨任务排序），可使用**LOCALLY ORDERED BY**：
  ```
  ALTER TABLE prod.db.sample WRITE LOCALLY ORDERED BY category, id;
  ```
  可使用**UNORDERED**取消表的排序顺序：
  ```
  ALTER TABLE prod.db.sample WRITE UNORDERED;
  ```
  
- WRITE DISTRIBUTED BY PARTITION **WRITE DISTRIBUTED BY PARTITION**用于指定每个分区由单个写入器（writer）处理，其默认实现方式为哈希分布。
  ```
  ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION;
  ```
  **DISTRIBUTED BY PARTITION** 可与**LOCALLY ORDERED BY**结合使用，实现按分区分布数据，同时在每个任务内对行进行本地排序：
  ```
  ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION LOCALLY ORDERED BY category, id;
  ```
  
 
#### ALTER TABLE SET/DROP IDENTIFIER FIELDS（MRS 3.6.0-LTS及之后版本）
执行以下命令在prod数据库的db模式中创建一个名为sample的Iceberg表，并按category列进行分区：
```
CREATE TABLE prod.db.sample (id bigint NOT NULL, data string NOT NULL, category string, ts timestamp, ts_day timestamp) USING iceberg PARTITIONED BY (category);
```
- SET IDENTIFIER FIELDS Iceberg支持通过**SET IDENTIFIER FIELDS**为表规范设置标识字段。如果Spark表配置了标识字段，该表可支持Flink SQL的更新插入（upsert）操作。
  Iceberg不支持直接通过**ALTER COLUMN id SET NOT NULL**将现有可空字段改成非空字段。
  - 示例一，需确保字段无空值：
    ```
    ALTER TABLE prod.db.sample SET IDENTIFIER FIELDS id;
    ```
    
  
  - 示例二：
    ```
    ALTER TABLE prod.db.sample SET IDENTIFIER FIELDS id, data;
    ```
    
  
  
  标识字段在创建或添加时，必须是非空列(NOT NULL)。后续执行的**ALTER TABLE ... SET IDENTIFIER FIELDS**语句会覆盖之前的标识字段设置。
  
- DROP IDENTIFIER FIELDS 可使用**DROP IDENTIFIER FIELDS**移除标识字段，且即使标识字段被移除，对应的列仍会保留在表的Schema中。
  - 示例一，需确保字段无空值：
    ```
    ALTER TABLE prod.db.sample DROP IDENTIFIER FIELDS id;
    ```
    
  
  - 示例二：
    ```
    ALTER TABLE prod.db.sample DROP IDENTIFIER FIELDS id, data;
    ```
    
   
 
