

 Amazon Redshift は、パッチ 198 以降、新しい Python UDF の作成をサポートしなくなります。既存の Python UDF は、2026 年 6 月 30 日まで引き続き機能します。詳細については、[ブログ記事](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)を参照してください。

# SQL コマンド
<a name="iceberg-writes-sql-syntax"></a>

Amazon Redshift の Apache Iceberg テーブルは、データレイク内の大規模な分析データセットを管理する強力な方法を提供します。これらのテーブルは、分析ワークロードのハイパフォーマンスを維持しながら、ACID トランザクション、スキーマの進化、タイムトラベル機能をサポートします。Apache Iceberg テーブルを使用すると、データを効率的に整理してパーティション化し、ファイル形式と圧縮を制御し、他の AWS サービスとシームレスに統合できます。

`CREATE TABLE ... USING ICEBERG` および `CREATE TABLE ... USING ICEBERG AS SELECT` コマンドを使用して、パーティション分割された Iceberg テーブルとパーティション分割されていない Iceberg テーブルを作成できます。Iceberg テーブルは、外部スキーマ表記 (`external_schema.table_name`) または 3 つの部分からなる表記 (`"catalog_name".database_name.table_name`) を使用して参照できます。このセクションの例は、両方の方法を示しています。

テーブルを作成したら、標準 `INSERT` コマンドを使用してデータを追加できます。Amazon Redshift は多くの Iceberg データ型で動作しますが、情報を挿入するときに一部のデータ形式を変換する必要がある場合があります。

`SHOW TABLES` コマンドを使用して Iceberg テーブルを表示できます。AWS Glue Data Catalog からテーブルを削除する場合は、`DROP TABLE` コマンドを使用できます。これにより、テーブル登録のみが削除されます。実際のデータは、別個に削除するまでストレージに保持されます。

既存のデータは、`DELETE`、`UPDATE`、および `MERGE` コマンドを使用して変更することもできます。他のすべての SQL ステートメント (`ALTER TABLE`) については、Iceberg テーブルでまだサポートされていません。

Amazon Redshift で作成されていない Iceberg テーブルへの書き込みはできます。ただし、いくつかの制限があります。
+ テーブルは Iceberg v2 テーブルである必要があります。
+ テーブルは、デフォルトのデータ形式として Parquet を使用している必要があります。
+ テーブルでメタデータ圧縮が True に設定されていないことが必要です。
+ テーブルで Write-Audit-Publish (WAP) が有効にされていないことが必要です。

以下のセクションでは、Amazon Redshift で Iceberg テーブルを作成、挿入、変更、管理するための SQL 構文を示します。

**Contents**
+ [CREATE TABLE](#iceberg-writes-create-table)
+ [CREATE TABLE AS SELECT](#iceberg-writes-create-table-as-select)
+ [テーブルを表示する](#iceberg-writes-show-table)
+ [INSERT INTO](#iceberg-writes-insert-into)
+ [DELETE](#iceberg-writes-delete)
+ [UPDATE](#iceberg-writes-update)
+ [MERGE](#iceberg-writes-merge)
+ [DROP TABLE](#iceberg-writes-drop-table)

## CREATE TABLE
<a name="iceberg-writes-create-table"></a>

```
CREATE TABLE [IF NOT EXISTS] {{<external_schema>}}.{{<table_name>}} (
  column_name data_type [, ...]
)
USING ICEBERG
[LOCATION 's3://{{your-bucket-name}}/prefix/']
[PARTITIONED BY [[column_name | transform_function]], ...]
[TABLE PROPERTIES ('compression_type'='<compression_value>')]
```

S3 テーブルバケットには 3 つの部分からなる表記を使用することもできます。

```
CREATE TABLE "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}} (
  column_name data_type [, ...]
)
USING ICEBERG
[PARTITIONED BY [[column_name | transform_function]], ...]
[TABLE PROPERTIES ('compression_type'='<compression_value>')]
```

`{{<external_schema>}}` は、外部テーブルを作成する既存の外部スキーマ名である必要があります。外部スキーマを作成および管理する方法の詳細については、Amazon Redshift ドキュメントの「[CREATE EXTERNAL SCHEMA](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_EXTERNAL_SCHEMA.html)」を参照してください。

`LOCATION` 句は、新しく作成された Iceberg テーブルのテーブルの場所を定義します。Amazon S3 Tables の場合、テーブルの場所は Amazon S3 Tables カタログ (`s3tablescatalog`) によって決定されるため、`LOCATION` を指定することはできません。

それ以外の場合、`LOCATION` は必須であり、空の場所である必要があります。つまり、この同じバケットとプレフィックスを共有する既存の Amazon S3 オブジェクトはありません。Amazon S3 バケットは、Amazon Redshift クラスターと同じリージョンに存在する必要があります。

ただし、AWS には、AWS Glue Data Catalog に保存されている Iceberg テーブルからデータをある AWS リージョンから別の AWS リージョンにレプリケートする方法が用意されているため、書き込みを別のリージョンにレプリケートできます。詳細については、「[AWS リージョン間でデータをレプリケートする](https://docs.aws.amazon.com/prescriptive-guidance/latest/apache-iceberg-on-aws/best-practices-workloads.html#workloads-replication)」を参照してください。

`PARTITIONED BY` は Iceberg テーブルパーティションを定義します。Amazon Redshift は、`void` を除くすべての Iceberg v2 パーティション変換をサポートしています。サポートされている変換のリストを次に示します。
+ **identity**
+ **bucket[N]**
+ **truncate[W]**
+ **year**
+ **month**
+ **day**
+ **hour**

これらの変換の詳しい定義および互換性のあるデータ型については、Apache Iceberg ドキュメントの「[パーティション変換](https://iceberg.apache.org/spec/#partition-transforms)」を参照してください。

`PARTITIONED BY` は、マルチレベルパーティショニングをサポートしています。例えば、次のコマンドを実行できます。

```
CREATE TABLE ...
USING ICEBERG
LOCATION ...
PARTITIONED BY (bucket(16, id), year(ship_date));
```

ただし、Amazon Redshift は複数の変換で 1 つの列を使用することをサポートしていません。例えば、次の構文はサポートされていません。

```
CREATE TABLE ...
USING ICEBERG
LOCATION ...
PARTITIONED BY (bucket(16, ship_date), year(ship_date));
```

`TABLE PROPERTIES` 句は、この Iceberg テーブルの追加のテーブルプロパティを定義します。サポートされる唯一のテーブルプロパティは、デフォルトの Parquet データファイル圧縮を定義する `compression_type` です。これを指定しない場合、`snappy` は圧縮コーデックとして使用されます。`compression_type` の想定される値は、`zstd`、`brotli`、`gzip`、`snappy`、`uncompressed` です。

**注記**  
`CREATE TABLE ... LIKE ...` は Iceberg テーブルではサポートされていません。Iceberg テーブルは、RMS テーブルにあるような列の制約や列属性もサポートしていません。

または、`CREATE TABLE AS SELECT` を使用して 1 回の操作で Iceberg テーブルを作成して入力することもできます。

## CREATE TABLE AS SELECT
<a name="iceberg-writes-create-table-as-select"></a>

```
CREATE TABLE {{<external_schema>}}.{{<table_name>}} [(
  column_name[, ...]
)]
USING ICEBERG
[LOCATION 's3://{{your-bucket-name}}/prefix/']
[PARTITIONED BY [[column_name | transform_function]], ...]
[TABLE PROPERTIES ('compression_type'='{{<compression-value>}}')]
AS
SELECT query
```

3 つの部分からなる表記を使用して、自動マウントカタログにテーブルを作成することもできます。

```
CREATE TABLE "{{<catalog_name>}}".{{<database_name>}}.{{<table_name>}} [(
  column_name[, ...]
)]
USING ICEBERG
[LOCATION 's3://{{your-bucket-name}}/prefix/']
[PARTITIONED BY [[column_name | transform_function]], ...]
[TABLE PROPERTIES ('compression_type'='{{<compression-value>}}')]
AS
SELECT query
```

これは、`CREATE` の後に `SELECT` ステートメントが `SELECT` クエリ結果をテーブルに入力することを除いて、`CREATE TABLE` ステートメントに似ています。

ここでの `CREATE TABLE` 句では、列のデータ型が `SELECT` クエリによって決定されるため、データ型を指定できなくなりました。

何らかの理由で `SELECT` クエリが失敗した場合、このクエリは失敗し、Iceberg テーブルは作成されません。

`SHOW TABLE` を使用して Iceberg テーブルの構造を表示できます。

## テーブルを表示する
<a name="iceberg-writes-show-table"></a>

```
SHOW TABLE {{<external_schema>}}.{{<table_name>}}
```

自動マウントカタログでは、3 つの部分からなる表記を使用することもできます。

```
SHOW TABLE "{{<catalog_name>}}".{{<database_name>}}.{{<table_name>}}
```

`SHOW TABLE` は Iceberg テーブルの `CREATE TABLE` ステートメントを表示します。コマンドは、テーブルのタイプに基づいて適切な結果を表示します。以下は、Iceberg テーブルの `SHOW TABLE` 出力の例です。

```
CREATE TABLE my_schema.items (id int, price decimal(5, 2))
USING ICEBERG
LOCATION 's3://my_s3_bucket/items/'
PARTITIONED BY (bucket(16, id))
TABLE PROPERTIES ('compression_type'='snappy')
```

**注記**  
Amazon S3 テーブルの場合、テーブルの場所は Amazon S3 テーブルカタログによって管理されるため、`LOCATION` 句は `SHOW TABLE` の結果では省略されます。

テーブルを作成したら、`INSERT INTO` を使用してデータを追加できます。

## INSERT INTO
<a name="iceberg-writes-insert-into"></a>

```
INSERT INTO {{<external_schema>}}.{{<table_name>}} [(column_name [, ...])] VALUES (...)
INSERT INTO {{<external_schema>}}.{{<table_name>}} [(column_name [, ...])] (SELECT query)

-- Using three-part notation for S3 table buckets:
INSERT INTO "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}} [(column_name [, ...])] VALUES (...)
INSERT INTO "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}} [(column_name [, ...])] (SELECT query)
```

上記の構文を使用して、既存の Iceberg テーブルに挿入 (`INSERT INTO`) できます。`VALUES` 句を使用する場合で、`column_name` 部が省略されている場合、`column_name` またはすべての列でリストされている列の値を指定します。

データがパーティション分割されたテーブルに挿入されると、事前定義されたパーティション仕様に従って新しい行が分散されます。何らかの理由で `SELECT` クエリが失敗した場合、クエリは失敗し、データは Iceberg テーブルに挿入されません。

## DELETE
<a name="iceberg-writes-delete"></a>

Iceberg テーブルの `DELETE` クエリは、RMS テーブル内の既存の `DELETE` 構文を使用します。

```
[ WITH [RECURSIVE] {{common_table_expression}} [, {{common_table_expression}} , ...] ]
DELETE [ FROM ] {{iceberg_table}}
[ { USING } {{table_name, ...}} ] [ WHERE {{condition}} ]
```

S3 テーブルバケットには 3 つの部分からなる表記を使用することもできます。

```
[ WITH [RECURSIVE] {{common_table_expression}} [, {{common_table_expression}} , ...] ]
DELETE [ FROM ] "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}}
[ { USING } {{table_name, ...}} ] [ WHERE {{condition}} ]
```

`{{<external_schema>}}.{{<external_table_name>}}` は、`{{iceberg_table}}` フォームを使用して参照することも、自動マウントカタログの 3 つの部分からなる表記を使用することもできます。「[Amazon Redshift での Iceberg テーブルの参照](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)」を参照してください。

`USING` 句の `{{table_name}}` は、`WHERE` 条件を満たす行を削除するために、ターゲットテーブルとの結合に使用されます。`{{table_name}}` は、Iceberg テーブルまたは Amazon Redshift RMS テーブルにすることができます。

Iceberg は隠しパーティションスキームを使用するため、ユーザーは `DELETE` クエリを使用してパーティションを削除できます。これにより、Hive テーブルの `ALTER TABLE ... DROP PARTITION ...` と同じ効果が得られます。

例えば、次のようなパーティション分割された Iceberg テーブルがあるとします。

```
CREATE TABLE my_external_schema.lineitem
(l_item_id int,
 l_ship_date varchar,
 ...
)
USING ICEBERG
LOCATION ...
PARTITIONED BY l_ship_date;
```

この場合、次のようなクエリを使用してパーティションを簡単に削除できます。

```
DELETE FROM my_external_schema.lineitem WHERE l_ship_date = '20251231';
```

このようなクエリの場合、Amazon Redshift はメタデータのみのオペレーションだけを行うように実行を最適化し、実行をショートサーキットします。したがって、通常の `DELETE` クエリとは異なり、メタデータのみの削除クエリでは `EXPLAIN` の実行ステップが表示されません。

```
explain DELETE FROM my_external_schema.lineitem WHERE l_ship_date = '20251231';

 QUERY PLAN
------------
"XN Seq Scan Metadata of my_external_schema.lineitem location: "s3://s3-path//table-location" format:ICEBERG (cost=0.00..0.01 rows=0 width=0)"
(0 rows)
```

## UPDATE
<a name="iceberg-writes-update"></a>

Iceberg テーブルの `UPDATE` クエリ構文は、RMS テーブルの既存の `UPDATE` 構文と非常によく似ています。

```
[ WITH [RECURSIVE] {{common_table_expression}} [, {{common_table_expression}} , ...] ]
UPDATE {{iceberg_table}} [ [ AS ] alias ] SET column = { {{expression}} } [,...]
[ FROM {{fromlist}} ]
[ WHERE {{condition}} ]
```

S3 テーブルバケットには 3 つの部分からなる表記を使用することもできます。

```
[ WITH [RECURSIVE] {{common_table_expression}} [, {{common_table_expression}} , ...] ]
UPDATE "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}} [ [ AS ] alias ] SET column = { {{expression}} } [,...]
[ FROM {{fromlist}} ]
[ WHERE {{condition}} ]
```

`{{<external_schema>}}.{{<external_table_name>}}` は、`{{iceberg_table}}` フォームを使用して参照することも、自動マウントカタログの 3 つの部分からなる表記を使用することもできます。「[Amazon Redshift での Iceberg テーブルの参照](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)」を参照してください。

他のテーブルの情報を参照することで、テーブルを更新できます。FROM 句の他のテーブルを一覧表示するか、WHERE 条件の一部としてサブクエリを使用します。ソーステーブルは Iceberg テーブルまたは Amazon Redshift RMS テーブルのいずれかです。

`UPDATE` はパーティション分割されたテーブルでも実行できます。現在のパーティション仕様に属する列の値を `UPDATE` で変更すると、更新された新しい値に基づいて、更新後の新しい行が新しいパーティションに挿入されます。

例えば、次のようなパーティション分割された Iceberg テーブルがあるとします。

```
CREATE TABLE my_external_schema.lineitem
(l_item_id int,
 l_ship_date varchar,
 ...
)
USING ICEBERG
LOCATION ...
PARTITIONED BY l_ship_date;

INSERT INTO my_external_schema.lineitem VALUES (10099, '20251231', ...);
```

次の update クエリを実行します。

```
UPDATE my_external_schema.lineitem SET l_ship_date = '20260101'
WHERE l_item_id = 10099;
```

この `l_item_id` 10099 の行をパーティション `20251231` から新しいパーティション `20260101` に移動します。

また、`UPDATE` が複数の候補値を持つ可能性があることに注意してください。次のクエリについて考えてみます。

```
CREATE TABLE my_ext_schema.t1(x1 int, y1 int) USING ICEBERG LOCATION ...;
CREATE TABLE my_ext_schema.t2(x2 int, y2 int) USING ICEBERG LOCATION ...;
INSERT INTO my_ext_schema.t1 VALUES (1,10), (2,20), (3,30);
INSERT INTO my_ext_schema.t2 VALUES (2,40), (2,50);
UPDATE my_ext_schema.t1 SET y1=y2 FROM my_ext_schema.t2 WHERE x1=x2;
```

この場合、y1 は 40 または 50 にすることができます。結果は非決定的です。このような場合、設定パラメータ `error_on_nondeterministic_update` を true に設定してクエリエラーを強制できます。これは、既存の RMS テーブル `UPDATE` の動作と一致します。詳細については、「[error\_on\_nondeterministic\_update](https://docs.aws.amazon.com/redshift/latest/dg/r_error_on_nondeterministic_update.html)」を参照してください。

## MERGE
<a name="iceberg-writes-merge"></a>

`MERGE` クエリは、ソーステーブルの行を条件付きでターゲットテーブルにマージします。既存の RMS テーブルと同じ `MERGE` クエリ構文を共有します。

```
MERGE INTO {{target_iceberg_table}} USING {{source_table}} [ [ AS ] {{alias}} ]
ON {{match_condition}}
[ WHEN MATCHED THEN { UPDATE SET {{col_name}} = { {{expr}} } [,...] | DELETE }
  WHEN NOT MATCHED THEN INSERT [ ( {{col_name}} [,...] ) ]
  VALUES ( { {{expr}} } [, ...] )
| REMOVE DUPLICATES ]
```

S3 テーブルバケットには 3 つの部分からなる表記を使用することもできます。

```
MERGE INTO "{{<table_bucket_name>}}@s3tablescatalog".{{<database_name>}}.{{<table_name>}} USING {{source_table}} [ [ AS ] {{alias}} ]
ON {{match_condition}}
[ WHEN MATCHED THEN { UPDATE SET {{col_name}} = { {{expr}} } [,...] | DELETE }
  WHEN NOT MATCHED THEN INSERT [ ( {{col_name}} [,...] ) ]
  VALUES ( { {{expr}} } [, ...] )
| REMOVE DUPLICATES ]
```

`{{<external_schema>}}.{{<external_table_name>}}` は、`{{target_iceberg_table}}` フォームを使用して参照することも、自動マウントカタログの 3 つの部分からなる表記を使用することもできます。「[Amazon Redshift での Iceberg テーブルの参照](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)」を参照してください。

`{{source_table}}` は Iceberg テーブルまたは Amazon Redshift RMS テーブルのいずれかです。

`REMOVE DUPLICATES` を使用する場合、`MERGE` コマンドは簡易モードを使用します。簡易モードの詳細については、元の `MERGE` [コマンドドキュメント](https://docs.aws.amazon.com/redshift/latest/dg/r_MERGE.html)を参照してください。

`MERGE` クエリの実行中に、Amazon Redshift は中間データファイルを生成し、ターゲットテーブルの場所に保存します。これらのファイルは、クエリ終了時にガベージコレクションされます。このため、`MERGE` クエリを適切に動作させるには、Amazon S3 バケットに対する `DELETE` アクセス許可が必要です。ガベージコレクションオペレーションが失敗すると、アクセス許可不足エラーがスローされます。Amazon S3 テーブルの場合、ガベージコレクションは Amazon S3 Tables サービスによって管理されます。したがって、`MERGE` クエリを実行するのに `DELETE` アクセス許可は必要ありません。

## DROP TABLE
<a name="iceberg-writes-drop-table"></a>

カタログから Iceberg テーブルを削除するには、`DROP TABLE` コマンドを使用します。

```
DROP TABLE {{<external_schema>}}.{{<table_name>}}
```

自動マウントカタログでは、3 つの部分からなる表記を使用することもできます。

```
DROP TABLE "{{<catalog_name>}}".{{<database_name>}}.{{<table_name>}}
```

Iceberg テーブルの削除はメタデータのみの操作です。Amazon S3 テーブルの場合、AWS Glue Data Catalog と Amazon S3 テーブルカタログからテーブルエントリを削除します。Amazon Redshift は、テーブルの場所にある既存のデータファイルやメタデータファイルをクリーンアップまたは削除しません。AWS Glue および Amazon S3 テーブルの機能を使用して、孤立したファイルを削除できます。AWS Glue については、「[孤立ファイルの削除](https://docs.aws.amazon.com/glue/latest/dg/orphan-file-deletion.html)」を参照してください。Amazon S3 テーブルについては、「[テーブルのメンテナンス](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-maintenance.html)」を参照してください。