オブジェクトの一覧を取得し、差分を出力するツール

この記事ではオブジェクトの一覧を取得し、差分を出力するツールについて解説します。

 ツールの概要

Oracle Databaseのテーブル、ビュー、インデックスの情報を取得し、初期状態と変更後の差分を比較するシェルスクリプトです。

接続したユーザのスキーマオブジェクト情報が出力され、チェックされます。

テーブルの追加などを実施した際に、きちんと追加されているか、ほかに差分が発生していないかを確認するためのツールになります。

他のオブジェクト情報などを取得したい場合にもSQLの定義を追加することによって対応することができます。


 ファイル構成

以下のようなファイル構成になります。

[oracle@localhost tools]$ ll
合計 12
drwxrwxr-x. 2 oracle oracle    6  7月 12 05:28 after
-rwxr-xr-x. 1 oracle oracle 2238  7月 12 05:28 check_diff.sh
-rwxr-xr-x. 1 oracle oracle 1844  7月 12 05:27 check_object.sh
drwxrwxr-x. 2 oracle oracle    6  7月 12 06:00 initial
-rw-rw-r--. 1 oracle oracle  739  7月 12 06:00 sql.conf

・sql.conf: SQLクエリとオブジェクトタイプの定義を含む設定ファイル

・check_object.sh: Oracleデータベースからオブジェクト情報を取得するスクリプト

・check_diff.sh: 初期状態と変更後の差分を比較するスクリプト

・after: 変更後のオブジェクト情報が格納されるディレクトリ

・initial: 初期状態のオブジェクト情報が格納されるディレクトリ


 シェルスクリプト

シェルスクリプト、設定ファイルの内容は以下の通りです。

#!/bin/bash
  
# 設定ファイルの読み込み
source sql.conf

# Oracleの接続情報を対話式で入力
read -p "Oracleユーザー名を入力してください: " ORACLE_USER
read -sp "Oracleパスワードを入力してください: " ORACLE_PASSWORD
echo
read -p "Oracleネットサービス名を入力してください: " ORACLE_NAME
echo "変更前は「1」を変更後は「2」を入力してください"
read input

# 引数チェック
if [ "$input" = "1" ]; then
    echo "1: 初期状態の情報を取得します"
    STATUS="initial"
elif [ "$input" = "2" ]; then
    echo "2: 変更後の情報を取得します"
    STATUS="after"
else
    echo "不正な入力です。1 または 2 を入力してください。"
    exit 1
fi

