Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

RDB上の任意のテーブルのレコード群の文字列を取得してテキストファイル化したものをWinMergeU.exeで差異を取る

More than 1 year has passed since last update.

1.WinMergeU.exeをコマンドラインで実行する

diff.bat
set PATH=%PATH%;C:\Program Files\WinMerge
WinMergeU.exe a.txt b.txt /x

・WindowsPCでBatファイルを用意して、DOSコマンドでWinMergeU.exeを起動して2ファイル(a.txtとb.txt)を比較する
/x を付けると、差異がなく同一の場合は、WinMergeU.exeを閉じるような設定が可能

2.python(pandas)で最寄りのRDBのレコードを取得してファイル生成する

test.py
import os
import pandas as pd
import sqlalchemy
from sqlalchemy import create_engine

#DB接続設定文字列
CONNECT_INFO = 'mssql+pyodbc://hogehoge'   #odbc名を指定
engine = sqlalchemy.create_engine(CONNECT_INFO, encoding='utf-8')

# 引数設定
prm = 1234

# クエリー文字列生成
qy = "SELECT RecID,fld1,fld2,fld3"
qy = qy  + " FROM [dbo].[hogehogeTBL]"
qy = qy  + " WHERE invalid <> 0 AND RecID = " + str(prm)

# DB接続→データ取得
df = pd.read_sql_query(qy , engine)

# dfオブジェクトの準備
df1 = df.head(1)  #最初のレコード
df1 = df1.apply(lambda x: x + '\n')
df2 = df.tail(1)  #最後のレコード
df2 = df2.apply(lambda x: x + '\n')

# テキストファイルの生成
df1.to_csv("a.txt",index= False , header=False)
df2.to_csv("b.txt",index= False , header=False)
print(df1)
print(df2)

# WinMergeの起動
os.system("diff.bat")


・上記では、例えばRDBにログテーブルみたいなものがあって、最初のレコードと最後のレコードの差異を比較したい場合などを想定。
・pandasのto_sql_query()でRDBに接続して、任意のデータベースの任意のテーブルを検索し、データを取得する
・RDBに接続するのは、ODBC(pyodbcとSQLAlchemy)を活用する。
・接続先の設定等は、ODBCアドミニストレータで設定(上記ではODBC名「hogehoge」)
・RDBに接続して取得したデータから、pandasデータフレームオブジェクトを生成
・pandasのhead()関数とtail()関数で、先頭行と末尾行のオブジェクトを生成(これを差異としてWinmergeに食わせたい!)
・Winmergeで差異を比較するために、テキストファイルを生成。pandasのto_csv()を利用する。
・pandasの*to_csv()の引数の指定で、「Index列は吐き出し不要」、「ヘッダー行も吐き出し不要」とする
apply関数で無名関数lambda()を記述して、各列の文字列のお尻に改行コードを挿入している。(←WinMergeで見やすくするため)
・osモジュールで、WinMerge.exeをDosコマンドで起動する
・WinMerge.exeを起動するために環境変数のPATH設定が必要。BATファイル内でSET PATHを実行してからWinMergeU.exeを起動している

3.補足

・pythonにdiffを取るモジュール等が用意されているが、イマイチだった?ので、WinMergeU.exeをpythonで制御する方向性で考察。
・WinMergeU.Exeの差異が色で一目で判定できるようなGUI画面で観察したかった。

・はじめRDB内のテーブルのレコード群をWinMergeU.exeに手動で1個1個コピペして差分を見てたのが、100件ほど手動で「コピペ→差分確認」を繰り返して、だんだん腕が痛くなってきたorかったるくなってきたので、一連の作業の自動化を試みた次第。

4.追記 <2019.06.12 add>

test2.py
import os
import pandas as pd
import sqlalchemy
from sqlalchemy import create_engine

#DB接続設定文字列
CONNECT_INFO = 'mssql+pyodbc://hogehoge'  
engine = sqlalchemy.create_engine(CONNECT_INFO, encoding='utf-8')

def test(prm):

    #print(str(prm))

    # クエリー文字列生成
    qy = "SELECT RecID,fld1,fld2,fld3"
    qy = qy  + " FROM [dbo].[hogehogeTBL]"
    qy = qy  + " WHERE invalid <> 0 AND RecID = " + str(prm)

    # dfオブジェクトの準備
    df = pd.read_sql_query(qy , engine)
    df1 = df.head(1)  #最初のレコード
    df1 = df1.apply(lambda x: x + '\n')
    df2 = df.tail(1)  #最後のレコード
    df2 = df2.apply(lambda x: x + '\n')

    # テキストファイルの生成
    df1.to_csv("a.txt",index= False , header=False)
    df2.to_csv("b.txt",index= False , header=False)

    # WinMergeの起動
    os.system("diff.bat")

# 一覧の取得
prm = 9876    

qy = "SELECT top 20 RecID FROM [dbo].[fugafugaTBL]"
qy = qy  + " WHERE invalid <> 0 AND RecID > " + str(prm)    
qy = qy  + " ORDER BY RecID" 

df2 = pd.read_sql_query(qy , engine)
lst =  df2.iloc[:,0].values.tolist()
print(lst)

# 連続実行
x = [test(i) for i in lst]

print("finish")

・WinMergeU.exeで差異を取る一覧リストも、RDBを検索してリスト化するように変更した
・リスト化したものをループ処理で引数を逐次していして連続実行できるように修正

Fortinbras
Go, bid the soldiers shoot.
https://connpass.com/user/fortinbras/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away