

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

# 在 DynamoDB 中使用更新表達式
<a name="Expressions.UpdateExpressions"></a>

`UpdateItem` 操作會更新現有項目，如尚不存在，則會將新項目新增到資料表中。您必須提供要更新項目的索引鍵。您也必須提供更新表達式，指出您想要修改的屬性以及您想要指派給它們的值。

*更新表達式*會指定 `UpdateItem` 如何修改項目的屬性，例如設定純量值或將元素從清單或映射中刪除。

以下是更新表達式的語法摘要。

```
update-expression ::=
    [ SET action [, action] ... ]
    [ REMOVE action [, action] ...]
    [ ADD action [, action] ... ]
    [ DELETE action [, action] ...]
```

更新表達式包含一或多個子句。每個子句的開頭是 `SET`、`REMOVE`、`ADD` 或 `DELETE` 關鍵字。您可以依任意順序在更新表達式中包含其中任何子句。不過，每個動作關鍵字都只能出現一次。

在每個子句內，會有以逗號分隔的一或多個動作。每個動作都會代表資料修改。

本節中的範例是以[在 DynamoDB 中使用投影表達式](Expressions.ProjectionExpressions.md)中所顯示的 `ProductCatalog` 項目為基礎。

以下主題涵蓋了 `SET` 動作的一些不同使用案例。

