読者です 読者をやめる 読者になる 読者になる

【SQL Server】テーブルのメタデータを取得する

色々と作業していたらテーブル設計書とレイアウトが全然違うテーブルが存在することに気づきました。

流石にテーブル名ぐらいはあってるんですが、見たことないカラムがもりもり追加されています。一体何を見てこのテーブルが作られたのか皆目検討もつきません。担当者は既に失踪してるので責め立てることも出来ません。まぁ、よくあることです。

とりあえず今のレイアウトと設計書のレイアウトのDiffをとらないとどうにもならないので、テーブルのメタデータを取得するSQLを書きます。こうやって余計な仕事が増えていくんですよねぇ。

オブジェクトカタログビューをながめる

Oracleなんかでもそうですが、SQL Serverのオブジェクト(テーブル、ビュー、インデックス、ストアドプロシージャ etc…)の情報はちゃんとDBに保管されているし、SELECTの権限があれば普通に見れます。

そのほとんどが見れるのがこのオブジェクトカタログです。とりあえずsys.objectsから見ていくのが定石です。

このsys.objects.object_idと他のカタログビューのobject_idをJOINしてもりもり情報をかき集めていくことになります。今回はテーブルだけ見れればいいので、sys.columnsと結合します。

SELECT
 --TODO:メタデータをあつめる
FROM
 sys.objects obj
 INNER JOIN sys.columns col
  ON obj.object_id = col.object_id
WHERE
 -- U = テーブル (ユーザー定義) 
 obj.type = 'U'

ちなみに、sys.tablesと言うビューもあります。これはsys.object.type = ‘U’で抽出済みだったり、他の情報が付与されてたりと、そこそこ便利です。今回はどっちでもいいんですけどね。

必要な情報をあつめる

じゃあ先ほどのSQLをベースに必要な情報を集めていきましょう。

SELECT
 obj.name [テーブル名]
 , col.name [カラム名]
 , col.max_length [最大桁数]
 , col.precision [有効桁数]
 , col.scale [小数点以下桁数]
 , col.is_nullable [Null許可]
FROM
 sys.objects obj
 INNER JOIN sys.columns col
  ON obj.object_id = col.object_id
WHERE
 -- U = テーブル (ユーザー定義) 
 obj.type = 'U'
ORDER BY
 obj.name
 , col.column_id

sys.columnsのcolumn_idにカラムの順番があるので、こいつでORDER BYをかけると定義順になってくれます。

で、sys.columnsはデータ型の情報をそのままでは持っていないので、sys.typesと結合してとってきます。

SELECT
 obj.name [テーブル名]
 , col.name [カラム名]
 , typ.name [型名]
 , col.max_length [最大桁数]
 , col.precision [有効桁数]
 , col.scale [小数点以下桁数]
 , col.is_nullable [Null許可]
FROM
 sys.objects obj
 INNER JOIN sys.columns col
  ON obj.object_id = col.object_id
 INNER JOIN sys.types typ
  ON col.user_type_id = typ.user_type_id
WHERE
 -- U = テーブル (ユーザー定義) 
 obj.type = 'U'
ORDER BY
 obj.name
 , col.column_id

まとめ

これで後は欲しいテーブルのあるDBでSQLを投げるだけです。

実際にはobj.nameでWHEREをかけるなどすべきでしょう。ストアドファンクション化しちゃってもいいかもしれません。

私はとりあえず次にこいつを吐き出すスクリプトを組まなきゃですね…。やれやれ。

参考