素のテキストファイルである.datファイルは、いろいろな目的に簡単に使い回せるので便利ですが、SQL文を使ってデータを操作したい場合がないこともありません。
そのような場合、最近では無料で使える本格的なRDBMSもあるので、性能的にはそれらを使うといいのでしょうが、個人用途で使うには複雑で管理が面倒な上、少々オーバースペックな気もします。
そこで、手軽なDBMSとして「SQLite」を使い、.datファイルからSQLiteのデータベースを構築する、「DataLab_SQLite.rb」スクリプトを作ってみました。
SQLiteは、アプリケーション組み込み型の軽量DBMSです。一般的なRDBMSはクライアント サーバ モデルで動作しますが、SQLiteはアプリケーションからライブラリとして呼び出されます。
インストールは、「sqlite3.dll」ファイルを、実行時にアクセスできるフォルダにコピーするだけです。
また、ユーザー管理だのパスワードだのといった面倒なこともなく、データ ファイルとしてファイルが1つ出来るだけなので、管理も楽です。
執筆時点では、SQLite3 3.6.6.2を使っています。
※データ種別ID「RACE」「DIFF」「BLOD」「SLOP」「YSCH」でダウンロードできるレコードをすべて格納した場合、データベースのファイルサイズは、3GB近くになります。SQLiteで管理するのにはあまり向いていない用途かもしれません。
SQLiteをRubyで使うには、SQLite3/Rubyをインストールするのが簡単です。
SQLite3/RubyはRubyGemsで簡単にインストールできます。
執筆時点におけるSQLite3/Rubyの最新版は1.2.4ですが、このバージョンでの変更点はWindowsなどのバイナリ ビルドに影響がなく、Windows向けのパッケージもないようです。
そのため、RubyGemsを使って普通にSQLite3/Rubyをインストールしようとすると、エラーになりました。そこで、ここでは1つ前の1.2.3をインストールしています。
RubyGemsで特定のバージョンをインストールするには、次のように「-v」オプションを使います。
>gem install sqlite3-ruby -v 1.2.3
RubyGemsでインストールしたライブラリがスクリプトから見付からない場合は、スクリプトのはじめに「require 'rubygems'」を記述するか、環境変数RUBYOPTに -rubygems を追加します。
このスクリプトは、データベースに、DataLab.のデータをすべて格納しています。検索用のキーと作成日時、.datファイル上の位置だけを格納するようにすれば、データベースのサイズは小さくなり、構築速度も速くなるのでしょうが、SQLiteだけで処理ができることを優先して、このような構成になっています。
「DataLab.sqlite」ファイルの具体的なテーブル構成は、「SQLite_table.pdf」を参照してください。
これ以外に、「WRITE_COUNT」テーブルがありますが、このテーブルはスクリプト内で使っています。
「.dat」ファイル上の1レコードが、複数テーブルの複数レコードに分割して格納されている場合があります。
たとえば、競走馬マスタ「UM.dat」のデータは、「UM」テーブルと「UM_18」テーブルに分割して格納されています。
競走馬マスタの項番「18」には「3代血統情報」として、「父・母・父父…」など14のデータが繰り返し格納されています。そのため、次のように項番「18」だけを別テーブルに分離しています。
「UM_18」は「UM」の「ROWID」値と、データの格納順を表わす「NUM」値がプライマリキーになっています。「ROWID」は、SQLiteのテーブルに必ず存在する、レコードごとに一意の数値です。
テーブルによっては「NUM」値ではなく、他のデータをプライマリキーにしている場合もあります。

