この記事ではオブジェクトの一覧を取得し、差分を出力するツールについて解説します。
ツールの概要
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:
-----------------------------
差分なし