

 Amazon Redshift 將不再支援從修補程式 198 開始建立新的 Python UDFs。現有 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/)。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# MERGE
<a name="r_MERGE"></a>

有條件地將來源資料表中的資料列合併到目標資料表中。傳統上，這只能透過單獨使用多個插入、更新或刪除陳述式來實現。如需使用 MERGE 讓您合併操作的相關資訊，請參閱 [UPDATE](https://docs.aws.amazon.com/redshift/latest/dg/r_UPDATE.html)、[DELETE](https://docs.aws.amazon.com/redshift/latest/dg/r_DELETE.html) 和 [INSERT](https://docs.aws.amazon.com/redshift/latest/dg/r_INSERT_30.html)。

## 語法
<a name="r_MERGE-synopsis"></a>

```
MERGE INTO target_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 ]
```

## Parameters
<a name="r_MERGE-parameters"></a>

 *target\_table*  
將與 MERGE 陳述式合併的暫存或永久資料表。

 *source\_table*  
提供要合併到 *target\_table* 之列的暫存或永久資料表。*source\_table* 也可以是 Spectrum 資料表。

 *alias*  
*source\_table* 暫時替代名稱。  
此為選用參數。以 AS 開頭的 *alias* 也是選用項目。

 *match\_condition*  
指定來源資料表資料欄與目標資料表資料欄之間的相等述詞，這些資料欄的作用是判斷 *source\_table* 中的資料列是否可與 *target\_table* 中的資料列相符。如果符合條件，則 MERGE 會針對該資料列執行 *matched\_clause*。否則，MERGE 會為該資料列執行 *not\_matched\_clause*。

WHEN MATCHED  
 指定當來源資料列與目標資料列之間的比對條件評估為 True 時，要執行的動作。您可以指定 UPDATE 動作或 DELETE 動作。

UPDATE  
 更新 *target\_table* 中的相符資料列。只會更新 *col\_name* 中您指定的值。

DELETE  
 刪除 *target\_table* 中的相符資料列。

WHEN NOT MATCHED  
 指定當比對條件評估為 False 或未知時要執行的動作。您只能為此子句指定 INSERT 插入動作。

INSERT  
 根據 *match\_condition*，從 *source\_table* 將不符合 *target\_table* 中的任何列插入 *target\_table* 列中。您可以依任意順序列出目標 *col\_name*。如果您不提供任何 *col\_name* 值，則預設順序是按所有資料表資料欄的宣告順序排序。

 *col\_name*  
您要修改的一個或多個資料欄名稱。不要在指定目標資料欄時包含資料表名稱。

 *expr*  
定義 *col\_name* 新值的運算式。

 REMOVE DUPLICATES  
指定 MERGE 命令以簡化模式執行。簡化模式有以下要求：  
+  *target\_table* 和 *source\_table* 必須具有相同數目的欄、相容的欄類型，以及相同的欄順序。
+  從 MERGE 命令省略 WHEN 子句和 UPDATE 和 INSERT 子句。
+  在 MERGE 命令中使用 REMOVE DUPLICATES 子句。
在簡化模式中，MERGE 會執行下列操作：  
+  *target\_table* 中具有 *source\_table* 中相符項目的資料列會更新，以符合 *source\_table* 中的值。
+  *source\_table* 中沒有 *target\_table* 中相符項目的資料列會插入到 *target\_table* 中。
+  當 *target\_table* 中的多個資料列與 *source\_table* 中的相同資料列相符時，重複的資料列會移除。Amazon Redshift 會保留一個資料列並對其進行更新。與 *source\_table* 中的資料列不相符的重複資料列保持不變。
使用 REMOVE DUPLICATES 可提供比使用 WHEN MATCHED 和 WHEN NOT MATCHED 更好的效能。如果 *target\_table* 和 *source\_table* 相容，而且您不需要在 *target\_table* 中保留重複資料列，我們建議您使用 REMOVE DUPLICATES。

## 使用須知
<a name="r_MERGE_usage_notes"></a>
+ 若要執行 MERGE 陳述式，您必須是 *source\_table* 和 *target\_table* 的擁有者，或具有這些資料表的 SELECT 許可。此外，視 MERGE 陳述式中包含的操作而定，您可能必須擁有 *target\_table* 的 UPDATE、DELETE 和 INSERT 許可。
+  *target\_table* 不能是系統資料表、目錄資料表或外部資料表。
+  *source\_table* 和 *target\_table* 不能是相同資料表。
+  您無法在 MERGE 陳述式中使用 WITH 子句。
+  *target\_table* 的資料列無法比對 *source\_table* 中的多個資料列。

  請思考下列範例：

  ```
  CREATE TABLE target (id INT, name CHAR(10));
  CREATE TABLE source (id INT, name CHAR(10));
  
  INSERT INTO target VALUES (1, 'Bob'), (2, 'John');
  INSERT INTO source VALUES (1, 'Tony'), (1, 'Alice'), (3, 'Bill');
  
  MERGE INTO target USING source ON target.id = source.id
  WHEN MATCHED THEN UPDATE SET id = source.id, name = source.name
  WHEN NOT MATCHED THEN INSERT VALUES (source.id, source.name);
  ERROR: Found multiple matches to update the same tuple.
  
  MERGE INTO target USING source ON target.id = source.id
  WHEN MATCHED THEN DELETE
  WHEN NOT MATCHED THEN INSERT VALUES (source.id, source.name);
  ERROR: Found multiple matches to update the same tuple.
  ```

  在這兩個 MERGE 陳述式中，操作都會失敗，因為 `source` 資料表中有多個 ID 值為 `1` 的資料列。
+  *match\_condition* 和 *expr* 不能部分參考 SUPER 類型的資料欄。例如，如果您的 SUPER 類型物件是陣列或結構，就不能將該資料欄的個別元素用於 *match\_condition* 或 *expr*，但您可以使用整個資料欄。

  請思考下列範例：

  ```
  CREATE TABLE IF NOT EXISTS target (key INT, value SUPER);
  CREATE TABLE IF NOT EXISTS source (key INT, value SUPER);
  
  INSERT INTO target VALUES (1, JSON_PARSE('{"key": 88}'));
  INSERT INTO source VALUES (1, ARRAY(1, 'John')), (2, ARRAY(2, 'Bill'));
  
  MERGE INTO target USING source ON target.key = source.key
  WHEN matched THEN UPDATE SET value = source.value[0]
  WHEN NOT matched THEN INSERT VALUES (source.key, source.value[0]);
  ERROR: Partial reference of SUPER column is not supported in MERGE statement.
  ```

  如需 SUPER 類型的相關資訊，請參閱 [SUPER 類型](https://docs.aws.amazon.com/redshift/latest/dg/r_SUPER_type.html)。
+ 如果 *source\_table* 很大，則將 *target\_table* 和 *source\_table* 中的聯接資料欄定義為分佈索引鍵可以提高性能。
+ 若要使用 REMOVE DUPLICATES 子句，您需要 *target\_table* 的 SELECT、INSERT 和 DELETE 許可。
+  *source\_table* 可以是檢視或子查詢。以下是 MERGE 陳述式的範例，其中 *source\_table* 是移除重複列的子查詢。

  ```
  MERGE INTO target
  USING (SELECT id, name FROM source GROUP BY 1, 2) as my_source
  ON target.id = my_source.id
  WHEN MATCHED THEN UPDATE SET id = my_source.id, name = my_source.name
  WHEN NOT MATCHED THEN INSERT VALUES (my_source.id, my_source.name);
  ```
+ 目標不可是相同 MERGE 陳述式之任何子查詢的資料來源。例如，下列 SQL 命令會傳回如下所示的錯誤：ERROR: Source view/subquery in Merge statement cannot reference target table. (錯誤：Merge 陳述式中的來源檢視/子查詢無法參考目標資料表)，因為子查詢參考 `target` 而非 `source`。

  ```
  MERGE INTO target
  USING (SELECT id, name FROM {{target}} GROUP BY 1, 2) as my_source
  ON target.id = my_source.id
  WHEN MATCHED THEN UPDATE SET id = my_source.id, name = my_source.name
  WHEN NOT MATCHED THEN INSERT VALUES (my_source.id, my_source.name);
  ```

## 範例
<a name="sub-examples-merge"></a>

下列範例會建立兩個資料表，然後對其執行 MERGE 作業，並更新目標資料表中的相符資料列，以及插入不相符的資料列。然後將另一個值插入到來源表資料表中，並執行另一個 MERGE 操作，這次會刪除相符的資料列並從來源資料表中插入新資料列。

首先建立並填入來源和目標資料表。

```
CREATE TABLE target (id INT, name CHAR(10));
CREATE TABLE source (id INT, name CHAR(10));

INSERT INTO target VALUES (101, 'Bob'), (102, 'John'), (103, 'Susan');
INSERT INTO source VALUES (102, 'Tony'), (103, 'Alice'), (104, 'Bill');

SELECT * FROM target;
 id  |    name
-----+------------
 101 | Bob
 102 | John
 103 | Susan
(3 rows)

SELECT * FROM source;
 id  |    name
-----+------------
 102 | Tony
 103 | Alice
 104 | Bill
(3 rows)
```

接下來，將來源資料表合併到目標資料表，使用相符的資料列更新目標資料表，並從來源資料表插入不相符的資料列。

```
MERGE INTO target USING source ON target.id = source.id
WHEN MATCHED THEN UPDATE SET id = source.id, name = source.name
WHEN NOT MATCHED THEN INSERT VALUES (source.id, source.name);

SELECT * FROM target;
 id  |    name
-----+------------
 101 | Bob
 102 | Tony
 103 | Alice
 104 | Bill
(4 rows)
```

請注意，識別碼值為 102 和 103 的資料列會更新，以符合目標資料表中的名稱值。此外，ID 值為 104 且名稱值為 Bill 的新資料列會插入目標資料表中。

接下來，在來源資料表中插入新資料列。

```
INSERT INTO source VALUES (105, 'David');

SELECT * FROM source;
 id  |    name
-----+------------
 102 | Tony
 103 | Alice
 104 | Bill
 105 | David
(4 rows)
```

最後，執行合併操作，刪除目標資料表中的相符資料列，並插入不相符的資料列。

```
MERGE INTO target USING source ON target.id = source.id
WHEN MATCHED THEN DELETE
WHEN NOT MATCHED THEN INSERT VALUES (source.id, source.name);

SELECT * FROM target;
 id  |    name
-----+------------
 101 | Bob
 105 | David
(2 rows)
```

識別碼值為 102、103 和 104 的資料列會從目標資料表中刪除，而識別碼值為 105 且名稱值為 David 的新資料列會插入目標資料表中。

下列範例顯示使用 REMOVE DUPLICATES 子句的簡化 MERGE 命令語法。

```
CREATE TABLE target (id INT, name CHAR(10));
CREATE TABLE source (id INT, name CHAR(10));

INSERT INTO target VALUES (30, 'Tony'), (11, 'Alice'), (23, 'Bill');
INSERT INTO source VALUES (23, 'David'), (22, 'Clarence');

MERGE INTO target USING source ON target.id = source.id REMOVE DUPLICATES;

SELECT * FROM target;
id | name
---+------------
30 | Tony
11 | Alice
23 | David
22 | Clarence
(4 rows)
```

下列範例顯示使用 REMOVE DUPLICATES 子句的簡化 MERGE 命令語法，會在 *target\_table* 中的列與 *source\_table* 中的列相符時，從前者中移除重複的列。

```
CREATE TABLE target (id INT, name CHAR(10));
CREATE TABLE source (id INT, name CHAR(10));

INSERT INTO target VALUES (30, 'Tony'), (30, 'Daisy'), (11, 'Alice'), (23, 'Bill'), (23, 'Nikki');
INSERT INTO source VALUES (23, 'David'), (22, 'Clarence');

MERGE INTO target USING source ON target.id = source.id REMOVE DUPLICATES;

SELECT * FROM target;
id | name
---+------------
30 | Tony
30 | Daisy
11 | Alice
23 | David
22 | Clarence
(5 rows)
```

執行 MERGE 後， *target\_table* 中只有一個 ID 值為 23 的資料列。由於 *source\_table* 中沒有 ID 值為 30 的資料列，所以 ID 值為 30 的兩個重複資料列會保留在 *target\_table* 中。

## 另請參閱
<a name="r_MERGE-see-also"></a>

 [INSERT](r_INSERT_30.md), [UPDATE](r_UPDATE.md), [DELETE](r_DELETE.md) 