sql-metadataを試してみる

2022.01.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

データアナリティクス事業本部のkobayashiです。

Pythonでクエリをパースしてその内容を扱う必要があったため簡単に扱えるライブラリを探していた所 sql-metadata というライブラリが見つかりました。クエリのメタデータ(カラム名、テーブル名など)が簡単に取得できたのでその内容をまとめます。

環境

  • macOS Big Sur
  • Python 3.7.12

sql-metadataとは

クエリ中に含まれているカラム名やテーブル名やそのエイリアス名を簡単に取得できます。またInset文では挿入する値も取得できます。sql-metadataは非検証SQLパーサーのpythonライブラリであるsqlparse を内部で使用しています。sql-metadataではsqlparseで取得できるTokenクラスを使いメタデータを取得しています。sqlparseの説明は弊社ブログ記事で説明されていますのでそちらの記事も御覧ください。

sql-metadataで対応しているクエリ構文は以下となっています。

  • MySQL
  • PostgreSQL
  • Sqlite
  • MSSQL
  • Apache Hive

オンラインデモがありますのでこちらでsql-metadataの使用感を試すことができます。

sql-metadataを試してみる

インストールはpipを使ってインストールするだけです。

$ pip install sql-metadata

では実際にカラム名、テーブル名、そのエイリアス名、Insert文の値の取得を試してみます。

カラム名の取得

はじめにカラム名の抽出を行ってみます。Pythonのスクリプトは非常に単純で特に難しいこともありません。

import sql_metadata

query_md = sql_metadata.Parser("select col1 as aaa, col2 as bbb  from table1 as t_1;").columns
print(query_md)
# ['col1', 'col2']

query_md = sql_metadata.Parser("select col1 as aaa, col2 as bbb  from table1 as t_1;").columns_aliases
print(query_md)
# {'aaa': 'col1', 'bbb': 'col2'}

query_md = sql_metadata.Parser(
    "select t_1.col1 , t_2.col2 from table1 as t_1 inner join table2 as t_2 on t_1.id = t_2.id;").columns_dict
print(query_md)
# {'select': ['table1.col1', 'table2.col2'], 'join': ['table1.id', 'table2.id']}
  • 1つ目はクエリからカラム名だけを取得しています。
  • 2つ目はエイリアスを取得していますが、「エイリアス名をキー」「元のカラム名を値」としてdictで取得しています。
  • 3つ目はカラム名をクエリ中の句ごとに取得しています。今回ですとselect句とjoin句で使用しているカラム名を取得しています。またエイリアス名は元のテーブル名に置換されて取得できるのでわかりやすい表現となっています。

テーブル名の取得

次にテーブル名の抽出を行ってみます。

import sql_metadata

query_md = sql_metadata.Parser("select col1 as aaa, col2 as bbb  from table1 as t_1;").tables
print(query_md)
# ['table1']

query_md = sql_metadata.Parser("select col1 as aaa, col2 as bbb  from table1 as t_1;").tables_aliases
print(query_md)
# {'t_1': 'table1'}

query_md = sql_metadata.Parser(
    "select col1 , col2  from table1 as t_1 inner join table2 as t_2 on t_1.id = t_2.id;").tables
print(query_md)
# ['table1', 'table2']
  • 1つ目はクエリからテーブル名だけを取得しています。
  • 2つ目はエイリアスを取得していますが、「エイリアス名をキー」「元のカラム名を値」としてdictで取得しています。カラムのエイリアス取得と同じです。
  • 3つ目は結合しているテーブルがlist形式で取得できています。

サブクエリの取得

次はサブクエリの抽出を行ってみます。

import sql_metadata

query_md = sql_metadata.Parser(
    "select x.aaa,x.bbb from (select col1 as aaa, col2 as bbb  from table1 as t_1) x;").subqueries
print(query_md)
# {'x': 'select col1 as aaa, col2 as bbb from table1 as t_1'}
  • エイリアス名をキー、サブクエリを値としてdict形式で取得しています。

Insertでの値の取得

最後にInsert文での値を取得してみます。

import sql_metadata

query_md = sql_metadata.Parser("INSERT INTO table1 (col1, col2, col3) VALUES ('Japan', 'Tokyo', 99.9);").values
print(query_md)
# ['Japan', 'Tokyo', 99.9]

query_md = sql_metadata.Parser("INSERT INTO table1 (col1, col2, col3) VALUES ('Japan', 'Tokyo', 99.9);").values_dict
print(query_md)
# {'col1': 'Japan', 'col2': 'Tokyo', 'col3': 99.9}
  • 1つ目はセットしている値をlist形式で取得しています。
  • 2つ目はカラム名をキー、セットしている値を値としてdict形式で取得しています。

このようにとても簡単にクエリのメタデータが取得できました。

sql-metadataのソースコードのtest/ディレクトリにはより複雑なクエリでの実行結果例も載っているのでそちらも確認いただくとより知見が深まると思いますので、一度ご確認ください。

まとめ

Pythonのライブラリsql-metadataライブラリを使ってクエリからカラム名やテーブル名といったクエリのメタデータを取得してみました。それ以外にもInsert文の値やサブクエリなども簡単に取得でき、これらのメタデータを使って何か処理を行いたい際にはsql-metadataはおすすめのライブラリです。

最後まで読んで頂いてありがとうございました。