# UPDATE文の構文

UPDATE文は、テーブル内の既存の行の値を変更するために使用します。

UPDATE文は、不正なデータの修正、欠損値の補完、行を削除・再挿入せずにステータス項目を更新する場合などに役立ちます。

Note
TrinoにおけるUPDATE文のサポートは、まだ実験的な段階です。

## 構文

```sql
UPDATE <table_name> SET <column_name> = <value>[, <column_name> = <value> ...] WHERE <condition>
```

各項目について:

- <table_name> は更新対象のテーブル名です
- <column_name> = <value> はカラムに設定する新しい値です
- <condition> は検索条件を指定する句です


意図しないデータ変更の発生を抑えるため、`WHERE`句のない`UPDATE`文は許可されていません。

### 例

航空便で出荷されたすべての品目のステータスを更新する例:

```sql
UPDATE lineitem SET status = 'SHIPPED' WHERE shipmode = 'AIR'
```

2017年7月1日(UTC)のイベントログを処理済みとしてマークする例:

```sql
UPDATE lineitem SET processed = true WHERE TD_TIME_RANGE(time, '2017-07-01','2017-07-02')
```

## 制限事項

### WHERE句のないUPDATEは不可

意図しないデータ変更の発生を抑えるため、UPDATE文ではWHERE句を含める必要があります。

エラーの例:

```
Does not support UPDATE statement without WHERE condition
```

### Data Tankに対するUPDATE

Data Tankに格納されているデータに対してUPDATE文を発行することはできません。
Data Tankに格納されたデータに対してUPDATE文を発行するには、PostgreSQL Data Tankに直接接続してください。

### 一度に更新できるパーティション数の上限

1つのUPDATEクエリで更新できるパーティション数は最大500kです。
この上限を超えるとUPDATEクエリは失敗します。

#### UPDATE文の影響範囲を減らす {#reduce-affected-rows-of-update-statement}

上限超過エラーやタイムアウトエラーでUPDATEクエリが失敗した場合は、影響範囲を減らすようにUPDATE文を書き換えてください。最も効果的な方法は、`TD_TIME_RANGE`または`TD_INTERVAL`を使ってUPDATEの時間範囲を制限するWHERE句を追加することです。たとえば、1年分のゲーム履歴データがある場合、次のクエリではなく、

```
UPDATE game_history SET active = false WHERE player_id=1000;
```

次のように書き換えます。

```
UPDATE game_history SET active = false
  WHERE player_id=1000
  AND TD_TIME_RANGE(time, '2018-01-01', '2018-02-01','PDT')
```

その後、すべての行が更新されるまで、時間範囲を変えながら更新を繰り返します。

### UPDATE文のタイムアウトエラー

UPDATE文の影響範囲が非常に大きい場合、UPDATEクエリは数時間かかることがあります。この場合、クエリがタイムアウトしてジョブが失敗することがあります。タイムアウトエラーでジョブが失敗した場合は、影響範囲を減らすようにUPDATE文を書き換えてください。[UPDATE文の影響範囲を減らす](#reduce-affected-rows-of-update-statement)を参照してください。

### 同一テーブルに対する同時DELETE/UPDATE文は競合する可能性があります

同一テーブルに対して複数のUPDATE文を同時に実行すると、実行時間が長くなったり、クエリが失敗したりすることがあります。これは、内部のパーティションファイル更新処理が競合するためです。一般的なガイドラインとして、UPDATE文の同時実行は避けることをおすすめします。競合の発生可能性は、UPDATE文の条件、データ量、テーブルのデータ分布など、さまざまな要因に依存し、予測が困難です。

競合によりUPDATE文が失敗した場合は、クエリを再実行してください。

### UPDATE文のリソース消費

UPDATEクエリはジョブを発行し、リソースを消費します。Treasure AIで使用されているストレージおよびインデックス方式の特性上、UPDATEクエリはリソースを多く消費する場合があります。

UPDATEクエリでフルテーブルスキャンが発生しないようにするには、以下を使用してください:

- テーブルがデフォルトの時間ベースパーティショニングを使用している場合は、TD_TIME_RANGEやTD_INTERVALなどの時間式
- テーブルがユーザー定義パーティショニングを使用している場合は、すべてのパーティションキーに対する等価述語


たとえば、テーブルが時間でパーティショニングされていて、2018年6月に作成されたユーザーセットを更新しようとしている場合、それがUPDATE文の重要なパラメーターでなくても、時間制約を含めてください。

たとえば、次のように記述します:

```
UPDATE logtable SET status = 'reviewed' WHERE userid IN (1234, 1235, 1236) AND TD_TIME_RANGE(time, '2018-06-01','2018-07-01')
```

時間制約を含めることで、クエリの速度が大幅に向上し、消費するリソースも削減されます。

## UPDATE文の取り消し

実行済みのUPDATE文をロールバックして変更前の値を復元したい場合は、Treasure AIサポートに連絡し、実行されたUPDATE文を含むジョブのジョブIDを提供する必要があります。多くの場合、UPDATE文を取り消すことができます。ただし、特定の状況ではUPDATE文のロールバックができません。

ロールバックができない状況には、次のようなものがあります:

- 別のUPDATE文によって新しいパーティションが変更されている場合。
- 保持期間の経過により、元のパーティションが破棄されている場合。
- テーブルが削除され、同じ名前で新しいテーブルが作成されている場合。
- 内部ストレージのメンテナンス処理の結果として、新しいパーティションがさらに変更または置き換えられている場合。