はじめに
BigQuery には、テーブルに追加された行の履歴を取得できる APPENDS 関数と、INSERT・UPDATE・DELETE などの変更履歴を取得できる CHANGES 関数があります。
どちらもテーブルの変更履歴を確認するための関数ですが、取得できる変更の種類や指定可能な期間などに違いがあります。
本記事では、同じテーブルに対して INSERT・UPDATE・DELETE を実行し、APPENDS と CHANGES でどのような結果が取得できるのかを比較します。
特に、以下の点を確認します。
-
APPENDSではどの変更が取得できるのか -
CHANGESではINSERT・UPDATE・DELETEがどのように記録されるのか - テーブル作成時点から履歴を取得した場合の
APPENDSとCHANGESの違い -
CHANGESに存在する「最大1日」の取得期間制限
サンプルテーブル作成
まず、動作確認に使用するテーブルを作成します。
今回は APPENDS だけでなく CHANGES の動作も確認するため、テーブル作成後に enable_change_history = TRUE を設定しています。APPENDS の利用だけであれば、enable_change_history の設定は必要ありません。
CREATE OR REPLACE TABLE
`<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
(
customer_id STRING,
customer_name STRING,
email STRING,
phone_number STRING,
postal_code STRING,
address STRING,
membership_rank STRING,
signup_date DATE,
is_active BOOL,
created_at TIMESTAMP
);
ALTER TABLE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
SET OPTIONS (
enable_change_history = TRUE
);
本記事では、テーブル作成時点からの履歴も確認するため、検証日の2日前に以下の初期データを登録しています。
初期データ
INSERT INTO
`<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
(
customer_id,
customer_name,
email,
phone_number,
postal_code,
address,
membership_rank,
signup_date,
is_active,
created_at
)
VALUES
(
'C001',
'山田 太郎',
'taro.yamada@example.com',
'090-1234-5678',
'100-0001',
'東京都千代田区千代田1-1',
'GOLD',
DATE '2024-01-15',
TRUE,
TIMESTAMP '2026-08-05 01:00:00+00'
),
(
'C002',
'佐藤 花子',
'hanako.sato@example.com',
'080-2345-6789',
'150-0001',
'東京都渋谷区神宮前2-2',
'SILVER',
DATE '2024-03-20',
TRUE,
TIMESTAMP '2026-08-05 01:05:00+00'
),
(
'C003',
'鈴木 一郎',
'ichiro.suzuki@example.jp',
'070-3456-7890',
'530-0001',
'大阪府大阪市北区梅田3-3',
'STANDARD',
DATE '2024-06-01',
TRUE,
TIMESTAMP '2026-08-05 01:10:00+00'
),
(
'C004',
'高橋 美咲',
'misaki.takahashi@example.com',
NULL,
'460-0001',
'愛知県名古屋市中区三の丸4-4',
'GOLD',
DATE '2025-01-10',
TRUE,
TIMESTAMP '2026-08-05 01:15:00+00'
),
(
'C005',
NULL,
'anonymous@example.com',
'09012345678',
NULL,
NULL,
'STANDARD',
DATE '2025-04-05',
FALSE,
TIMESTAMP '2026-08-05 01:20:00+00'
),
(
'C006',
'John Smith',
'john.smith+test@example.com',
'+81-90-4567-8901',
'060-0001',
'北海道札幌市中央区北一条西5-5',
'SILVER',
DATE '2025-07-12',
TRUE,
TIMESTAMP '2026-08-05 01:25:00+00'
);
DML を実行
続いて、APPENDS と CHANGES の違いを確認するため、同じレコードに対して INSERT → UPDATE → DELETE の順に DML を実行します。
INSERT INTO `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
VALUES
(
'C000',
'山田 太郎',
'taro.yamada@example.com',
'090-1111-2222',
'100-0001',
'東京都千代田区千代田1-1',
'GOLD',
DATE '2026-08-01',
TRUE,
CURRENT_TIMESTAMP()
);
UPDATE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
SET
membership_rank = 'PLATINUM',
email = 'new.taro.yamada@example.com'
WHERE customer_id = 'C000';
DELETE FROM `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`
WHERE customer_id = 'C000';
APPENDS と CHANGES を確認
ここからは、先ほど実行した DML が APPENDS と CHANGES でどのように取得されるのかを確認します。
まずは DML を実行する直前の時刻を start_timestamp に指定し、その時刻からクエリ実行時点までの変更履歴を取得します。
DML 実行直前から現在時刻まで
まず APPENDS を実行します。
end_timestamp に NULL を指定すると、クエリの実行開始時点までに追加された行が取得対象になります。
SELECT
customer_id,
_CHANGE_TYPE,
_CHANGE_TIMESTAMP
FROM APPENDS(
TABLE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`,
TIMESTAMP '2026-08-07 04:20:00+00',
NULL
)
ORDER BY _CHANGE_TIMESTAMP
;
実行結果を見ると、C000 の INSERT のみが取得されています。
その後に実行した UPDATE と DELETE は APPENDS の履歴には追加されません。
続いて、同じ期間を指定して CHANGES を実行します。
SELECT
customer_id,
_CHANGE_TYPE,
_CHANGE_TIMESTAMP,
_CHANGE_IS_FOR_UPDATE
FROM CHANGES(
TABLE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`,
TIMESTAMP '2026-08-07 04:20:00+00',
NULL
)
ORDER BY _CHANGE_TIMESTAMP
;
CHANGES では、INSERT・UPDATE・DELETE による変更を確認できます。
UPDATE が実行された場合、更新前のレコードは _CHANGE_TYPE = 'DELETE'、更新後のレコードは _CHANGE_TYPE = 'UPDATE' として出力されます。
テーブル作成時点から現在時刻まで
次に、start_timestamp と end_timestamp の両方に NULL を指定し、テーブル作成時点から現在までの履歴を取得してみます。
今回のテーブルは検証日の2日前に作成しており、テーブル作成時刻は BigQuery のタイムトラベル期間内にあります。
まず APPENDS を実行します。
SELECT
customer_id,
_CHANGE_TYPE,
_CHANGE_TIMESTAMP
FROM APPENDS(
TABLE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`,
NULL,
NULL
)
ORDER BY _CHANGE_TIMESTAMP
;
APPENDS では、テーブル作成時点から現在までに追加された行の履歴を取得できます。
同じ条件で CHANGES も実行してみます。
SELECT
customer_id,
_CHANGE_TYPE,
_CHANGE_TIMESTAMP,
_CHANGE_IS_FOR_UPDATE
FROM CHANGES(
TABLE `<PROJECT_ID>.<DATASET_ID>.<TABLE_NAME>`,
NULL,
NULL
)
ORDER BY _CHANGE_TIMESTAMP
;
こちらはエラーになります。
CHANGES では、start_timestamp と end_timestamp の間に指定できる期間が最大1日に制限されています。
今回はテーブル作成から2日以上経過しているため、start_timestamp = NULL によってテーブル作成時点から取得しようとすると、1日の上限を超えてエラーになります。
Updated change history start time to table creation time. The change history time window for CHANGES TVF exceeds the maximum allowed time window seconds of 86400. Start time: 2026-08-05T04:18:11.371Z, end time: 2026-08-07T05:15:08.866001Z. Table: 578497549185:<DATASET_ID>.<TABLE_NAME>
まとめ
APPENDS と CHANGES の違いを整理すると、以下のようになります。
| 項目 | APPENDS | CHANGES |
|---|---|---|
| INSERT | 取得できる | 取得できる |
| UPDATE | 取得できない | 取得できる |
| DELETE | 取得できない | 取得できる |
enable_change_history |
不要 | 必要 |
| 1回に指定できる期間 | 1日の制限なし | 最大1日 |
| タイムトラベル期間の制限 | あり | あり |
_CHANGE_IS_FOR_UPDATE |
なし | あり |





