You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
create or replace table `check_table_schema.target_table`asselect* replace (cast(station_id as STRING) as station_id)
from`check_table_schema.reference_table`
;
with table1 as (
select*from`check_table_schema.INFORMATION_SCHEMA.COLUMNS`where table_name ='reference_table'
)
, table2 as (
select*from`check_table_schema.INFORMATION_SCHEMA.COLUMNS`where table_name ='target_table'
)
select
if(
count(1) >0
, error(
string_agg(
format('%t', (
column_name
, lhs.data_type
, rhs.data_type
, compare_result
))
)
)
, "PASSED"
) as msg
from table1 as lhs
full join table2 as rhs using(column_name)
left join unnest([STRUCT(
case
when lhs.data_type=rhs.data_type then "STRICT_MATCH"
when lhs.data_type!=rhs.data_type then "STRICT_UNMATCH"
when lhs.data_typeis not null then "EXISTS_ONLY_LEFT"
when rhs.data_typeis not null then "EXISTS_ONLY_RIGHT"
end as compare_result
)])
where compare_result not in ("STRICT_MATCH")
with core as (
select* replace (cast(station_id as STRING) as station_id)
from`check_table_schema.reference_table`
)
, _validation as (
-- ※ カラム名一致や厳密な型一致は取れないselect*from`check_table_schema.reference_table`union allselect*from core
limit0
)
select*from core
--> Column 1 in UNION ALL has incompatible types: INT64, STRING at [9:9]
ただし、この方法では UNION ALLオペレータでは暗黙的な型変換を許容するため、
次のようなケースではエラーを発生させることができず、緩い等価性で評価される。
with core as (
select* replace (cast(station_id as BIGNUMERIC) as station_id)
from`check_table_schema.reference_table`
)
, _validation as (
-- ※ カラム名一致や厳密な型一致は取れないselect*from`check_table_schema.reference_table`union allselect*from core
limit0
)
select*from core
メリット
カラム数と緩い等価一致の確認ができる
CTEとして組み込みが可能で、DRYRUNなどでの検証も可能
ゼロコスト: スキャン量やクエリコストがかからない
デメリット
カラム名の合致は比較できない
緩い等価確認になる
厳密なカラムの型一致
union all などによる set operatorでの確認では、簡易的で利用しやすい分暗黙的変換が行われる。
厳密な型一致で比較できない点で不便である。
これを型レベルで比較するには、次のようにすると良い。
with
ref1 as (
select1as a, 2as b
)
, ref2 as (
select2as c, 3as d
)
, _validation as (
select-- Schme field consitency
if(
format('%t', `bqutil.fn.json_extract_keys`(json_query(to_json_string([lhs]), "$.0")))
= format('%t', `bqutil.fn.json_extract_keys`(json_query(to_json_string([rhs]), "$.0")))
-- Schema type consitencyand ([lhs] || [rhs]) is not null
, null
, error("schema field is not matched")
)
--> Errorfrom unnest([0])
left join (select*from ref1 limit0) as lhs on true
left join (select*from ref2 limit0) as rhs on true
)
select*from _validation
-- dee テーブルを構築
create temp table _skelton_dee
asselect
(
selectas struct
(selectas struct *from`check_table_schema.reference_table`limit0).*
) as lhs
, (
selectas struct
(
selectas struct * replace (cast(station_id as STRING) as station_id)
from`check_table_schema.reference_table`limit0
).*
) as rhs
;
select
if(
array_length(`bqutil.fn.json_extract_keys`(to_json_string(lhs))) = (
select
countif(lhs = rhs)
from
unnest(`bqutil.fn.json_extract_keys`(to_json_string(lhs))) as lhs with offset ix
, unnest(`bqutil.fn.json_extract_keys`(to_json_string(rhs))) as rhs with offset iy
)
and [lhs] || [rhs]
, "PASSED"
, error('table schema is not matched')
)
from _skelton as r
with
ref1 as (
select1as a, 2as b
)
, ref2 as (
select2as c, 3as d
)
, _validation as (
select-- Schme field consitency
if(
format('%t', `bqutil.fn.json_extract_keys`(json_query(to_json_string([lhs]), "$.0")))
= format('%t', `bqutil.fn.json_extract_keys`(json_query(to_json_string([rhs]), "$.0")))
-- Schema type consitencyand ([lhs] || [rhs]) is not null
, null
, error("schema field is not matched")
)
from unnest([0])
left join (select*from ref1 limit0) as lhs on true
left join (select*from ref2 limit0) as rhs on true
)
select*from _validation
テーブルが特定のスキーマと同一の型表現を持つことはしばしば重要である。
SQLにはや、JOINやワイルドカード表現含め最終的なテーブルの出力形式は暗黙的に解決する方法も多く
暗黙的な型変換やNULLに関する型推論によりテーブルの出力結果の型が意図せず変えてしまうことも多い。
こういった場合において、テーブルのカラム群の整合性を確認できることは便利である。
例えば、本番用のテーブルと現在開発中のテーブルの整合性が確認できることで
変更の際の懸念をひとつ減らすことができる。
この記事では、テーブル間のスキーマの整合性を確認する手段の方法について検討する
準備
この記事では、次のような形で テーブルが物理化されていることを前提に実行を行う。
確認したいSQL
INFORMATION_SCHEMA.COLUMNS による 確認
カラムの整合性を確認するための、最も単純な方法は INFORMATION_SCHEMAを確認し
テーブルのスキーマを確認する方法である。
これは次のように確認することができる。
メリット
デメリット
緩いカラムの型一致
最初の手段ではスキャン量がかかる型確認方法だったが、これをゼロコストで達成したい。
つまりスキャンコストやスロット消費が無い状態で確認する状態の達成を目指す。
これは次のようなクエリで確認することができる。
ただし、この方法では UNION ALLオペレータでは暗黙的な型変換を許容するため、
次のようなケースではエラーを発生させることができず、緩い等価性で評価される。
メリット
デメリット
厳密なカラムの型一致
union all などによる set operatorでの確認では、簡易的で利用しやすい分暗黙的変換が行われる。
厳密な型一致で比較できない点で不便である。
これを型レベルで比較するには、次のようにすると良い。
メリット:
デメリット:
テーブルの整合性の厳密一致
SQL単体では、テーブルのカラム型までは確認できるが、カラム名やカラム名の順序までは比較することができない。
BigQuery Scriptを利用し、ここまでの方法を発展させるとクエリの実行コストを抑えた
テーブルの型検証を行うことができる。
上記、手順は煩雑なためプロシージャなどで用意すると良いかもしれない。
メリット
デメリット
まとめ
この記事では、SQLが生成するテーブルの整合性を確認するための方法を紹介した。
ここで紹介した検証方法を使うことで、スロット消費を限りなく抑えた型確認をSQL単体で、実行することができる。確認項目と用途に応じて選べると良いだろう
The text was updated successfully, but these errors were encountered: