BigQuery - 检查 table 是否已经存在

BigQuery - Check if table already exists

我在 BigQuery 中有一个数据集。此数据集包含多个 table。

我正在使用 BigQuery API 以编程方式执行以下步骤:

  1. 查询数据集中的 tables - 由于我的响应太大,我启用了 allowLargeResults 参数并将我的响应转移到目标 table.

  2. 然后我将数据从目标 table 导出到 GCS 存储桶。

要求:

我该怎么做?

提前致谢。

这里是一个 python 片段,它将判断 table 是否存在(在此过程中删除它——小心!):

def doesTableExist(project_id, dataset_id, table_id):
  bq.tables().delete(
      projectId=project_id, 
      datasetId=dataset_id,
      tableId=table_id).execute()
  return False

或者,如果您不想在此过程中删除 table,您可以尝试:

def doesTableExist(project_id, dataset_id, table_id):
  try:
    bq.tables().get(
        projectId=project_id, 
        datasetId=dataset_id,
        tableId=table_id).execute()
    return True
  except HttpError, err
    if err.resp.status <> 404:
       raise
    return False

如果你想知道bq来自哪里,你可以从这里调用build_bq_clienthttp://code.google.com/p/bigquery-e2e/source/browse/samples/ch12/auth.py

一般来说,如果您使用它来测试您是否应该 运行 一项会修改 table 的工作,那么最好还是完成这项工作,并且使用 WRITE_TRUNCATE 作为写入配置。

另一种方法是创建一个 predictable 作业 ID,然后使用该 ID 重试该作业。如果作业已经存在,则作业已经 运行(但是,您可能需要仔细检查以确保作业没有失败)。

享受:

def doesTableExist(bigquery, project_id, dataset_id, table_id):
    try:
        bigquery.tables().get(
            projectId=project_id, 
            datasetId=dataset_id,
            tableId=table_id).execute()
        return True
    except Exception as err:
        if err.resp.status != 404:
            raise
        return False

有一个编辑异常。

my_bigquery 是 class google.cloud.bigquery.Client 的一个实例(已经验证并关联到一个项目):

my_bigquery.dataset(dataset_name).table(table_name).exists()  # returns boolean

它执行 API 调用以通过 GET 请求 table 测试是否存在

来源:https://googlecloudplatform.github.io/google-cloud-python/0.24.0/bigquery-table.html#google.cloud.bigquery.table.Table.exists

它对我有用 Google Bigquery Python 模块的 0.27

Alex F 的解决方案适用于 v0.27,但不适用于更高版本。为了 migrate to v0.28+,以下解决方案将起作用。

from google.cloud import bigquery

project_nm = 'gc_project_nm'
dataset_nm = 'ds_nm'
table_nm = 'tbl_nm'

client = bigquery.Client(project_nm)
dataset = client.dataset(dataset_nm)
table_ref = dataset.table(table_nm)

def if_tbl_exists(client, table_ref):
    from google.cloud.exceptions import NotFound
    try:
        client.get_table(table_ref)
        return True
    except NotFound:
        return False

if_tbl_exists(client, table_ref)

内联SQL备选

tarheel's answer is probably the most correct at this point in time

但我正在考虑上面 Ivan 的评论,即“404 也可能意味着由于多种原因资源不存在”,所以这是一个应该总是成功的解决方案 运行 元数据查询和return一个结果。

It's not the fastest, because it always has to run the query, bigquery has overhead for small queries

我之前看到的一个技巧是查询 information_schema 一个 (table) 对象,然后 union 一个确保记录总是 returned 即使对象没有。还有一个 LIMIT 1 和一个排序,以确保单个记录 returned 代表 table,如果它确实存在的话。请参阅下面代码中的 SQL。

  • 尽管文档声称 Bigquery 标准 SQL 符合 ISO,但它们不支持 information_schema,但它们确实支持 __table_summary__
  • dataset 是必需的,因为如果不指定 dataset
  • 就无法查询 __table_summary__
  • 数据集不是 SQL 中的参数,因为如果没有 sql 注入问题就无法参数化对象名称(除了神奇的 _TABLE_SUFFIX,请参阅 https://cloud.google.com/bigquery/docs/querying-wildcard-tables )
#!/usr/bin/env python
"""
Inline SQL way to check a table exists in Bigquery

e.g.
print(table_exists(dataset_name='<dataset_goes_here>', table_name='<real_table_name'))
True

print(table_exists(dataset_name='<dataset_goes_here>', table_name='imaginary_table_name'))
False
"""
from __future__ import print_function
from google.cloud import bigquery


def table_exists(dataset_name, table_name):
    client = bigquery.Client()
    query = """
        SELECT table_exists FROM
        (
          SELECT true as table_exists, 1 as ordering
          FROM __TABLES_SUMMARY__ WHERE table_id = @table_name
          UNION ALL
          SELECT false as table_exists, 2 as ordering
        ) ORDER by ordering LIMIT 1"""
    query_params = [bigquery.ScalarQueryParameter('table_name', 'STRING', table_name)]
    job_config = bigquery.QueryJobConfig()
    job_config.query_parameters = query_params

    if dataset_name is not None:
        dataset_ref = client.dataset(dataset_name)
        job_config.default_dataset = dataset_ref

    query_job = client.query(
        query,
        job_config=job_config
    )

    results = query_job.result()
    for row in results:
        # There is only one row because LIMIT 1 in the SQL
        return row.table_exists

您现在可以使用 exists() 检查数据集是否与 table 相同 BigQuery exist documentation

最近 big query 引入了所谓的脚本语句,这对于某些流程来说可能是游戏规则的改变者。

在这里查看: https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting

现在例如检查 table 是否存在你可以使用这样的东西:

sql = """
  BEGIN
  IF EXISTS(SELECT 1 from `YOUR_PROJECT.YOUR_DATASET.YOUR_TABLE) THEN
  SELECT 'table_found';
  END IF;
  EXCEPTION WHEN ERROR THEN

  # you can print your own message like above or return error message 
  # however google says not to rely on error message structure as it may change

  select @@error.message;
END;
"""