

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# SET 子句
<a name="iot-sql-set"></a>

使用 SET 子句定义存储表达式结果的变量。您可以在 SELECT 和 WHERE 子句以及替换模板中重复使用这些变量。这可以帮助您避免重复复杂的表达式并减少 SQL 语句中的函数调用次数。

SET 子句支持[数据类型](iot-sql-data-types.md)[运算符](iot-sql-operators.md)、[函数](iot-sql-functions.md)、、[文本](iot-sql-literals.md)、[Case 语句](iot-sql-case.md)、[JSON 扩展](iot-sql-json.md)、、[变量](#iot-sql-set-usage)和[嵌套对象查询](iot-sql-nested-queries.md)。

## SET 子句语法
<a name="iot-sql-set-syntax"></a>

SET 子句必须出现在您的 SQL 语句中的 SELECT 子句之前。使用以下语法：

```
SET @variable_name = expression [, @variable_name2 = expression2]
```

语法规则：
+ 变量名称的开头为 `@`
+ 变量名可以包含字母、数字和下划线
+ 变量名最长可为 64 个字符
+ 可以在单个 SET 子句中设置多个变量，用逗号分隔
+ 每个变量只能分配一次（变量是不可变的）
+ 每条 SQL 语句只能使用一次 SET 关键字

## 使用变量
<a name="iot-sql-set-usage"></a>

定义变量后，可以在以下情况下使用它们：
+ 选择子句
+ WHERE 子句
+ 其他 SET 变量赋值
+ 操作替换模板
+ 错误操作替换模板
+ 嵌套的选择查询
+ 函数参数（某些参数，例如 roLearn 参数和切换类似函数模式的参数`transform("enrichArray", attributes, values)`不支持变量）

使用与 SET 子句中相同的`@variable_name`语法来引用变量。您还可以使用 JSON 扩展语法来访问包含对象的变量的属性，例如`@variable_name.property`。

## SET 子句示例
<a name="iot-sql-set-examples"></a>

**变量的基本用法**

以下示例显示了按主题发布的有效负载`device/data`：`{"temp_fahrenheit": 75, "humidity": 60}`

SQL 语句：

```
SET @temp_celsius = (temp_fahrenheit - 32) * 5 / 9
SELECT @temp_celsius AS celsius, humidity FROM 'device/data'
```

传出有效载荷：`{"celsius": 23.89, "humidity": 60}`

**访问嵌入式 JSON 对象中的成员**

以下示例显示了按主题发布的有效负载`device/data`：`{"device1": {"deviceId":"weather_sensor", "deviceData": {"sensors": {"temp_fahrenheit": 75, "humidity": 60}, "location": [47.606,-122.332]}}}`

SQL 语句：

```
SET @device_sensor_data = device1.deviceData.sensors
SELECT @device_sensor_data.temp_fahrenheit AS temp_fahrenheit, @device_sensor_data.humidity as humidity, device1.deviceId as deviceId FROM 'device/data'
```

传出有效载荷：`{"temp_fahrenheit":75,"humidity":60,"deviceId":"weather_sensor"}`

 有关如何使用 JSON 扩展的更多信息，请参阅 [JSON 扩展](iot-sql-json.md) 

**避免重复的函数调用**

SET 变量有助于避免重复复杂的解码操作：

```
SET @decoded_data = decode(encode(*, 'base64'), 'proto', 'schema', 'schema.desc', 'message.proto', 'Message')
SELECT @decoded_data.sensor_id, @decoded_data.reading FROM 'device/protobuf' 
WHERE @decoded_data.reading > 100
```

如果没有 SET 变量，则需要重复三次解码函数，这会超出函数调用限制。

**多个变量**

你可以在单个 SET 子句中定义多个变量，方法是用逗号分隔它们：

```
SET @user_data = get_user_properties(device_id), @threshold = 50
SELECT @user_data.name, temp_fahrenheit FROM 'sensors/+'
WHERE temp_fahrenheit > @threshold AND @user_data.active = true
```

**在替换模板中使用变量**

变量还可以在操作替换模板中使用，允许您在 SQL 语句和规则操作中重复使用计算值。

SQL 语句：

```
SET @temp_celsius = (temp_fahrenheit - 32) * 5 / 9
SELECT @temp_celsius AS celsius, humidity FROM 'device/data'
```

操作配置：

```
{
  "s3": {
    "roleArn": "arn:aws:iam::123456789012:role/testRuleRole",
    "bucketName": "bucket",
    "key": "temperature-data/${device_id}/temp-${@temp_celsius}C.json"
  }
}
```

在此示例中，在替换模板中使用 SET 变量`@temp_celsius`来构造 S3 操作的关键字段。

**非 JSON 负载使用情况**

SET 变量不直接支持非 JSON 有效负载，因此必须先对有效负载进行编码或解码：

```
SET @encoded_payload = encode(*, 'base64')
SELECT @encoded_payload AS raw_data FROM 'device/binary'
```

 有关如何使用非 JSON 负载的更多信息，请参阅 [使用二进制有效载荷](binary-payloads.md) 

## 设定条款限制
<a name="iot-sql-set-limits"></a>

以下限制适用于 SET 变量：
+ 每条 SQL 语句最多有 10 个唯一变量
+ 最大可变值大小为 128 kiB（缩小后的 UTF-8 JSON 字符串）
+ 所有变量的最大总值大小为 128 KiB
+ 变量名限制为 64 个字符
+ 变量可以直接接受 JSON 负载（必须首先对非 JSON 负载进行编码/解码）