備忘録

本の中の食べ物や日々の道具などについて書いたり消したり直したり

ビューを調査する(oracle)

はじめに

 Oracleで便利なビューが沢山あると楽だけど、謎のノウハウやら得体の知れない仕様を詰め込まれたビューを引き継いだ場合はなかなか厄介だ。
 ファンクション、プロシージャ、トリガーよりすこし癖のある調査が必要となるビューの調査方法について備忘をかねて記述しておく。
 

再確認

 バージョン管理システムにビューの最新のソースや最新のドキュメントが登録されているかを調べる。それらが見つかれば以下の作業は必要ないはず。

ビューのソースを参照

 Oracleではファンクションやプロシージャ、トリガーのソースを調べるときは「user_source」を参照すれば良い。

SELECT
    text 
FROM 
    user_source 
WHERE 
    name = "名称" 
ORDER BY
    line

 ところが「user_source」にはビューは含まれていない。ビューの情報を持っているテーブル「user_views」を参照する必要がある。

SELECT
    text
FROM
    user_views
WHERE
    view_name = "名称" 

依存関係

 沢山のビューの中から、特定のオブジェクトを参照しているビューを洗い出すには「user_dependencies」を調査するほうが「user_views」の中身を見ていくより速い。

SELECT
    name,
    referenced_type,
    referenced_name
FROM
    user_dependencies
WHERE
    type = 'VIEW'
AND
    referenced_name = "参照されているオブジェクトの名称"

マジックナンバーの埋め込みを調査するには?

 マジックナンバー使ったり、さらにDECODEで条件分岐などのロジックを埋め込んでいるようなオブジェクトを洗い出す必要がある場合にはどうするか。

 ビュー以外の場合は以下の方法で検索できるが

SELECT
    name,
    line,
    text
FROM
    user_source
WHERE
    text like "%マジックナンバー%"
ORDER BY
    line

 ところが調査対象であるビューのソースを保持している項目「user_views.text」の属性は「LONG型」だ。
 これは最大長の大きいVARCHAR2型みたいなものだけど、where句で使えない制約付の型なので「user_source.text」を検索する場合のような扱いは出来ない。

 どうするかというと簡単なスクリプトを作成して調査する。
 以下の例はrubyアドホックに作ってみたスクリプトだ。

 #!/usr/bin/env ruby
 require 'oci8'
 oracle = OCI8.new('ユーザID', 'パスワード', 'データベース名称')
 oracle.exec("select view_name,text from user_views") {|view_name,text|
    text.split("\n").each { |line|
        if ARGV.length != 0 then
            ARGV.each{ |magic_no|
                if (line.index(magic_no) != nil) then
                    puts "\""+ view_name + "\",\"" +  line.chomp + "\"\n";
                end
            }
        end
    }
 }

 やっていることは単純で、

  1. 全ビューを検索対象として
  2. ソースを改行コード毎に調査
  3. それが引数で渡したマジックナンバーにマッチするかを調べる
  4. 該当した場合はビュー名称と該当ソースを出力する

ことくらい。

これを適当な名称をつけて

>スクリプト名 マジックナンバー

で実行すれば、マジックナンバーを利用しているビューのリストが取得できる。
 マジックナンバー利用はあまり有益じゃないのでリファクタリング可能ならしておくこと。

おわりに

 調査後ソースをバージョン管理するなりドキュメントを整理してプロジェクト内でも管理体制を周知しておくと、後々引き継ぎした人が助かるだろう。