「DataLab.sqlite」ファイルに含まれるテーブルの構成は、次のような規則になっています。
「DataLab.sqlite」ファイルは、
などを使ってアクセスできます。
たとえば、RでRSQLiteを使って、2008年1月に行なわれたレースの情報(プライマリキー(4〜9)、距離(34)、トラックコード(36)、コース区分(38)、競争名(12)、データ区分(2))を取得するコード例は、次のようになります。(RSQLiteはすでにインストールされているとします)。
> library(RSQLite)
> drv <- dbDriver("SQLite")
> con <- dbConnect(drv, dbname="Download/DataLab.sqlite")
> df200801 <- dbGetQuery(con, 'select "4", "5",
"6", "7", "8", "9", "34",
"36", "38", "12", "2" from "RA"
where "4" = "2008" AND "5" like "01%";')
> dbDisconnect(con)
同じことをTkSQLiteで行なうと、次のようになります。
データの文字コードをシフトJISのまま格納しているので、TkSQLiteの文字コードをシフトJISにしないと(「データベース」→「文字コード」→「shiftjis」メニューを選択)、文字化けします。

このスクリプトには、ちょっとした問題があります。
【参考】DataLab.の払戻データ(blog)
#JRA-VANからダウンロードしたデータを格納する、SQLite3のデータベース ファイルを作る
#require 'rubygems' #RubyGemsを使ってSQLite3/Rubyをインストールしている場合
#または、環境変数RUBYOPTに -rubygems を追加
#sqliteをロードする
require 'sqlite3'
#データベース"DataLab.sqlite"を作成する
# * ファイルがすでに存在するときはファイルを開く。
# * ファイルがないときは新しいデータベースを作成する。
db = SQLite3::Database.new('Download/DataLab.sqlite')
#テーブルの構造
table = Hash.new
#キー:DataLabのレコードID
#値:テーブルの構造:[更新日付の位置, 第1テーブルの構造, [第2テーブルの構造, ...]]
# 更新日付の位置:[位置, 長さ]
# 第1テーブルの構造:[テーブル情報, [プライマリキーのカラム, ...],[その他のカラム, ...]]
# 第2テーブルの構造:[テーブル情報, 有効性判定, [プライマリキーのカラム, ...],[その他のカラム, ...]]
# テーブル情報:[テーブル名, 繰り返し回数]
# カラムの構造:[カラム名, 位置, ステップ長, 長さ]
# 有効性判定:[位置, ステップ長, 長さ, 判定文字]
#1.特別登録馬
table["TK"] = [[4-1,8],[["TK",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,1],["11",29-1,0,4],["12",33-1,0,60],["13",93-1,0,60],["14",153-1,0,60],["15",213-1,0,120],["16",333-1,0,120],["17",453-1,0,120],["18",573-1,0,20],["19",593-1,0,12],["20",605-1,0,6],["21",611-1,0,1],["22",612-1,0,3],["23",615-1,0,1],["24",616-1,0,2],["25",618-1,0,3],["26",621-1,0,1],["27",622-1,0,3],["28",625-1,0,3],["29",628-1,0,3],["30",631-1,0,3],["31",634-1,0,3],["32",637-1,0,4],["33",641-1,0,2],["34",643-1,0,2],["35",645-1,0,8],["36",653-1,0,3]]],[[["TK_37",300],[656-1+( 1)-1,70,3,"0"],[["ID",0,0,0],["a",656-1+( 1)-1,70,3]],[["b",656-1+( 4)-1,70,10],["c",656-1+( 14)-1,70,36],["d",656-1+( 50)-1,70,2],["e",656-1+( 52)-1,70,1],["f",656-1+( 53)-1,70,1],["g",656-1+( 54)-1,70,5],["h",656-1+( 59)-1,70,8],["i",656-1+( 67)-1,70,3],["j",656-1+( 70)-1,70,1]]]]]
#2.レース詳細
table["RA"] = [[4-1,8],[["RA",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,1],["11",29-1,0,4],["12",33-1,0,60],["13",93-1,0,60],["14",153-1,0,60],["15",213-1,0,120],["16",333-1,0,120],["17",453-1,0,120],["18",573-1,0,20],["19",593-1,0,12],["20",605-1,0,6],["21",611-1,0,1],["22",612-1,0,3],["23",615-1,0,1],["24",616-1,0,1],["25",617-1,0,2],["26",619-1,0,3],["27",622-1,0,1],["28",623-1,0,3],["29",626-1,0,3],["30",629-1,0,3],["31",632-1,0,3],["32",635-1,0,3],["33",638-1,0,60],["34",698-1,0,4],["35",702-1,0,4],["36",706-1,0,2],["37",708-1,0,2],["38",710-1,0,2],["39",712-1,0,2],["40",714-1,0,7*8],["41",770-1,0,5*8],["42",810-1,0,5*8],["43",850-1,0,3*8],["44",874-1,0,4],["45",878-1,0,4],["46",882-1,0,2],["47",884-1,0,2],["48",886-1,0,2],["49",888-1,0,1],["50",889-1,0,1],["51",890-1,0,1],["52",891-1,0,25*3],["53",966-1,0,4],["54",970-1,0,3],["55",973-1,0,3],["56",976-1,0,3],["57",979-1,0,3],["58_1",982-1,0,72],["58_2",982-1+72,0,72],["58_3",982-1+72*2,0,72],["58_4",982-1+72*3,0,72],["59",1270-1,0,1]]],[]]
#3.馬毎レース情報
table["SE"] = [[4-1,8],[["SE",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2],["12",31-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,1],["11",29-1,0,2],["13",41-1,0,36],["14",77-1,0,2],["15",79-1,0,1],["16",80-1,0,1],["17",81-1,0,2],["18",83-1,0,2],["19",85-1,0,1],["20",86-1,0,5],["21",91-1,0,8],["22",99-1,0,6],["23",105-1,0,64],["24",169-1,0,60],["25",229-1,0,60],["26",289-1,0,3],["27",292-1,0,3],["28",295-1,0,1],["29",296-1,0,1],["30",297-1,0,5],["31",302-1,0,5],["32",307-1,0,8],["33",315-1,0,8],["34",323-1,0,1],["35",324-1,0,1],["36",325-1,0,3],["37",328-1,0,1],["38",329-1,0,3],["39",332-1,0,1],["40",333-1,0,2],["41",335-1,0,2],["42",337-1,0,1],["43",338-1,0,1],["44",339-1,0,4],["45",343-1,0,3],["46",346-1,0,3],["47",349-1,0,3],["48",352-1,0,2],["49",354-1,0,2],["50",356-1,0,2],["51",358-1,0,2],["52",360-1,0,4],["53",364-1,0,2],["54",366-1,0,8],["55",374-1,0,8],["56",382-1,0,3],["57",385-1,0,3],["58",388-1,0,3],["59",391-1,0,3],["61",532-1,0,4],["62",536-1,0,1],["63",537-1,0,1],["64",538-1,0,5],["65",543-1,0,4],["66",547-1,0,4],["67",551-1,0,2],["68",553-1,0,1]]],[[["SE_60",3],[394-1+( 1)-1,46,10,"0"],[["ID",0,0,0],["a",394-1+( 1)-1,46,10]],[["b",394-1+( 11)-1,46,36]]]]]
#4.払戻
table["HR"] = [[4-1,8],[["HR",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,2],["11",30-1,0,2],["12",32-1,0,1],["13",33-1,0,1],["14",34-1,0,1],["15",35-1,0,1],["16",36-1,0,1],["17",37-1,0,1],["18",38-1,0,1],["19",39-1,0,1],["20",40-1,0,1],["21",41-1,0,1],["22",42-1,0,1],["23",43-1,0,1],["24",44-1,0,1],["25",45-1,0,1],["26",46-1,0,1],["27",47-1,0,1],["28",48-1,0,1],["29",49-1,0,1],["30",50-1,0,1],["31",51-1,0,1],["32",52-1,0,1],["33",53-1,0,1],["34",54-1,0,1],["35",55-1,0,1],["36",56-1,0,1],["37",57-1,0,1],["38",58-1,0,1],["39",59-1,0,28*1],["40",87-1,0,8*1],["41",95-1,0,8*1]]],[[["HR_42",3],[103-1+( 3)-1,13,9," "],[["ID",0,0,0],["a",103-1+( 1)-1,13,2]],[["b",103-1+( 3)-1,13,9],["c",103-1+( 12)-1,13,2]]],[["HR_43",5],[142-1+( 3)-1,13,9," "],[["ID",0,0,0],["a",142-1+( 1)-1,13,2]],[["b",142-1+( 3)-1,13,9],["c",142-1+( 12)-1,13,2]]],[["HR_44",3],[207-1+( 3)-1,13,9," "],[["ID",0,0,0],["a",207-1+( 1)-1,13,2]],[["b",207-1+( 3)-1,13,9],["c",207-1+( 12)-1,13,2]]],[["HR_45",3],[246-1+( 5)-1,16,9," "],[["ID",0,0,0],["a",246-1+( 1)-1,16,4]],[["b",246-1+( 5)-1,16,9],["c",246-1+( 14)-1,16,3]]],[["HR_46",7],[294-1+( 5)-1,16,9," "],[["ID",0,0,0],["a",294-1+( 1)-1,16,4]],[["b",294-1+( 5)-1,16,9],["c",294-1+( 14)-1,16,3]]],[["HR_47",3],[406-1+( 5)-1,16,9," "],[["ID",0,0,0],["a",406-1+( 1)-1,16,4]],[["b",406-1+( 5)-1,16,9],["c",406-1+( 14)-1,16,3]]],[["HR_48",6],[454-1+( 5)-1,16,9," "],[["ID",0,0,0],["a",454-1+( 1)-1,16,4]],[["b",454-1+( 5)-1,16,9],["c",454-1+( 14)-1,16,3]]],[["HR_49",3],[550-1+( 7)-1,18,9," "],[["ID",0,0,0],["a",550-1+( 1)-1,18,6]],[["b",550-1+( 7)-1,18,9],["c",550-1+( 16)-1,18,3]]],[["HR_50",6],[604-1+( 7)-1,19,9," "],[["ID",0,0,0],["a",604-1+( 1)-1,19,6]],[["b",604-1+( 7)-1,19,9],["c",604-1+( 16)-1,19,4]]]]]
#5.票数1
table["H1"] = [[4-1,8],[["H1",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,2],["11",30-1,0,2],["12",32-1,0,1],["13",33-1,0,1],["14",34-1,0,1],["15",35-1,0,1],["16",36-1,0,1],["17",37-1,0,1],["18",38-1,0,1],["19",39-1,0,1],["20",40-1,28,1],["21",68-1,8,1],["22",76-1,8,1],["30",28800-1,0,11],["31",28811-1,0,11],["32",28822-1,0,11],["33",28833-1,0,11],["34",28844-1,0,11],["35",28855-1,0,11],["36",28866-1,0,11],["37",28877-1,0,11],["38",28888-1,0,11],["39",28899-1,0,11],["40",28910-1,0,11],["41",28921-1,0,11],["42",28932-1,0,11],["43",28943-1,0,11]]],[[["H1_23",28],[84-1+( 1)-1,15,2," "],[["ID",0,0,0],["a",84-1+( 1)-1,15,2]],[["b",84-1+( 3)-1,15,11],["c",84-1+( 14)-1,15,2]]],[["H1_24",28],[504-1+( 1)-1,15,2," "],[["ID",0,0,0],["a",504-1+( 1)-1,15,2]],[["b",504-1+( 3)-1,15,11],["c",504-1+( 14)-1,15,2]]],[["H1_25",36],[924-1+( 1)-1,15,2," "],[["ID",0,0,0],["a",924-1+( 1)-1,15,2]],[["b",924-1+( 3)-1,15,11],["c",924-1+( 14)-1,15,2]]],[["H1_26",153],[1464-1+( 1)-1,18,4," "],[["ID",0,0,0],["a",1464-1+( 1)-1,18,4]],[["b",1464-1+( 5)-1,18,11],["c",1464-1+( 16)-1,18,3]]],[["H1_27",153],[4218-1+( 1)-1,18,4," "],[["ID",0,0,0],["a",4218-1+( 1)-1,18,4]],[["b",4218-1+( 5)-1,18,11],["c",4218-1+( 16)-1,18,3]]],[["H1_28",306],[6972-1+( 1)-1,18,4," "],[["ID",0,0,0],["a",6972-1+( 1)-1,18,4]],[["b",6972-1+( 5)-1,18,11],["c",6972-1+( 16)-1,18,3]]],[["H1_29",816],[12480-1+( 1)-1,20,6," "],[["ID",0,0,0],["a",12480-1+( 1)-1,20,6]],[["b",12480-1+( 7)-1,20,11],["c",12480-1+( 18)-1,20,3]]]]]
#6.票数6(3連単)
table["H6"] = [[4-1,8],[["H6",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,2],["11",30-1,0,2],["12",32-1,0,1],["13",33-1,0,18*1],["15",102867-1,0,11],["16",102878-1,0,11]]],[[["H6_14",4896],[51-1+( 1)-1,21,6," "],[["ID",0,0,0],["a",51-1+( 1)-1,21,6]],[["b",51-1+( 7)-1,21,11],["c",51-1+( 18)-1,21,4]]]]]
#7.オッズ1(単複枠)
table["O1"] = [[4-1,8],[["O1",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["14",41-1,0,1],["15",42-1,0,1],["16",43-1,0,1],["20",928-1,0,11],["21",939-1,0,11],["22",950-1,0,11]]],[[["O1_17",28],[44-1+( 1)-1,8,2," "],[["ID",0,0,0],["a",44-1+( 1)-1,8,2]],[["b",44-1+( 3)-1,8,4],["c",44-1+( 7)-1,8,2]]],[["O1_18",28],[268-1+( 1)-1,12,2," "],[["ID",0,0,0],["a",268-1+( 1)-1,12,2]],[["b",268-1+( 3)-1,12,4],["c",268-1+( 7)-1,12,4],["d",268-1+( 11)-1,12,2]]],[["O1_19",36],[604-1+( 1)-1,9,2," "],[["ID",0,0,0],["a",604-1+( 1)-1,9,2]],[["b",604-1+( 3)-1,9,5],["c",604-1+( 8)-1,9,2]]]]]
#8.オッズ2(馬連)
table["O2"] = [[4-1,8],[["O2",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["15",2030-1,0,11]]],[[["O2_14",153],[41-1+( 1)-1,13,4," "],[["ID",0,0,0],["a",41-1+( 1)-1,13,4]],[["b",41-1+( 5)-1,13,6],["c",41-1+( 11)-1,13,3]]]]]
#9.オッズ3(ワイド)
table["O3"] = [[4-1,8],[["O3",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["15",2642-1,0,11]]],[[["O3_14",153],[41-1+( 1)-1,17,4," "],[["ID",0,0,0],["a",41-1+( 1)-1,17,4]],[["b",41-1+( 5)-1,17,5],["c",41-1+( 10)-1,17,5],["d",41-1+( 15)-1,17,3]]]]]
#10.オッズ4(馬単)
table["O4"] = [[4-1,8],[["O4",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["15",4019-1,0,11]]],[[["O4_14",306],[41-1+( 1)-1,13,4," "],[["ID",0,0,0],["a",41-1+( 1)-1,13,4]],[["b",41-1+( 5)-1,13,6],["c",41-1+( 11)-1,13,3]]]]]
#11.オッズ5(3連複)
table["O5"] = [[4-1,8],[["O5",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["15",12281-1,0,11]]],[[["O5_14",816],[41-1+( 1)-1,15,6," "],[["ID",0,0,0],["a",41-1+( 1)-1,15,6]],[["b",41-1+( 7)-1,15,6],["c",41-1+( 13)-1,15,3]]]]]
#12.オッズ6(3連単)
table["O6"] = [[4-1,8],[["O6",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,2],["12",38-1,0,2],["13",40-1,0,1],["15",83273-1,0,11]]],[[["O6_14",4896],[41-1+( 1)-1,17,6," "],[["ID",0,0,0],["a",41-1+( 1)-1,17,6]],[["b",41-1+( 7)-1,17,7],["c",41-1+( 14)-1,17,4]]]]]
#13.競走馬マスタ
table["UM"] = [[4-1,8],[["UM",0],[["4",12-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["5",22-1,0,1],["6",23-1,0,8],["7",31-1,0,8],["8",39-1,0,8],["9",47-1,0,36],["10",83-1,0,36],["11",119-1,0,60],["12",179-1,0,1],["13",180-1,0,19],["14",199-1,0,2],["15",201-1,0,1],["16",202-1,0,1],["17",203-1,0,2],["19",821-1,0,1],["20",822-1,0,5],["21",827-1,0,8],["22",835-1,0,20],["23",855-1,0,6],["24",861-1,0,70],["25",931-1,0,20],["26",951-1,0,6],["27",957-1,0,64],["28",1021-1,0,9],["29",1030-1,0,9],["30",1039-1,0,9],["31",1048-1,0,9],["32",1057-1,0,9],["33",1066-1,0,9],["34",1075-1,0,6*3],["35",1093-1,0,6*3],["36",1111-1,0,6*3],["37",1129-1,0,6*3],["38",1147-1,0,6*3],["39",1165-1,0,6*3],["40",1183-1,0,6*3],["41",1201-1,0,6*3],["42",1219-1,0,6*3],["43",1237-1,0,6*3],["44",1255-1,0,6*3],["45",1273-1,0,6*3],["46",1291-1,0,6*3],["47",1309-1,0,6*3],["48",1327-1,0,6*3],["49",1345-1,0,6*3],["50",1363-1,0,6*3],["51",1381-1,0,6*3],["52",1399-1,0,6*3],["53",1417-1,0,6*3],["54",1435-1,0,6*3],["55",1453-1,0,6*3],["56",1471-1,0,6*3],["57",1489-1,0,6*3],["58",1507-1,0,6*3],["59",1525-1,0,6*3],["60",1543-1,0,6*3],["61",1561-1,0,4*3],["62",1573-1,0,3]]],[[["UM_18",14],[205-1+( 1)-1,44,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",205-1+( 1)-1,44,8],["b",205-1+( 9)-1,44,36]]]]]
#14.騎手マスタ
table["KS"] = [[4-1,8],[["KS",0],[["4",12-1,0,5]],[["2",3-1,0,1],["3",4-1,0,8],["5",17-1,0,1],["6",18-1,0,8],["7",26-1,0,8],["8",34-1,0,8],["9",42-1,0,34],["10",76-1,0,34],["11",110-1,0,30],["12",140-1,0,8],["13",148-1,0,80],["14",228-1,0,1],["15",229-1,0,1],["16",230-1,0,1],["17",231-1,0,1],["18",232-1,0,20],["19",252-1,0,5],["20",257-1,0,8]]],[[["KS_21",2],[265-1+( 1)-1,67,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",265-1+( 1)-1,67,16],["b",265-1+( 17)-1,67,2],["c",265-1+( 19)-1,67,10],["d",265-1+( 29)-1,67,36],["e",265-1+( 65)-1,67,2],["f",265-1+( 67)-1,67,1]]],[["KS_22",2],[399-1+( 1)-1,64,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",399-1+( 1)-1,64,16],["b",399-1+( 17)-1,64,2],["c",399-1+( 19)-1,64,10],["d",399-1+( 29)-1,64,36]]],[["KS_23",3],[527-1+( 1)-1,163,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",527-1+( 1)-1,163,16],["b",527-1+( 17)-1,163,60],["c",527-1+( 77)-1,163,20],["d",527-1+( 97)-1,163,12],["e",527-1+( 109)-1,163,6],["f",527-1+( 115)-1,163,1],["g",527-1+( 116)-1,163,2],["h",527-1+( 118)-1,163,10],["i",527-1+( 128)-1,163,36]]],[["KS_24",3],[1016-1+( 1)-1,1052,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",1016-1+( 1)-1,1052,4],["b",1016-1+( 5)-1,1052,10],["c",1016-1+( 15)-1,1052,10],["d",1016-1+( 25)-1,1052,10],["e",1016-1+( 35)-1,1052,10],["f",1016-1+( 45)-1,1052,6*6],["g",1016-1+( 81)-1,1052,6*6],["h",1016-1+( 117)-1,1052,6*6],["i",1016-1+( 153)-1,1052,6*6],["j",1016-1+( 189)-1,1052,6*6],["k",1016-1+( 225)-1,1052,6*6],["l",1016-1+( 261)-1,1052,6*6],["m",1016-1+( 297)-1,1052,6*6],["n",1016-1+( 333)-1,1052,6*6],["o",1016-1+( 369)-1,1052,6*6],["p",1016-1+( 405)-1,1052,6*6],["q",1016-1+( 441)-1,1052,6*6],["r",1016-1+( 477)-1,1052,6*6],["s",1016-1+( 513)-1,1052,6*6],["t",1016-1+( 549)-1,1052,6*6],["u",1016-1+( 585)-1,1052,6*6],["v",1016-1+( 621)-1,1052,6*6],["w",1016-1+( 657)-1,1052,6*6],["x",1016-1+( 693)-1,1052,6*6],["y",1016-1+( 729)-1,1052,6*6],["z",1016-1+( 765)-1,1052,6*6],["aa",1016-1+( 801)-1,1052,6*6],["ab",1016-1+( 837)-1,1052,6*6],["ac",1016-1+( 873)-1,1052,6*6],["ad",1016-1+( 909)-1,1052,6*6],["ae",1016-1+( 945)-1,1052,6*6],["af",1016-1+( 981)-1,1052,6*6],["ag",1016-1+(1017)-1,1052,6*6]]]]]
#15.調教師マスタ
table["CH"] = [[4-1,8],[["CH",0],[["4",12-1,0,5]],[["2",3-1,0,1],["3",4-1,0,8],["5",17-1,0,1],["6",18-1,0,8],["7",26-1,0,8],["8",34-1,0,8],["9",42-1,0,34],["10",76-1,0,30],["11",106-1,0,8],["12",114-1,0,80],["13",194-1,0,1],["14",195-1,0,1],["15",196-1,0,20]]],[[["CH_16",3],[216-1+( 1)-1,163,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",216-1+( 1)-1,163,16],["b",216-1+( 17)-1,163,60],["c",216-1+( 77)-1,163,20],["d",216-1+( 97)-1,163,12],["e",216-1+( 109)-1,163,6],["f",216-1+( 115)-1,163,1],["g",216-1+( 116)-1,163,2],["h",216-1+( 118)-1,163,10],["i",216-1+( 128)-1,163,36]]],[["CH_17",3],[705-1+( 1)-1,1052,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",705-1+( 1)-1,1052,4],["b",705-1+( 5)-1,1052,10],["c",705-1+( 15)-1,1052,10],["d",705-1+( 25)-1,1052,10],["e",705-1+( 35)-1,1052,10],["f",705-1+( 45)-1,1052,6*6],["g",705-1+( 81)-1,1052,6*6],["h",705-1+( 117)-1,1052,6*6],["i",705-1+( 153)-1,1052,6*6],["j",705-1+( 189)-1,1052,6*6],["k",705-1+( 225)-1,1052,6*6],["l",705-1+( 261)-1,1052,6*6],["m",705-1+( 297)-1,1052,6*6],["n",705-1+( 333)-1,1052,6*6],["o",705-1+( 369)-1,1052,6*6],["p",705-1+( 405)-1,1052,6*6],["q",705-1+( 441)-1,1052,6*6],["r",705-1+( 477)-1,1052,6*6],["s",705-1+( 513)-1,1052,6*6],["t",705-1+( 549)-1,1052,6*6],["u",705-1+( 585)-1,1052,6*6],["v",705-1+( 621)-1,1052,6*6],["w",705-1+( 657)-1,1052,6*6],["x",705-1+( 693)-1,1052,6*6],["y",705-1+( 729)-1,1052,6*6],["z",705-1+( 765)-1,1052,6*6],["aa",705-1+( 801)-1,1052,6*6],["ab",705-1+( 837)-1,1052,6*6],["ac",705-1+( 873)-1,1052,6*6],["ad",705-1+( 909)-1,1052,6*6],["ae",705-1+( 945)-1,1052,6*6],["af",705-1+( 981)-1,1052,6*6],["ag",705-1+(1017)-1,1052,6*6]]]]]
#16.生産者マスタ
table["BR"] = [[4-1,8],[["BR",0],[["4",12-1,0,6]],[["2",3-1,0,1],["3",4-1,0,8],["5",18-1,0,70],["6",88-1,0,70],["7",158-1,0,70],["8",228-1,0,168],["9",396-1,0,20]]],[[["BR_10",2],[416-1+( 1)-1,60,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",416-1+( 1)-1,60,4],["b",416-1+( 5)-1,60,10],["c",416-1+( 15)-1,60,10],["d",416-1+( 25)-1,60,6*6]]]]]
#17.馬主マスタ
table["BN"] = [[4-1,8],[["BN",0],[["4",12-1,0,6]],[["2",3-1,0,1],["3",4-1,0,8],["5",18-1,0,64],["6",82-1,0,64],["7",146-1,0,50],["8",196-1,0,100],["9",296-1,0,60]]],[[["BN_10",2],[356-1+( 1)-1,60,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",356-1+( 1)-1,60,4],["b",356-1+( 5)-1,60,10],["c",356-1+( 15)-1,60,10],["d",356-1+( 25)-1,60,6*6]]]]]
#18.繁殖馬マスタ
table["HN"] = [[4-1,8],[["HN",0],[["4",12-1,0,8]],[["2",3-1,0,1],["3",4-1,0,8],["5",20-1,0,8],["6",28-1,0,10],["7",38-1,0,1],["8",39-1,0,36],["9",75-1,0,40],["10",115-1,0,80],["11",195-1,0,4],["12",199-1,0,1],["13",200-1,0,1],["14",201-1,0,2],["15",203-1,0,1],["16",204-1,0,4],["17",208-1,0,20],["18",228-1,0,8],["19",236-1,0,8]]],[]]
#19.産駒マスタ
table["SK"] = [[4-1,8],[["SK",0],[["4",12-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["5",22-1,0,8],["6",30-1,0,1],["7",31-1,0,1],["8",32-1,0,2],["9",34-1,0,1],["10",35-1,0,4],["11",39-1,0,6],["12",45-1,0,20]]],[[["SK_13",14],[65-1,8,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["13",65-1,8,8]]]]]
#20.出走別着度数
table["CK"] = [[4-1,8],[["CK",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2],["10",28-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["11",38-1,0,36],["12",74-1,0,9],["13",83-1,0,9],["14",92-1,0,9],["15",101-1,0,9],["16",110-1,0,9],["17",119-1,0,9],["18",128-1,0,6*3],["19",146-1,0,6*3],["20",164-1,0,6*3],["21",182-1,0,6*3],["22",200-1,0,6*3],["23",218-1,0,6*3],["24",236-1,0,6*3],["25",254-1,0,6*3],["26",272-1,0,6*3],["27",290-1,0,6*3],["28",308-1,0,6*3],["29",326-1,0,6*3],["30",344-1,0,6*3],["31",362-1,0,6*3],["32",380-1,0,6*3],["33",398-1,0,6*3],["34",416-1,0,6*3],["35",434-1,0,6*3],["36",452-1,0,6*3],["37",470-1,0,6*3],["38",488-1,0,6*3],["39",506-1,0,6*3],["40",524-1,0,6*3],["41",542-1,0,6*3],["42",560-1,0,6*3],["43",578-1,0,6*3],["44",596-1,0,6*3],["45",614-1,0,6*3],["46",632-1,0,6*3],["47",650-1,0,6*3],["48",668-1,0,6*3],["49",686-1,0,6*3],["50",704-1,0,6*3],["51",722-1,0,6*3],["52",740-1,0,6*3],["53",758-1,0,6*3],["54",776-1,0,6*3],["55",794-1,0,6*3],["56",812-1,0,6*3],["57",830-1,0,6*3],["58",848-1,0,6*3],["59",866-1,0,6*3],["60",884-1,0,6*3],["61",902-1,0,6*3],["62",920-1,0,6*3],["63",938-1,0,6*3],["64",956-1,0,6*3],["65",974-1,0,6*3],["66",992-1,0,6*3],["67",1010-1,0,6*3],["68",1028-1,0,6*3],["69",1046-1,0,6*3],["70",1064-1,0,6*3],["71",1082-1,0,6*3],["72",1100-1,0,6*3],["73",1118-1,0,6*3],["74",1136-1,0,6*3],["75",1154-1,0,6*3],["76",1172-1,0,6*3],["77",1190-1,0,6*3],["78",1208-1,0,6*3],["79",1226-1,0,6*3],["80",1244-1,0,6*3],["81",1262-1,0,6*3],["82",1280-1,0,6*3],["83",1298-1,0,6*3],["84",1316-1,0,6*3],["85",1334-1,0,6*3],["86",1352-1,0,6*3],["87",1370-1,0,4*3],["88",1382-1,0,3],["89",1385-1,0,5],["90",1390-1,0,34],["92",3864-1,0,5],["93",3869-1,0,34],["95",6343-1,0,6],["96",6349-1,0,64],["97",6413-1,0,64],["98",6597-1,0,6],["99",6603-1,0,70],["100",6673-1,0,70]]],[[["CK_91",2],[1424-1+1-1,1220,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",1424-1+1-1,1220,4],["b",1424-1+5-1,1220,10],["c",1424-1+15-1,1220,10],["d",1424-1+25-1,1220,10],["e",1424-1+35-1,1220,10],["f",1424-1+45-1,1220,30],["g",1424-1+75-1,1220,30],["h",1424-1+105-1,1220,24],["i",1424-1+129-1,1220,24],["j",1424-1+153-1,1220,24],["k",1424-1+177-1,1220,24],["l",1424-1+201-1,1220,24],["m",1424-1+225-1,1220,24],["n",1424-1+249-1,1220,24],["o",1424-1+273-1,1220,24],["p",1424-1+297-1,1220,24],["q",1424-1+321-1,1220,24],["r",1424-1+345-1,1220,24],["s",1424-1+369-1,1220,24],["t",1424-1+393-1,1220,24],["u",1424-1+417-1,1220,24],["v",1424-1+441-1,1220,24],["w",1424-1+465-1,1220,24],["x",1424-1+489-1,1220,24],["y",1424-1+513-1,1220,24],["z",1424-1+537-1,1220,24],["aa",1424-1+561-1,1220,24],["ab",1424-1+585-1,1220,24],["ac",1424-1+609-1,1220,24],["ad",1424-1+633-1,1220,24],["ae",1424-1+657-1,1220,24],["af",1424-1+681-1,1220,24],["ag",1424-1+705-1,1220,24],["ah",1424-1+729-1,1220,24],["ai",1424-1+753-1,1220,24],["aj",1424-1+777-1,1220,24],["ak",1424-1+801-1,1220,24],["al",1424-1+825-1,1220,24],["am",1424-1+849-1,1220,24],["an",1424-1+873-1,1220,24],["ao",1424-1+897-1,1220,24],["ap",1424-1+921-1,1220,24],["aq",1424-1+945-1,1220,24],["ar",1424-1+969-1,1220,24],["as",1424-1+993-1,1220,24],["at",1424-1+1017-1,1220,24],["au",1424-1+1041-1,1220,18],["av",1424-1+1059-1,1220,18],["aw",1424-1+1077-1,1220,18],["ax",1424-1+1095-1,1220,18],["ay",1424-1+1113-1,1220,18],["az",1424-1+1131-1,1220,18],["ba",1424-1+1149-1,1220,18],["bb",1424-1+1167-1,1220,18],["bc",1424-1+1185-1,1220,18],["bd",1424-1+1203-1,1220,18]]],[["CK_94",2],[3903-1+1-1,1220,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",3903-1+1-1,1220,4],["b",3903-1+5-1,1220,10],["c",3903-1+15-1,1220,10],["d",3903-1+25-1,1220,10],["e",3903-1+35-1,1220,10],["f",3903-1+45-1,1220,30],["g",3903-1+75-1,1220,30],["h",3903-1+105-1,1220,24],["i",3903-1+129-1,1220,24],["j",3903-1+153-1,1220,24],["k",3903-1+177-1,1220,24],["l",3903-1+201-1,1220,24],["m",3903-1+225-1,1220,24],["n",3903-1+249-1,1220,24],["o",3903-1+273-1,1220,24],["p",3903-1+297-1,1220,24],["q",3903-1+321-1,1220,24],["r",3903-1+345-1,1220,24],["s",3903-1+369-1,1220,24],["t",3903-1+393-1,1220,24],["u",3903-1+417-1,1220,24],["v",3903-1+441-1,1220,24],["w",3903-1+465-1,1220,24],["x",3903-1+489-1,1220,24],["y",3903-1+513-1,1220,24],["z",3903-1+537-1,1220,24],["aa",3903-1+561-1,1220,24],["ab",3903-1+585-1,1220,24],["ac",3903-1+609-1,1220,24],["ad",3903-1+633-1,1220,24],["ae",3903-1+657-1,1220,24],["af",3903-1+681-1,1220,24],["ag",3903-1+705-1,1220,24],["ah",3903-1+729-1,1220,24],["ai",3903-1+753-1,1220,24],["aj",3903-1+777-1,1220,24],["ak",3903-1+801-1,1220,24],["al",3903-1+825-1,1220,24],["am",3903-1+849-1,1220,24],["an",3903-1+873-1,1220,24],["ao",3903-1+897-1,1220,24],["ap",3903-1+921-1,1220,24],["aq",3903-1+945-1,1220,24],["ar",3903-1+969-1,1220,24],["as",3903-1+993-1,1220,24],["at",3903-1+1017-1,1220,24],["au",3903-1+1041-1,1220,18],["av",3903-1+1059-1,1220,18],["aw",3903-1+1077-1,1220,18],["ax",3903-1+1095-1,1220,18],["ay",3903-1+1113-1,1220,18],["az",3903-1+1131-1,1220,18],["ba",3903-1+1149-1,1220,18],["bb",3903-1+1167-1,1220,18],["bc",3903-1+1185-1,1220,18],["bd",3903-1+1203-1,1220,18]]],[["CK_98",2],[6477-1+( 1)-1,60,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",6477-1+( 1)-1,60,4],["b",6477-1+( 5)-1,60,10],["c",6477-1+( 15)-1,60,10],["d",6477-1+( 25)-1,60,6*6]]],[["CK_101",2],[6743-1+( 1)-1,60,0,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",6743-1+( 1)-1,60,4],["b",6743-1+( 5)-1,60,10],["c",6743-1+( 15)-1,60,10],["d",6743-1+( 25)-1,60,6*6]]]]]
#21.レコードマスタ
table["RC"] = [[4-1,8],[["RC",0],[["4",12-1,0,1],["5",13-1,0,4],["6",17-1,0,4],["7",21-1,0,2],["8",23-1,0,2],["9",25-1,0,2],["10",27-1,0,2],["11",29-1,0,4],["14",94-1,0,2],["15",96-1,0,4],["16",100-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["12",33-1,0,60],["13",93-1,0,1],["17",102-1,0,1],["18",103-1,0,4],["19",107-1,0,1],["20",108-1,0,1],["21",109-1,0,1]]],[[["RC_22",3],[110-1+( 1)-1,130,10,"0"],[["ID",0,0,0],["a",110-1+( 1)-1,130,10]],[["b",110-1+( 11)-1,130,36],["c",110-1+( 47)-1,130,2],["d",110-1+( 49)-1,130,1],["e",110-1+( 50)-1,130,5],["f",110-1+( 55)-1,130,34],["g",110-1+( 89)-1,130,3],["h",110-1+( 92)-1,130,5],["i",110-1+( 97)-1,130,34]]]]]
#22.坂路調教
table["HC"] = [[4-1,8],[["HC",0],[["4",12-1,0,1],["5",13-1,0,8],["6",21-1,0,4],["7",25-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["8",35-1,0,4],["9",39-1,0,3],["10",42-1,0,4],["11",46-1,0,3],["12",49-1,0,4],["13",53-1,0,3],["14",56-1,0,3]]],[]]
#23.競走馬市場取引価格
table["HS"] = [[4-1,8],[["HS",0],[["4",12-1,0,10],["8",42-1,0,6],["11",168-1,0,8]],[["2",3-1,0,1],["3",4-1,0,8],["5",22-1,0,8],["6",30-1,0,8],["7",38-1,0,4],["9",48-1,0,40],["10",88-1,0,80],["12",176-1,0,8],["13",184-1,0,1],["14",185-1,0,10]]],[]]
#24.馬名の意味由来
table["HY"] = [[4-1,8],[["HY",0],[["4",12-1,0,10]],[["2",3-1,0,1],["3",4-1,0,8],["5",22-1,0,36],["6",58-1,0,64]]],[]]
#25.開催スケジュール
table["YS"] = [[4-1,8],[["YS",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["9",26-1,0,1]]],[[["YS_10",3],[27-1+( 113)-1,118,4,"0"],[["ID",0,0,0],["NUM",0,0,0]],[["a",27-1+( 1)-1,118,4],["b",27-1+( 5)-1,118,60],["c",27-1+( 65)-1,118,20],["d",27-1+( 85)-1,118,12],["e",27-1+( 97)-1,118,6],["f",27-1+( 103)-1,118,3],["g",27-1+( 106)-1,118,1],["h",27-1+( 107)-1,118,2],["i",27-1+( 109)-1,118,3],["j",27-1+( 112)-1,118,1],["k",27-1+( 113)-1,118,4],["l",27-1+( 117)-1,118,2]]]]]
#26.データマイニング予想
table["DM"] = [[4-1,8],[["DM",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,4]]],[[["DM_11",18],[32-1+( 1)-1,15,2," "],[["ID",0,0,0],["a",32-1+( 1)-1,15,2]],[["b",32-1+( 3)-1,15,5],["c",32-1+( 8)-1,15,4],["d",32-1+( 12)-1,15,4]]]]]
#27.馬体重
table["WH"] = [[4-1,8],[["WH",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8]]],[[["WH_11",18],[36-1+( 1)-1,45,2,"0"],[["ID",0,0,0],["a",36-1+( 1)-1,45,2]],[["b",36-1+( 3)-1,45,36],["c",36-1+( 39)-1,45,3],["d",36-1+( 42)-1,45,1],["e",36-1+( 43)-1,45,3]]]]]
#28.天候馬場状態
table["WE"] = [[4-1,8],[["WE",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,8],["10",34-1,0,1]],[["2",3-1,0,1],["3",4-1,0,8],["11",35-1,0,1],["12",36-1,0,1],["13",37-1,0,1],["14",38-1,0,1],["15",39-1,0,1],["16",40-1,0,1]]],[]]
#29.出走取消・競走除外
table["AV"] = [[4-1,8],[["AV",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2],["11",36-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["12",38-1,0,36],["13",74-1,0,3]]],[]]
#30.騎手変更
table["JC"] = [[4-1,8],[["JC",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2],["10",28-1,0,8],["11",36-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["12",38-1,0,36],["13",74-1,0,3],["14",77-1,0,5],["15",82-1,0,34],["16",116-1,0,1],["17",117-1,0,3],["18",120-1,0,5],["19",125-1,0,34],["20",159-1,0,1]]],[]]
#31.発走時刻変更
table["TC"] = [[4-1,8],[["TC",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,4],["12",40-1,0,4]]],[]]
#32.コース変更
table["CC"] = [[4-1,8],[["CC",0],[["4",12-1,0,4],["5",16-1,0,4],["6",20-1,0,2],["7",22-1,0,2],["8",24-1,0,2],["9",26-1,0,2]],[["2",3-1,0,1],["3",4-1,0,8],["10",28-1,0,8],["11",36-1,0,4],["12",40-1,0,2],["13",42-1,0,4],["14",46-1,0,2],["15",48-1,0,1]]],[]]
#テーブル作成用SQL文の生成
def create_table_sql(table_name, col_key, col_value)
sql = 'CREATE TABLE "' + table_name + '" ('
sql_primary = 'PRIMARY KEY('
col_key.each {|col|
sql += '"' + col[0] + '"' + ' '
if col[0] == 'ID' or col[0] == 'NUM'
sql += 'INTEGER, '
else
sql += 'TEXT, '
end
sql_primary += '"' + col[0] + '"' + ', '
}
sql_primary.chop!
sql_primary.chop!
sql_primary += ')'
col_value.each {|col|
sql += '"' + col[0] + '"' + ' '
if col[0] == 'ID' or col[0] == 'NUM'
sql += 'INTEGER, '
else
sql += 'TEXT, '
end
}
sql += sql_primary + ');'
return sql
end
print "テーブル作成..."
#テーブルが存在しなければ、作成する
db_tables = db.execute("SELECT tbl_name FROM sqlite_master WHERE TYPE=?", "table").flatten
table.each {|key, value|
#第1テーブル確認
t = value[1]
if db_tables.include?(t[0][0]) == false
# print create_table_sql(t[0][0], t[1], t[2]), "\n"
db.execute( create_table_sql(t[0][0], t[1], t[2]) )
print "[", t[0][0], "]"
end
#第2テーブル確認
value[2].each {|t|
if db_tables.include?(t[0][0]) == false
# print create_table_sql(t[0][0], t[2], t[3]), "\n"
db.execute( create_table_sql(t[0][0], t[2], t[3]) )
print "[", t[0][0], "]"
end
}
}
if db_tables.include?('WRITE_COUNT') == false
db.execute('CREATE TABLE "WRITE_COUNT" ("NAME" TEXT, "COUNT" INTEGER, PRIMARY KEY("NAME"))')
table.each {|key, value|
db.execute('INSERT INTO "WRITE_COUNT" ("NAME", "COUNT") VALUES (?, ?)', key, 0)
}
print "[WRITE_COUNT]"
end
print "OK\n"
#書き込みカウントの読み込み
write_count = Hash.new
db.execute('SELECT "NAME", "COUNT" FROM "WRITE_COUNT"') {|row|
write_count[row[0]] = [row[1].to_i, 0]
}
#日付確認用SQL文の生成
def create_checkdate_sql(table_name, col_key)
sql = 'SELECT "3" FROM "' + table_name + '"'
t = ' WHERE '
col_key.each {|col|
sql += t + '"' + col[0] + '" = :col_' + col[0]
t = ' AND '
}
return sql
end
#ROWID取得用SQL文の生成
def create_getrowid_sql(table_name, col_key)
sql = 'SELECT "ROWID" FROM "' + table_name + '"'
t = ' WHERE '
col_key.each {|col|
sql += t + '"' + col[0] + '" = :col_' + col[0]
t = ' AND '
}
return sql
end
#挿入用SQL文の生成
def create_insert_sql(table_name, col_key, col_value)
sql = 'INSERT INTO "' + table_name + '" ('
sql_values = ' VALUES ('
col_key.each {|col|
sql += '"' + col[0] + '", '
sql_values += ':col_' + col[0] + ', '
}
col_value.each {|col|
sql += '"' + col[0] + '", '
sql_values += ':col_' + col[0] + ', '
}
sql.chop!
sql.chop!
sql_values.chop!
sql_values.chop!
sql += ')' + sql_values + ')'
return sql
end
#更新用SQL文の生成
def create_update_sql(table_name, col_key, col_value)
sql = 'UPDATE "' + table_name + '" SET'
col_value.each {|col|
sql += ' "' + col[0] + '" = :col_' + col[0] + ','
}
sql.chop!
t = ' WHERE '
col_key.each {|col|
sql += t + '"' + col[0] + '" = :col_' + col[0]
t = ' AND '
}
return sql
end
#削除用SQL文の生成
def create_delete_sql(table_name)
return 'DELETE FROM "' + table_name + '" WHERE "ID" = :col_ID'
end
#末尾の全角空白文字と空白文字" \t\r\n\f\v"を削除する
def rstripWS(txt)
while txt.sub!(/ $/, '')
end
txt.rstrip
end
#Ctrl + Cで停止させられた場合の処理
$flag_stop = false
Signal.trap(:INT){
$flag_stop = true
}
#SQL文の準備
$checkdate_sql = Hash.new
$getrowid_sql = Hash.new
$insert_sql = Hash.new
$update_sql = Hash.new
$delete_sql = Hash.new
table.each {|key, value|
#第1テーブル用SQL文
t = value[1]
$checkdate_sql[t[0][0]] = create_checkdate_sql(t[0][0], t[1])
$getrowid_sql[t[0][0]] = create_getrowid_sql(t[0][0], t[1])
$insert_sql[t[0][0]] = create_insert_sql(t[0][0], t[1], t[2])
$update_sql[t[0][0]] = create_update_sql(t[0][0], t[1], t[2])
#第2テーブル用SQL文
value[2].each {|t|
$insert_sql[t[0][0]] = create_insert_sql(t[0][0], t[2], t[3])
$update_sql[t[0][0]] = create_update_sql(t[0][0], t[2], t[3])
$delete_sql[t[0][0]] = create_delete_sql(t[0][0])
}
}
#SQLパラメータの設定
def sql_bindparam(stmt, col_set, data, count = 0, rowid = -1)
col_set.each { |col|
param_name = 'col_' + col[0]
if col[0] == 'ID'
stmt.bind_param(param_name, rowid)
elsif col[0] == 'NUM'
stmt.bind_param(param_name, count)
else
stmt.bind_param(param_name, rstripWS(data[col[1] + col[2] * count, col[3]]))
end
}
end
#SQL文の実行
def sql_execute(db, data, sql, col_key, col_value, count = 0, rowid = -1)
db.prepare(sql) do |stmt|
sql_bindparam(stmt, col_key, data, count, rowid) unless col_key == nil
sql_bindparam(stmt, col_value, data, count, rowid) unless col_value == nil
stmt.execute do |result|
#p result
end
end
end
#SQL文の実行(最初の値を返す)
def sql_get_first_value(db, data, sql, col_key, col_value)
return nil if sql == nil
db.prepare(sql) { |stmt|
sql_bindparam(stmt, col_key, data) unless col_key == nil
sql_bindparam(stmt, col_value, data) unless col_value == nil
stmt.execute! { |row| return row[0] }
}
nil
end
#変数
$insert_count = 0
$update_count = 0
$skip_count = 0
#データ作成年月日をチェックし、データの挿入or更新をする
def database_update(db, data, table_type)
#■第1テーブル更新
table_name = table_type[1][0][0]
col_key = table_type[1][1]
col_value = table_type[1][2]
del_flag = false
#既存データ作成年月日の取得
changedate = sql_get_first_value(db, data, $checkdate_sql[table_name], col_key, nil)
if changedate == nil then
#挿入(データなし)
$insert_count = $insert_count + 1
sql_execute(db, data, $insert_sql[table_name], col_key, col_value)
elsif changedate < data[table_type[0][0], table_type[0][1]] then
#更新
$update_count = $update_count + 1
sql_execute(db, data, $update_sql[table_name], col_key, col_value)
del_flag = true
else
#スキップ
$skip_count = $skip_count + 1
return
end
#第1テーブルのROWID取得
rowid = sql_get_first_value(db, data, $getrowid_sql[table_name], col_key, nil)
rowid = rowid.to_i
#■第2テーブル更新
table_type[2].each { |sub_table|
next if sub_table == nil
table_name = sub_table[0][0]
col_key = sub_table[2]
col_value = sub_table[3]
#既存データ削除
sql_execute(db, data, $delete_sql[table_name], [['ID',0,0,0]], nil, 0, rowid) if del_flag
#挿入
sub_table[0][1].times { |n|
#有効性チェック
if sub_table[1][2] > 0 then
datacheck = data[sub_table[1][0]+sub_table[1][1]*n, sub_table[1][2]]
next if datacheck == (sub_table[1][3] * sub_table[1][2])
end
sql_execute(db, data, $insert_sql[table_name], col_key, col_value, n, rowid)
}
}
end
#Downloadフォルダ内の.datファイルを列挙する
Dir.glob('Download/*.dat').each { |name|
if FileTest.file?(name) then
print "[", name, "]"
#ファイルの種類を確認
recordid = File.basename(name)[0,2].upcase
unless table[recordid] == nil then
before_insert_count = $insert_count
before_update_count = $update_count
before_skip_count = $skip_count
#.datファイルを開く
count = 1000
print "開始..."
open(name, "rb") { |datfile|
#.datファイルから1レコード読み込む
datfile.each { |line|
#レコードの種類を確認
# (1つのファイルに複数種類のレコードが混在している場合の処理)
#recordid = line[0, 2]
#next if table[recordid] == nil
#書き込みカウンタのチェック
record_count = write_count[recordid]
record_count = [0, 0] if record_count == nil
record_count[1] = record_count[1] + 1
write_count[recordid] = record_count
if (record_count[0] < record_count[1])
#データベースに書き込み
database_update(db, line, table[recordid])
end
#進行状況を表示(1000単位)
count = count - 1
if count <= 0 then
print '*'
count = 1000
end
#Ctrl + C
break if $flag_stop
}
}
print "\n =>[insert:", $insert_count - before_insert_count, ",",
"update:", $update_count - before_update_count, ",",
"skip:", $skip_count - before_skip_count, "]"
end
print "\n"
#Ctrl + C
break if $flag_stop
end
}
#書き込みカウントの書き込み
db.execute('DELETE FROM "WRITE_COUNT"')
write_count.each { |key, value|
count = if (value[0] > value[1]) then value[0] else value[1] end
db.execute('INSERT INTO "WRITE_COUNT" ("NAME", "COUNT") VALUES (?, ?)', key, count)
}
print "insert:", $insert_count, "\n",
"update:", $update_count, "\n",
" skip:", $skip_count, "\n"
#データベースを閉じる
db.close

(C) 2008 NARITA Takuro
E-Mail:narita@a1.mbn.or.jp