# データベースから情報を取得する関数
function fetch_data() {
    local sql_query=$1
    local output_file=$2
    local temp_output_file="${output_file}.tmp"
    sqlplus -s "${ORACLE_USER}/${ORACLE_PASSWORD}@${ORACLE_NAME}" <<EOF > ${temp_output_file}
WHENEVER SQLERROR EXIT SQL.SQLCODE
SET PAGESIZE 50000
SET LINESIZE 200
SET FEEDBACK OFF
SET ECHO OFF
SET MARKUP CSV ON
${sql_query}
EXIT
EOF

        # エラーが発生したか確認
    if [ $? -ne 0 ]; then
        echo "Error: SQL*Plusの実行に失敗しました SQLクエリ、接続情報を確認してください"
        cat ${temp_output_file}
        rm ${temp_output_file}
        exit 1
    else
        mv ${temp_output_file} ${output_file}
        echo "情報が ${output_file} に出力されました。"
    fi
}
# 配列の長さを取得
length=${#OBJECT_TYPES[@]}
# 繰り返し処理で情報を取得
for ((i = 0; i < length; i++)); do
    object_type=${OBJECT_TYPES[$i]}
    sql_query=${SQL_QUERIES[$i]}
    fetch_data "${sql_query}" "${STATUS}/${object_type}_${STATUS}.txt"
done


#!/bin/bash
  
# 設定ファイルの読み込み
source sql.conf

# 差分出力ファイル
FORMATTED_DIFF_FILE="object_diff.txt"

# 差分があるかどうかを確認するフラグ
has_diff=false

# 各オブジェクトタイプの差分を比較
for ((i = 0; i < ${#OBJECT_TYPES[@]}; i++)); do
    object_type=${OBJECT_TYPES[$i]}
    initial_file="initial/${object_type}_initial.txt"
    after_file="after/${object_type}_after.txt"
    diff_file="${object_type}_diff.txt"

    # ファイルが存在するか確認
    if [ ! -f ${initial_file} ]; then
        echo "Error: Initial file ${initial_file} が存在しません"
        exit 1
    fi
    if [ ! -f ${after_file} ]; then
        echo "Error: After file ${after_file} が存在しません"
        exit 1
    fi

        # 差分を比較して出力
    diff ${initial_file} ${after_file} > ${diff_file}

    # 差分がある場合、フラグを立てる
    if [ -s ${diff_file} ]; then
        has_diff=true
    fi
done

# フォーマットされた差分出力ファイルを作成
if [ "${has_diff}" = true ]; then
    {
        for ((i = 0; i < ${#OBJECT_TYPES[@]}; i++)); do
            object_type=${OBJECT_TYPES[$i]}
            diff_file="${object_type}_diff.txt"
            echo "${object_type^}の差分:"
            echo "${selected_elements[$i]}:"
            echo "-----------------------------"
            if [ -s ${diff_file} ]; then
                while IFS= read -r line; do
                    if [[ $line =~ ^\< ]]; then
                        echo "削除: ${line:2}"
                    elif [[ $line =~ ^\> ]]; then
                        echo "追加: ${line:2}"
                    fi
                done < ${diff_file}
            else
                echo "差分なし"
            fi
            echo
        done
    } > ${FORMATTED_DIFF_FILE}
    echo "初期状態と変更後のフォーマットされた差分が ${FORMATTED_DIFF_FILE} に出力されました。"
else
    echo "差分はありません。"
fi

# 差分ファイルを削除
for ((i = 0; i < ${#OBJECT_TYPES[@]}; i++)); do
    object_type=${OBJECT_TYPES[$i]}
    diff_file="${object_type}_diff.txt"
    rm ${diff_file}
done

#!/bin/bash
# SQLクエリの定義
TABLE_SQL="SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME;" VIEW_SQL="SELECT VIEW_NAME FROM USER_VIEWS ORDER BY VIEW_NAME;" INDEX_SQL="SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME, COLUMN_POSITION FROM USER_IND_COLUMNS ORDER BY TABLE_NAME, INDEX_NAME, COLUMN_POSITION;" # 配列の定義 OBJECT_TYPES=("table" "view" "index") SQL_QUERIES=("${TABLE_SQL}" "${VIEW_SQL}" "${INDEX_SQL}") # 配列を走査してSELECTとFROMの間の要素を抽出し、別の配列に格納 for query in "${SQL_QUERIES[@]}"; do     # 正規表現を使ってSELECTとFROMの間の文字列を抽出     if [[ "$query" =~ SELECT\ (.*)\ FROM ]]; then         selected_elements+=("${BASH_REMATCH[1]}")     fi done

 使用方法

①初期状態の情報を取得

初期状態のデータベース情報を取得します。

check_object.shを実行します。

出力メッセージに合わせて、Oracleのユーザー名、パスワード、および接続識別子を入力します。

初期状態の情報を取得するのでパラメータは「1」を入力します。

[oracle@localhost tools]$ ./check_object.sh 
Oracleユーザー名を入力してください: test
Oracleパスワードを入力してください: 
Oracleネットサービス名を入力してください: pdb2
変更前は「1」を変更後は「2」を入力してください
1
1: 初期状態の情報を取得します
情報が initial/table_initial.txt に出力されました。
情報が initial/view_initial.txt に出力されました。
情報が initial/index_initial.txt に出力されました。

②変更後の情報を取得

変更後のデータベース情報を取得します。

今回の例では新規に「TEST」テーブルを作成した状態で実行します。

check_object.shを再度実行します。

出力メッセージに合わせて、Oracleのユーザー名、パスワード、および接続識別子を入力します。

変更後の情報を取得するのでパラメータは「2」を入力します。

[oracle@localhost tools]$ ./check_object.sh 
Oracleユーザー名を入力してください: test
Oracleパスワードを入力してください: 
Oracleネットサービス名を入力してください: pdb2
変更前は「1」を変更後は「2」を入力してください
2
2: 変更後の情報を取得します
情報が after/table_after.txt に出力されました。
情報が after/view_after.txt に出力されました。
情報が after/index_after.txt に出力されました。


③差分の比較

初期状態と変更後のデータベース情報を比較します。check_diff.shを実行します。

差分がある場合、object_diff.txtファイルが生成されます。

このファイルには、初期状態と変更後のデータベースの差分が記録されています。

[oracle@localhost tools]$ ./check_diff.sh 
初期状態と変更後のフォーマットされた差分が object_diff.txt に出力されました。
[oracle@localhost tools]$ cat object_diff.txt 
Tableの差分:
TABLE_NAME:
-----------------------------
追加: "TEST"

Viewの差分:
VIEW_NAME:
-----------------------------
差分なし

Indexの差分:
INDEX_NAME, TABLE_NAME, COLUMN_NAME, COLUMN_POSITION:
-----------------------------
差分なし
出力結果を確認すると「TEST」表の追加があり、ほかは差分がないことが確認できました。