在会话中编写查询

本文档介绍如何在 BigQuery 会话中编写查询。本文档面向已对 BigQuery 会话有一定了解并且知道如何在会话中运行查询的用户。

会话存储状态。在一个会话中创建的状态会保留并在整个会话期间都可使用。因此,如果您在一个查询条目中创建临时表,则可以在会话的其余部分的其他查询条目中使用该临时表。

会话支持会话变量会话系统变量多语句查询多语句事务

在完成这些步骤之前,请确保您拥有在会话中正常工作所必需的权限

在会话中使用系统变量

您可使用以下系统变量来设置或检索会话级数据:

  • @@dataset_id:当前项目中默认数据集的 ID。系统变量 @@dataset_project_id@@dataset_id 可以一起使用。
  • @@dataset_project_id:查询中使用的数据集的默认项目 ID。如果未设置此系统变量,或将其设置为 NULL,则使用查询执行项目。系统变量 @@dataset_project_id@@dataset_id 可以一起使用。
  • @@query_label:要分配给会话的作业标签。标签可用于整个会话,而不仅仅是用于会话中的特定查询。
  • @@session_id:当前会话的 ID。
  • @@time_zone:在依赖时区的 SQL 函数中使用的默认时区(如果未将时区指定为参数)。

这些系统变量在会话期间可随时使用,并且适用于剩余会话。您无法定义这些变量,但可以使用 SET 语句为其分配新值。

会话中变量的大小上限为 1 MB,会话中所有变量的大小上限为 10 MB。

为会话分配标签

您可以为会话分配作业标签。执行此操作后,会话中的所有未来查询都将分配给该标签。标签在会话期间可随时使用,并且适用于剩余会话。您分配的作业标签将显示在审核日志中。

在会话中使用变量

您可以使用变量来创建、设置和检索会话级数据。变量在会话期间可随时使用,并且适用于剩余会话。

  • 如需创建会话范围的变量,请在 BEGIN...END 块之外使用 DECLARE 语句。
  • 如需在创建会话范围的变量后设置该变量,请使用 SET 语句。
  • BEGIN...END 块中声明的变量不是会话范围的变量。
  • 可在 BEGIN...END 块内部引用会话范围的变量。
  • 可在 BEGIN...END 块内设置会话范围的变量。

会话中变量的大小上限为 1 MB,会话中所有变量的大小上限为 10 MB。

在会话中使用临时表

通过临时表,您可以将中间结果保存到表中。临时表在会话级可见,因此您无需在数据集中保存或维护该临时表。它会在会话终止后自动删除。在会话处于活动状态时,您需要为临时表的存储付费。如需详细了解临时表,请参阅使用多语句查询

在会话中使用临时函数

临时函数在会话级可见,因此您无需在数据集中保存或维护该临时表。它会在会话终止后自动删除。

在会话中使用多语句查询

您可以在会话中使用 GoogleSQL 多语句查询。一个脚本可以包含每个脚本的临时表和系统变量。会话变量和临时表对脚本可见。在脚本中声明的所有顶级变量也是会话变量。

在会话中运行多查询多语句事务

您可以在一个会话中对多个查询运行多语句事务。例如:

以下查询会启动事务。

BEGIN TRANSACTION

在事务内,以下查询会创建一个名为 Flights 的临时表,然后返回此表中的数据。查询中包含两条语句。

CREATE TEMP TABLE Flights(total INT64)  AS SELECT * FROM UNNEST([10,23,3,14,55]) AS a;

SELECT * FROM Flights;

以下查询会提交事务。

COMMIT

您可通过以下命令找到影响 Flights 表的活动事务:

WITH running_transactions AS (
  SELECT DISTINCT transaction_id
  FROM
    `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
    WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
    EXCEPT DISTINCT
    SELECT transaction_id FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
    WHERE
      creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
      AND statement_type = "COMMIT_TRANSACTION"
      OR statement_type = "ROLLBACK_TRANSACTION"
)
SELECT
  jobs.transaction_id AS transaction_id,
  project_id,
  user_email,
  session_info.session_id,
  query
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT AS jobs, running_transactions
  WHERE
  creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND destination_table = ("Flights")
  AND jobs.transaction_id = running_transactions.transaction_id;

如果您要取消正在进行的事务,并且您拥有 bigquery.admin 角色,则可以使用与 Cloud Shell 中的事务相关联的会话 ID 发出回滚语句。也可以通过 API 调用发出此语句。使用与事务关联的会话 ID 运行查询时,结果中会显示会话 ID。

示例会话

以下是 Google Cloud 控制台中的会话工作流示例:

  1. 在 Google Cloud 控制台中,打开新的编辑器标签页,然后创建会话

  2. 在编辑器标签页中,添加以下查询:

    CREATE TEMP TABLE Flights(total INT64)  AS SELECT * FROM UNNEST([10,23,3,14,55]) AS a;
    SELECT * FROM Flights;
    
  3. 运行查询。系统会创建一个名为 Flights 的临时表,并返回所有数据。

    +-------+
    | total |
    +-------+
    |    55 |
    |    23 |
    |     3 |
    |    14 |
    |    10 |
    +-------+
    
  4. 删除编辑器标签页中的内容并添加以下查询:

    SELECT * FROM Flights LIMIT 2;
    
  5. 运行查询。返回两条记录的结果。即使您删除了较早的查询,该查询中的信息也会存储在当前会话中。

    +-------+
    | total |
    +-------+
    |    55 |
    |    23 |
    +-------+
    
  6. 删除编辑器标签页中的内容并添加以下查询:

    DECLARE x INT64 DEFAULT 10;
    
    SELECT total * x AS total_a FROM Flights LIMIT 2;
    
    BEGIN
      SET x = 100;
      SELECT total * x AS total_b FROM Flights LIMIT 2;
    END;
    
    SELECT total * x AS total_c FROM Flights LIMIT 2;
    
  7. 运行查询。会话范围的变量 x 用于限制为 Flights 表返回的结果数。如果此变量在 BEGIN...END 语句之外声明,在 BEGIN...END 语句内设置,然后再次在 BEGIN...END 语句外部引用,那么请仔细查看设置范围对此变量的影响。

    +---------+
    | total_a |
    +---------+
    |     550 |
    |     230 |
    +---------+
    
    +---------+
    | total_b |
    +---------+
    |    5500 |
    |    2300 |
    +---------+
    
    +---------+
    | total_c |
    +---------+
    |    5500 |
    |    2300 |
    +---------+
    
  8. 删除编辑器标签页中的内容并添加以下查询:

    SELECT STRING(TIMESTAMP "2008-12-20 15:30:00+00", @@time_zone) AS default_time_zone;
    
    SET @@time_zone = "America/Los_Angeles";
    
    SELECT STRING(TIMESTAMP "2008-12-20 15:30:00+00", @@time_zone) AS new_time_zone;
    
  9. 运行查询。会话范围的系统变量 @@time_zone 用于为时间戳分配时区。第一个语句返回带默认时区的时间戳(在此示例中为 UTC)。下一个语句将 @@time_zone 分配给新值。第三个语句返回带有新时区的时间戳。

    +-------------------------------+
    | default_time_zone             |
    +-------------------------------+
    | 2008-12-20 15:30:00+00        |
    +-------------------------------+
    
    +-------------------------------+
    | new_time_zone                 |
    +-------------------------------+
    | 2008-12-20 07:30:00-08        |
    +-------------------------------+
    

后续步骤