2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BigQueryでテーブルのDDL(CreateTable文)をINFORMATION_SCHEMAから若干無理やり(?)作成する

Last updated at Posted at 2021-01-11

ざっと調べたのですが、BQで掲題のように任意のテーブルからCreateTable文を取得する簡単な方法(show create table等)が見つからなかったのでINFORMATION_SCHEMAを利用して作ってみました。(バッドノウハウ感がありますが・・・ :thinking:

※カラム数が数百とかあったりする場合便利かもしれません。
 もっとスマートな取得方法がありましたら、どなたか教えて下さい。

CREATE TABLE文を生成するクエリ(SQLを生成するSQL)

以下、DDL(CREATE TABLE文)を生成するクエリですが、生成されるDDLの形式としては**「CREATE TABLE XXX AS SELECT」構文**にしています。
前半のCREATE部が欲しい場合や、逆にSELECTだけが欲しいケースの場合、適宜withブロックの「ddl」のところを編集すれば都合の良い形式に編集できると思います。

with
target as (
  select
    -- 利用対象のテーブル名になるようここを編集してください
    'my-project' as project,
    'my-dataset' as dataset,  -- データセットだけは下記クエリの方にも複数箇所埋め込まれていることに注意(全部置換必要)
    'my-table' as table
),
table_info as (
  SELECT
    tables.table_catalog,
    tables.table_schema,
    tables.table_name,
    option.option_value,
  FROM
    my-dataset.INFORMATION_SCHEMA.TABLES tables
    cross join target
    left join my-dataset.INFORMATION_SCHEMA.TABLE_OPTIONS option
      on tables.table_catalog = option.table_catalog
      and tables.table_schema = option.table_schema
      and tables.table_name = option.table_name
      and option_name = 'description'
  where
    tables.table_catalog = target.project
    and tables.table_schema = target.dataset
    and tables.table_name = target.table
),
column_info as (
  SELECT
    column.ordinal_position,
    column.column_name,
    column.data_type,
    path.description,
  FROM
    my-dataset.INFORMATION_SCHEMA.COLUMNS column
      cross join target
      left join my-dataset.INFORMATION_SCHEMA.COLUMN_FIELD_PATHS path
        on column.table_name = path.table_name
        and column.column_name = path.column_name
  WHERE
    column.table_catalog = target.project
    and column.table_schema = target.dataset
    and column.table_name = target.table
),
ddl as (
  -- はじめの「create table xxx (」までを作る部分
  select
    0 as ordinal_position,
    'create table ' || table_info.table_catalog || '.' || table_info.table_schema || '.' || table_info.table_name ||  ' (' as text,
  from
    table_info
  union all
  -- 「カラム名 データ型 カラム説明」のリストを作る部分
  SELECT
    column_info.ordinal_position,
    '  ' || column_info.column_name || ' ' || column_info.data_type || ' options(description="' || ifnull(column_info.description, '') || '"),' as text,
  FROM
    column_info
  union all
  -- CREATE TABLE文の最後、テーブルの説明などのオプションを指定する部分(パーティションテーブルも対応したいなどはこの辺をいじればOK)
  select
    1000000 as ordinal_position,
    ') options(description = "' || ifnull(trim(table_info.option_value, '"'), '') || '") as select' as text,
  from
    table_info
  union all
  -- SELECTのカラムリスト
  SELECT
    1000000 + column_info.ordinal_position as ordinal_position,
    '  ' || column_info.column_name || ','  as text,
  FROM
    column_info
  union all
  -- SELECTのFrom部
  select
    10000000 as ordinal_position,
    'from ' || table_info.table_catalog || '.' || table_info.table_schema || '.' || table_info.table_name as text,
  from
    table_info
)
select ddl.text from ddl order by ordinal_position

使い方

  • 以下3つのキーワードを自分の環境に合わせて修正する
    • my-project
    • my-dataset (※他は修正1箇所ですが、datasetだけ修正が複数箇所に必要であることにご注意を)
    • my-table

注意点

  • 以下の情報しか取得していませんので、必要に応じてもう少し編集必要です。(例えばパーティション情報などは対象外)
    • テーブル名物理
    • カラム名物理
    • テーブルDESCRIPTION
    • カラムDESCRIPTION

結果の紹介

対象のテーブル

create table my-dataset.test_table_01 (
  col1 NUMERIC options(description="カラム1つ目"),
  col2 STRING options(description="カラム2つ目"),
  col3 DATETIME options(description="カラム3つ目"),
) options(description = "テストのテーブル")

image.png

SQL実行結果(SQLを生成するクエリ実行結果)

プロジェクトIDは隠しています。データセットはtest_terui_01です。
image.png

DDL利用方法

BQのWEBコンソールに出力されたものを複数行に渡るDDL形式にするために、ちょっとめんどくさい加工が必要になりました。
→Pythonとかで軽いツール作りたくなりますが、面倒なのでそこまではやってません。

DDLのSQLテキストを取得する手順

  • 「SAVE RESULTS」で「Google Sheets」を選択して結果を取得する
  • スプレッドシートに書かれたA列をコピーする

なぜわざわざ「Google Sheets」としたか

  • 「Copy to Clipboard」や「CSV」の場合、クエリ中にあるダブルコートやカンマなどが影響していて、エスケープ用のダブルコートが付加されるため、エスケープをクリアする処理が必要になる
  • JSONの場合も、クエリにそのまま転用するには文字列加工が必要

image.png

おしまい。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?