5
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?

BigQueryスクリプトで複数テーブルの行数比較を自動化する

Last updated at Posted at 2025-12-17

概要

前回の記事では、BigQueryスクリプトのFOR INループで複数テーブルを一括処理する方法を紹介しました。

今回はこれを応用して、EXECUTE IMMEDIATEINTO句とUSING句を活用し、複数テーブルの行数比較結果をテーブルに保存するスクリプトを紹介します。
テーブル移行時のデータ検証等に活用できるかと思います。

BigQueryスクリプト

DECLARE dataset_name STRING DEFAULT 'my_dataset';
DECLARE result_table STRING DEFAULT 'my-project.my_dataset.comparison_results';

DECLARE date_suffix STRING;
DECLARE table1_id STRING;
DECLARE table2_id STRING;
DECLARE table1_count INT64;
DECLARE table2_count INT64;
DECLARE is_equal BOOL;

BEGIN
  -- 行数比較結果保存用テーブルの作成
  CREATE TABLE IF NOT EXISTS `my-project.my_dataset.comparison_results` (
    table1 STRING,
    table2 STRING,
    table1_count INT64,
    table2_count INT64,
    is_equal BOOL,
    checked_at TIMESTAMP
  );

  FOR record IN (
    SELECT table_id
    FROM `my-project.my_dataset.__TABLES_SUMMARY__`
    WHERE REGEXP_CONTAINS(table_id, r'^target_table1_\d{8}$')
    ORDER BY table_id
  )
  DO
    SET table1_id = record.table_id;
    SET date_suffix = REGEXP_EXTRACT(table1_id, r'(\d{8})');
    SET table2_id = FORMAT('target_table2_%s', date_suffix);

    -- INTO句で結果を変数に格納
    EXECUTE IMMEDIATE FORMAT("""
      SELECT COUNT(1) FROM `my-project.%s.%s`
    """, dataset_name, table1_id)
    INTO table1_count;

    EXECUTE IMMEDIATE FORMAT("""
      SELECT COUNT(1) FROM `my-project.%s.%s`
    """, dataset_name, table2_id)
    INTO table2_count;

    SET is_equal = table1_count = table2_count;

    -- USING句でパラメータバインド
    EXECUTE IMMEDIATE FORMAT("""
      INSERT INTO %s (table1, table2, table1_count, table2_count, is_equal, checked_at)
      VALUES (@table1, @table2, @table1_count, @table2_count, @is_equal, CURRENT_TIMESTAMP())
    """, result_table)
    USING
      table1_id AS table1,
      table2_id AS table2,
      table1_count AS table1_count,
      table2_count AS table2_count,
      is_equal AS is_equal;

  END FOR;
END;

結果確認のsampleクエリ

比較結果をテーブルに格納しているので、以下のように確認できます。

SELECT *
FROM `my-project.my_dataset.comparison_results`
WHERE is_equal = FALSE
ORDER BY checked_at DESC;

前回からの応用ポイント

INTO句:クエリ結果を変数に格納する

通常のEXECUTE IMMEDIATEはクエリを実行するだけですが、INTO句を使うと結果を変数に格納できます。

-- 結果が変数 table1_count に入る
EXECUTE IMMEDIATE "SELECT COUNT(1) FROM `my-project.my_dataset.my_table`"
INTO table1_count;

これにより取得した値を後続の処理(比較やINSERTなど)で使えるようになります。

USING句:変数の値を安全にSQLへ渡す

INSERT文などで変数の値を使いたい場合、FORMATで直接埋め込む方法もありますが、USING句を使うとより安全に値を渡せます。

EXECUTE IMMEDIATE """
  INSERT INTO my_table (col1, col2)
  VALUES (@param1, @param2)
"""
USING
  value1 AS param1,
  value2 AS param2;

前回同様、FOR INループは1テーブルずつ逐次実行されるため対象テーブルが多い場合はご注意いただきたいですが、今回は検証結果をテーブル格納しているので、行数比較レベルのシンプルな検証であれば対象テーブルが-1000程度まではそこまで時間もかからないかな、といった印象です。(実行プロジェクトの混み具合次第ではありますが...)

以上です。
どなたかのお役に立てれば幸いです。

関連資料

5
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
5
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?