处理响应¶
本主题说明如何处理来自 SQL API 的响应。
本主题内容:
了解执行流程¶
默认情况下,Snowflake 同步执行语句并返回流程图中所示的响应代码之一:
如上面的流程图所示:
如果提交了一条成功执行的语句,Snowflake 将返回 HTTP 响应代码 200 和 ResultSet 对象中的结果行。
使用
ResultSet
对象 检索结果。如果 在单个请求中提交了多个语句,并且请求被成功处理,那么 Snowflake 将返回 HTTP 响应代码 200 和一个 ResultSet 对象。
ResultSet
对象不包含结果中的任何行。相反,data
字段仅包含消息“Multiple statements executed successfully.”。要检索数据,必须从
statementHandles
字段获取请求中各个语句的句柄。对于每个语句句柄,发送请求以检查语句的执行状态。请参阅 检查语句执行状态并检索数据。有关处理指定多个 SQL 语句的请求响应的过程的更多信息,请参阅 获取请求中每个 SQL 语句的结果。
如果语句执行时间超过 45 秒,或者如果指定应该异步执行该语句,Snowflake 将返回 HTTP 响应代码 202 和一个 QueryStatus 对象。
可以向
QueryStatus
对象中的statementStatusUrl
字段指定的端点发送请求,以检查语句的执行状态。请参阅 检查语句执行状态并检索数据。如果要取消该语句的执行,可以使用
QueryStatus
对象中statementHandle
字段的语句句柄向/api/v2/statements/statementHandle/cancel
发送请求。请参阅 取消执行 SQL 语句。。
检查语句执行状态并检索数据¶
在某些情况下,需要发送请求来检查语句的执行状态:
:doc:` 提交 SQL 语句进行执行 <submitting-requests>` 时,如果该语句的执行尚未完成或提交了异步查询,Snowflake 将返回 202 响应代码。
要检查语句是否已完成执行,必须发送请求以检查语句的状态。
如果 在单个请求中提交了多个 SQL 语句,那么可以通过发送一个检查语句状态的请求来获得每个语句的结果。
在这两种情况下,向 /api/v2/statements/
端点发送 GET
请求,并将语句句柄作为路径参数追加到 URL 路径的末尾。有关详细信息,请参阅 GET /api/v2/statements/{statementHandle}。
GET /api/v2/statements/{statementHandle}
{statementHandle}
是要检查的语句的句柄。要获取语句句柄,请执行以下操作:
如果收到带有 202 响应代码的响应,则响应的正文将包含一个 QueryStatus 对象。可以从此对象的
statementHandle
字段中获取语句句柄。请注意,还可以从此对象的
statementStatusUrl
字段中获取请求的完整 URL。{ "code": "090001", "sqlState": "00000", "message": "successfully executed", "statementHandle": "e4ce975e-f7ff-4b5e-b15e-bf25f59371ae", "statementStatusUrl": "/api/v2/statements/e4ce975e-f7ff-4b5e-b15e-bf25f59371ae" }
如果提交了包含多个 SQL 语句的请求,则响应的正文将包括一个包含
statementHandles
字段的ResultSet
对象。可以从此字段获取各个语句的句柄。{ ... "statementHandles" : [ "019c9fce-0502-f1fc-0000-438300e02412", "019c9fce-0502-f1fc-0000-438300e02416" ], ... }
例如,以下 curl
命令使用句柄 e4ce975e-f7ff-4b5e-b15e-bf25f59371ae
检查语句的状态:
curl -i -X GET \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "User-Agent: myApplicationName/1.0" \
-H "X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT" \
"https://<account_identifier>.snowflakecomputing.cn/api/v2/statements/e4ce975e-f7ff-4b5e-b15e-bf25f59371ae"
其中:
jwt
是您 为身份验证生成的 JWT。myApplicationName
是应用程序标识符的示例。account_identifier
是您的 账户标识符。
当发送检查状态的请求时,Snowflake 会返回以下流程图中所示的响应代码之一:
如上面的流程图所示:
如果语句已成功执行,Snowflake 将返回 HTTP 响应代码 200 和 ResultSet 对象中的结果行。
使用
ResultSet
对象 检索结果。如果语句尚未完成执行,Snowflake 将返回 HTTP 响应代码 202 和一个 QueryStatus 对象。
使用此对象 检查语句的执行状态。
如果在执行语句时发生错误,Snowflake 将返回 HTTP 响应代码 422 和一个 QueryFailureStatus 对象。
您可以从此对象获取 有关错误的详细信息。
从响应中获取结果¶
备注
Snowflake 版本 5.40 推出了对 Snowflake SQL API 返回的数据处理方式的变更,以及其他变更。
本部分介绍如何使用 Snowflake SQL API 的较新功能从响应中获取结果。有关使用较旧、已弃用行为的信息,请参阅 已弃用的功能。
如果 :doc:` 提交一条 SQL 语句进行执行 <submitting-requests>` 或 :ref:` 检查语句执行的状态 <label-sql_api_checking_statement_status>`,如果语句执行成功,Snowflake 将在响应正文中返回一个 ResultSet 对象。
Snowflake API 返回分区中的数据。Snowflake 确定返回的分区数和每个分区的大小。分区大小是变量,并且基于 Snowflake 针对特定 SQL 查询返回的数据量。
提交请求时,此响应的正文将包含一个 partitionInfo
字段。此字段包含一个对象数组,每个对象都描述一个数据分区。第一个对象描述此响应中返回的数据分区。其余对象描述可以通过针对 partition=partition_number
提交后续请求来检索的其他分区。
数组中的每个对象都指定分区的行数和大小。应用程序可以使用此分区元数据来确定如何处理为后续请求返回的分区。
下面显示了部分响应的示例:
{
"code": "090001",
"statementHandle": "536fad38-b564-4dc5-9892-a4543504df6c",
"sqlState": "00000",
"message": "successfully executed",
"createdOn": 1597090533987,
"statementStatusUrl": "/api/v2/statements/536fad38-b564-4dc5-9892-a4543504df6c",
"resultSetMetaData" : {
"numRows" : 50000,
"format" : "jsonv2",
"partitionInfo" : [ {
"rowCount" : 12288,
"uncompressedSize" : 124067,
"compressedSize" : 29591
}, {
"rowCount" : 37712,
"uncompressedSize" : 414841,
"compressedSize" : 84469
}],
},
"data": [
["customer1", "1234 A Avenue", "98765", "2021-01-20
12:34:56.03459878"],
["customer2", "987 B Street", "98765", "2020-05-31
01:15:43.765432134"],
["customer3", "8777 C Blvd", "98765", "2019-07-01
23:12:55.123467865"],
["customer4", "64646 D Circle", "98765", "2021-08-03
13:43:23.0"]
]
}
获取有关结果的元数据¶
在响应中返回的 ResultSet
对象中,resultSetMetaData
字段包含描述结果集的 ResultSet_resultSetMetaData 对象(例如,结果的格式、返回的分区数等)。
获取有关 ResultSet
对象中返回的列的元数据¶
resultSetMetaData
字段包含有关 ResultSet
对象中返回列的信息。
在下面的示例中, rowType
字段包含 ResultSet_resultSetMetaData_rowType 对象的数组。每个对象都描述结果中的一列。type
字段指定列的 Snowflake 数据类型。
{
"resultSetMetaData": {
"numRows": 1300,
"rowType": [
{
"name":"ROWNUM",
"type":"FIXED",
"length":0,
"precision":38,
"scale":0,
"nullable":false
}, {
"name":"ACCOUNT_NAME",
"type":"TEXT",
"length":1024,
"precision":0,
"scale":0,
"nullable":false
}, {
"name":"ADDRESS",
"type":"TEXT",
"length":16777216,
"precision":0,
"scale":0,
"nullable":true
}, {
"name":"ZIP",
"type":"TEXT",
"length":100,
"precision":0,
"scale":0,
"nullable":true
}, {
"name":"CREATED_ON",
"type":"TIMESTAMP_NTZ",
"length":0,
"precision":0,
"scale":3,
"nullable":false
}],
"partitionInfo": [{
... // Partition metadata
}]
}
}
获取有关 ResultSet
对象返回的分区的元数据¶
当您提交执行查询的请求时,响应将包含描述了如何在响应之间对数据进行分区以及第一个数据分区的元数据。
resultSetMetaData
字段包含一个 partitionInfo
字段。此字段包含一个对象数组,每个对象都描述一个数据分区。第一个对象描述此响应中返回的数据分区。其余的对象描述了可以通过使用 partition=partition_number
提交后续请求来检索的附加分区。
下面显示了部分响应的示例:
{
"resultSetMetaData": {
"numRows: 103477,
"format": "jsonv2"
"rowType": {
... // Column metadata.
},
"partitionInfo": [{
"rowCount": 12344,
"uncompressedSize": 14384873,
},{
"rowCount": 47387,
"uncompressedSize": 76483423,
"compressedSize": 4342748
},{
"rowCount": 43746,
"uncompressedSize": 43748274,
"compressedSize": 746323
}]
},
...
}
在此示例中, partitionInfo
字段中的第一个对象描述此响应的数据字段中的数据分区。
第二个对象描述第二个数据分区,其中包含 47387 行,您可以通过发送请求来进行检索
GET /api/v2/statements/handle?partition=1
。
第三个对象描述第三个数据分区,其中包含 43746 行,您可以通过发送请求
GET /api/v2/statements/handle?partition=2
。
从结果中获取数据¶
在响应中的 ResultSet
对象中,结果位于 data
字段中。data
字段包含 JSON 中的字符串数组。例如:
{
...
"data": [
["customer1", "1234 A Avenue", "98765", "2021-01-20 12:34:56.03459878"],
["customer2", "987 B Street", "98765", "2020-05-31 01:15:43.765432134"],
["customer3", "8777 C Blvd", "98765", "2019-07-01 23:12:55.123467865"],
["customer4", "64646 D Circle", "98765", "2021-08-03 13:43:23.0"]
],
...
}
数组中的每个数组都包含一行的数据。每个数组中的元素表示一行中的数据。
结果集中的数据用 JSON 编码并表示为字符串,与列的 Snowflake 数据类型无关。
例如, NUMBER
列中的值 1.0
作为字符串 "1.0"
返回。再举一个例子,时间戳以自纪元以来的纳秒数返回。例如,2021 年 1 月 28 日星期四 10:09:37.123456789 PM 的时间戳返回为 "1611871777123456789"
。
您负责将字符串转换为适当的数据类型。
根据 Snowflake 数据类型,Snowflake 以下列格式的字符串形式返回值(如果 POST 提交语句请求中未指定 输出格式参数 ):
- INT / NUMBER:
字符串中的十进制数。
- FLOAT:
字符串中的整数或浮点数。
- VARCHAR:
字符串。
- BINARY:
字符串中的十六进制数。
- BOOLEAN:
字符串中的“false”或“true”。
- DATE:
自纪元以来的天数的整数值(以字符串表示)(例如
18262
)。- TIME、TIMESTAMP_LTZ、TIMESTAMP_NTZ:
自纪元以来的秒数的浮点值(小数点后 9 位)(例如
82919.000000000
)。- TIMESTAMP_TZ:
自纪元以来的秒数的浮点值(小数点后 9 位),后跟空格和时区偏移量(以分钟为单位)(例如
1616173619000000000 960
)
检索其他分区¶
Snowflake SQL API 返回分区中的数据。第一个分区以 JSON 格式返回,并包含有关为特定查询返回的所有分区的元数据。应用程序可以使用此分区元数据来确定如何处理为后续请求返回的分区。
在收到包含第一个数据分区的响应后,可以通过针对 partition=partition_number
提交请求来获取其余分区,其中 partition_number
标识要返回的数据分区。分区号 0
标识在初始请求中返回的第一个数据分区。
例如,在收到第一个数据分区后,您可以通过提交一个请求来获取第二个数据分区,并将分区参数设置为 1
:
GET /api/v2/statements/<handle>?partition=1
在对 GET /api/v2/statements/<handle>?partition=partition_number
请求的响应中,正文包含压缩形式的 JSON 数据(使用 gzip)。
响应包括 HTTP 标头 Content-Encoding: gzip
,它指示响应的正文被压缩。
这些响应不包含任何元数据。所有分区的元数据在第一个分区中提供。
以字符串形式返回 SQL NULL 值¶
默认情况下,SQL NULL 值返回为值 null
:
"data" : [ [ null ], ... ]
如果希望这些值以字符串 "null"
的形式返回,请在 :doc:` 提交 SQL 语句以执行的 POST 请求 <submitting-requests>` 中将 nullable
查询参数设置为 false
。例如:
POST /api/v2/statements?nullable=false
这会将 SQL NULL 值返回为 "null"
:
"data" : [ [ "null" ], ... ]
备注
不能在 :ref:` 要检查语句状态的 GET 请求 <label-sql_api_checking_statement_status>` 中指定 nullable
参数。
设置查询结果输出的格式¶
Snowflake SQL API 支持用于格式化输出的参数(例如 日期、时间和时间戳的会话参数)。
例如,在默认情况下,像 2019-03-27 这样的 DATE 值返回为“17982”(2019-03-27 是时间戳之后的 17982 天)。如果您在以下请求中指定 DATE_OUTPUT_FORMAT 应该是“MM/DD/YY”:
{
"statement": "select date_column from mytable",
"resultSetMetaData": {
"format": "jsonv2",
},
"parameters": {
"DATE_OUTPUT_FORMAT": "MM/DD/YYYY"
}
...
}
DATE 值返回为“03/27/2019”。
在请求主体的 parameters
字段中,您可以设置以下参数,这些参数决定数据的输出格式:
BINARY_OUTPUT_FORMAT
DATE_OUTPUT_FORMAT
TIME_OUTPUT_FORMAT
TIMESTAMP_LTZ_OUTPUT_FORMAT
TIMESTAMP_NTZ_OUTPUT_FORMAT
TIMESTAMP_TZ_OUTPUT_FORMAT
TIMESTAMP_OUTPUT_FORMAT
TIMEZONE
备注
Snowflake 会忽略这些参数的账户级别和用户级别设置。为了在 SQL API 结果中更改各值的格式,您必须在请求主体中设置这些输出参数。
在 resultSet
对象中包含行号¶
结果集中不返回行号。若要在响应中包含行号,请在查询中调用 SEQUENCE 或 ROW_NUMBER 窗口函数来生成行号。