**Topics**
+ [SET – 修改或新增項目屬性](#Expressions.UpdateExpressions.SET)
+ [REMOVE – 刪除項目中的屬性](#Expressions.UpdateExpressions.REMOVE)
+ [ADD – 更新數字與集合](#Expressions.UpdateExpressions.ADD)
+ [DELETE – 移除集合中的元素](#Expressions.UpdateExpressions.DELETE)
+ [使用多個更新表達式](#Expressions.UpdateExpressions.Multiple)

## SET – 修改或新增項目屬性
<a name="Expressions.UpdateExpressions.SET"></a>

在更新表達式中使用 `SET` 動作，將一或多個屬性新增至項目。這些屬性如已存在，每一個都會為新值所覆寫。如果您想要避免覆寫現有屬性，則可以搭配使用 `SET` 與 `if_not_exists` 函數。`if_not_exists` 函數為 `SET` 動作專有，而且只能用於更新表達式。

當您使用 `SET` 更新清單元素時，會將該元素的內容取代為您所指定的新資料。如果元素尚未存在，則 `SET` 會在清單結尾附加新的元素。

如果您在單一 `SET` 操作中新增多個元素，則會依元素號碼依序排序元素。

您也可以使用 `SET` 來加減類型為 `Number` 的屬性。若要執行多個 `SET` 動作，請使用逗號分隔它們。

在下列語法摘要中：
+ *path* 元素是項目的文件路徑。
+ **operand** 元素可以是項目或函數的文件路徑。

```
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function

function ::=
    if_not_exists (path, value)
```

如果項目不包含指定路徑中的屬性，則 `if_not_exists` 會評估為 `value`。否則，項目會評估為 `path`。

下列 `PutItem` 操作會建立範例參考的範例項目。

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

`--item` 的引數會存放在 `item.json` 檔案中。(為求簡化，只會使用一些項目屬性)。

```
{
    "Id": {"N": "789"},
    "ProductCategory": {"S": "Home Improvement"},
    "Price": {"N": "52"},
    "InStock": {"BOOL": true},
    "Brand": {"S": "Acme"}
}
```

**Topics**
+ [修改屬性](#Expressions.UpdateExpressions.SET.ModifyingAttributes)
+ [新增清單和映射](#Expressions.UpdateExpressions.SET.AddingListsAndMaps)
+ [將元素新增至清單](#Expressions.UpdateExpressions.SET.AddingListElements)
+ [新增巢狀映射屬性](#Expressions.UpdateExpressions.SET.AddingNestedMapAttributes)
+ [增加和減少數值屬性](#Expressions.UpdateExpressions.SET.IncrementAndDecrement)
+ [將元素附加至清單](#Expressions.UpdateExpressions.SET.UpdatingListElements)
+ [防止覆寫現有屬性](#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites)

### 修改屬性
<a name="Expressions.UpdateExpressions.SET.ModifyingAttributes"></a>

**Example**  
更新 `ProductCategory` 和 `Price` 屬性。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET ProductCategory = :c, Price = :p" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":c": { "S": "Hardware" },
    ":p": { "N": "60" }
}
```

**注意**  
在 `UpdateItem` 操作中，`--return-values ALL_NEW` 會讓 DynamoDB 傳回在更新後所顯示的項目。

### 新增清單和映射
<a name="Expressions.UpdateExpressions.SET.AddingListsAndMaps"></a>

**Example**  
新增清單和映射。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":ri": {
        "L": [
            { "S": "Hammer" }
        ]
    },
    ":pr": {
        "M": {
            "FiveStar": {
                "L": [
                    { "S": "Best product ever!" }
                ]
            }
        }
    }
}
```

### 將元素新增至清單
<a name="Expressions.UpdateExpressions.SET.AddingListElements"></a>

**Example**  
將新的屬性新增至 `RelatedItems` 清單。(請記住，清單元素的開頭為零，因此 [0] 代表清單中的第一個元素、[1] 代表第二個元素，以此類推)。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :ri" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":ri": { "S": "Nails" }
}
```

**注意**  
當您使用 `SET` 更新清單元素時，會將該元素的內容取代為您所指定的新資料。如果元素尚未存在，則 `SET` 會在清單結尾附加新的元素。  
如果您在單一 `SET` 操作中新增多個元素，則會依元素號碼依序排序元素。

### 新增巢狀映射屬性
<a name="Expressions.UpdateExpressions.SET.AddingNestedMapAttributes"></a>

**Example**  
新增一些巢狀映射屬性。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
    --expression-attribute-names file://names.json \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-names` 的引數會存放在 `names.json` 檔案中。  

```
{
    "#pr": "ProductReviews",
    "#5star": "FiveStar",
    "#3star": "ThreeStar"
}
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":r5": { "S": "Very happy with my purchase" },
    ":r3": {
        "L": [
            { "S": "Just OK - not that great" }
        ]
    }
}
```

**重要**  
如果父映射不存在，則無法更新巢狀映射屬性。如果您嘗試在父映射 (`ProductReviews.FiveStar`) 不存在時更新巢狀屬性 （例如 `ProductReviews`)，DynamoDB 會傳回 `ValidationException`，並顯示*「更新表達式中提供的文件路徑無效，無法更新」訊息。*  
建立稍後更新巢狀對應屬性的項目時，請初始化父屬性的空對應。例如：  

```
{
    "Id": {"N": "789"},
    "ProductReviews": {"M": {}},
    "Metadata": {"M": {}}
}
```
這可讓您像 一樣更新巢狀屬性，`ProductReviews.FiveStar`而不會發生錯誤。

### 增加和減少數值屬性
<a name="Expressions.UpdateExpressions.SET.IncrementAndDecrement"></a>

您可以新增或扣除現有數值屬性。若要執行此作業，請使用 `+` (加號) 和 `-` (減號) 運算子。

**Example**  
減少項目的 `Price`。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```
若要增加 `Price`，您要在更新表達式中使用 `+` 運算子。

### 將元素附加至清單
<a name="Expressions.UpdateExpressions.SET.UpdatingListElements"></a>

您可以將元素新增至清單結尾。若要執行此作業，請搭配使用 `SET` 與 `list_append` 函數。(函數名稱區分大小寫。) `list_append` 函數為 `SET` 動作專有，而且只能用於更新表達式。語法如下。
+ `list_append (list1, list2)`

此函數需要兩個列表作為輸入，並將所有元素從 `list2` 附加到 ` list1`。

**Example**  
在[將元素新增至清單](#Expressions.UpdateExpressions.SET.AddingListElements)中，您會建立 `RelatedItems` 清單，並使用兩個元素填入它：`Hammer` 和 `Nails`。現在，您可在 `RelatedItems` 結尾多附加兩個元素。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(#ri, :vals)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values file://values.json  \
    --return-values ALL_NEW
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":vals": {
        "L": [
            { "S": "Screwdriver" },
            {"S": "Hacksaw" }
        ]
    }
}
```
最後，您將另一個元素附加到 `RelatedItems` 的*開頭*。若要執行此作業，請切換 `list_append` 元素的順序。(請記住，`list_append` 採用兩份清單做為輸入，並將第二份清單附加至第一份清單。)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(:vals, #ri)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
    --return-values ALL_NEW
```
產生的 `RelatedItems` 屬性現在會包含五個元素，順序如下：`Chisel`、`Hammer`、`Nails`、`Screwdriver`、`Hacksaw`。

### 防止覆寫現有屬性
<a name="Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites"></a>

**Example**  
設定項目的 `Price`，但只有在項目還沒有 `Price` 屬性時。(如果 `Price` 已存在，則不會發生任何事。)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW
```

## REMOVE – 刪除項目中的屬性
<a name="Expressions.UpdateExpressions.REMOVE"></a>

在更新表達式中使用 `REMOVE` 動作，從而在 Amazon DynamoDB 中移除項目的一或多個屬性。若要執行多個 `REMOVE` 動作，請使用逗號分隔它們。

下列是更新表達式中 `REMOVE` 的語法摘要。唯一的運算元是您想要移除的屬性文件路徑。

```
remove-action ::=
    path
```

**Example**  
移除項目中的一些屬性。(如果屬性不存在，則不會發生任何事。)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE Brand, InStock, QuantityOnHand" \
    --return-values ALL_NEW
```

### 移除清單中的元素
<a name="Expressions.UpdateExpressions.REMOVE.RemovingListElements"></a>

您可以使用 `REMOVE` 刪除清單中的個別元素。

**Example**  
在 [將元素附加至清單](#Expressions.UpdateExpressions.SET.UpdatingListElements) 中，您修改清單屬性 (`RelatedItems`)，讓它包含五個元素：  
+ `[0]`—`Chisel`
+ `[1]`—`Hammer`
+ `[2]`—`Nails`
+ `[3]`—`Screwdriver`
+ `[4]`—`Hacksaw`
下列 AWS Command Line Interface (AWS CLI) 範例`Nails`會從清單中刪除 `Hammer`和 。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
    --return-values ALL_NEW
```
移除 `Hammer` 和 `Nails` 之後，會轉移其餘的元素。此清單現在包含下列項目：  
+ `[0]`—`Chisel`
+ `[1]`—`Screwdriver`
+ `[2]`—`Hacksaw`

## ADD – 更新數字與集合
<a name="Expressions.UpdateExpressions.ADD"></a>

**注意**  
一般而言，建議使用 `SET`，而不是`ADD`確保等冪性操作。

在更新表達式中使用 `ADD` 動作，將新的屬性及其值新增至項目。

如果屬性已存在，則 `ADD` 的行為取決於屬性的資料類型：
+ 如果屬性是數字，而您要新增的值也是數字，則此值會以數學方式新增到現有屬性。(如果值是負數，則會從現有屬性減去。)
+ 如果屬性是集合，而您要新增的值也是集合，則此值會附加至現有集合。

**注意**  
`ADD` 動作只支援數字和集合資料類型。

若要執行多個 `ADD` 動作，請使用逗號分隔它們。

在下列語法摘要中：
+ *path* 元素是屬性的文件路徑。屬性必須是 `Number` 或集合資料類型。
+ *value* 元素是您要新增至屬性的數字 (針對 `Number` 資料類型)，或要附加至屬性的集合 (針對集合類型)。

```
add-action ::=
    path value
```

以下主題涵蓋了 `ADD` 動作的一些不同使用案例。

**Topics**
+ [新增數字](#Expressions.UpdateExpressions.ADD.Number)
+ [將元素新增至集合](#Expressions.UpdateExpressions.ADD.Set)

### 新增數字
<a name="Expressions.UpdateExpressions.ADD.Number"></a>

假設 `QuantityOnHand` 屬性不存在。下列 AWS CLI 範例會將 `QuantityOnHand`設定為 5。

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW
```

現在已有 `QuantityOnHand`，您可以重新執行範例，`QuantityOnHand` 每次的增量為 5。

### 將元素新增至集合
<a name="Expressions.UpdateExpressions.ADD.Set"></a>

假設 `Color` 屬性不存在。下列 AWS CLI 範例會將 `Color` 設定為具有兩個元素的字串集。

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
    --return-values ALL_NEW
```

現在已有 `Color`，您可以在其中新增更多元素。

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
    --return-values ALL_NEW
```

## DELETE – 移除集合中的元素
<a name="Expressions.UpdateExpressions.DELETE"></a>

**重要**  
`DELETE` 動作僅支援 `Set` 資料類型。

在更新表達式中使用 `DELETE` 動作，移除集合中的一或多個元素。若要執行多個 `DELETE` 動作，請使用逗號分隔它們。

在下列語法摘要中：
+ *path* 元素是屬性的文件路徑。屬性必須是集合資料類型。
+ *subset* 是您要從 *path* 刪除的一或多個元素。您必須指定 *subset* 做為集合類型。

```
delete-action ::=
    path subset
```

**Example**  
在 [將元素新增至集合](#Expressions.UpdateExpressions.ADD.Set) 中，您會建立 `Color` 字串集。本範例會從該集合中移除一些元素。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "DELETE Color :p" \
    --expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
    --return-values ALL_NEW
```

## 使用多個更新表達式
<a name="Expressions.UpdateExpressions.Multiple"></a>

您可以在單一更新表達式中使用多個動作。套用任何動作之前，所有屬性參考都會針對項目的狀態進行解析。

**Example**  
指定項目 時`{"id": "1", "a": 1, "b": 2, "c": 3}`，下列表達式會移除`a`並轉移 `b`和 的值`c`：  

```
aws dynamodb update-item \
    --table-name test \
    --key '{"id":{"S":"1"}}' \
    --update-expression "REMOVE a SET b = a, c = b" \
    --return-values ALL_NEW
```
結果為 `{"id": "1", "b": 1, "c": 2}`。即使`a`移除`b`並在相同的表達式中重新指派，這兩個參考都會解析為其原始值。

**Example**  
如果您想要修改屬性的值並完全移除其他屬性，您可以在單一陳述式中使用 SET 和 REMOVE 動作。此操作會將 `Price` 值減少為 15，同時也會從項目中移除 `InStock` 屬性。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p REMOVE InStock" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```

**Example**  
如果您想要新增至清單，同時變更其他屬性的值，您可以在單一陳述式中使用兩個 SET 動作。此操作會將「釘子」新增到 `RelatedItems` 清單屬性中，並將 `Price` 值設定為 21。  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :newValue, Price = :newPrice" \
    --expression-attribute-values '{":newValue": {"S":"Nails"}, ":newPrice": {"N":"21"}}'  \
    --return-values ALL_NEW
```