Ruby + Sequelを使って、日本語テーブル名やカラム名を持つMS Accessからデータを抽出する

以前の記事でSequelを使ってMS Accessへと接続できることが分かりました。

ただ、残念ながらテーブル名やカラム名が日本語になっていることがあるため、その場合はどうなるかを試してみました。

 

環境

 
また、MS Access日本語サンプルテーブルを以下の構造で用意します。半角カタカナを使っています。

カラム名
ID オートナンバー
名前 テキスト
コメント テキスト

なお、データベースファイル名は日本語でも接続できました。

 

検証

事前準備

今回のコードの基本形は以下の通りです。TableNameテーブルより、ID=1のデータを取得し、col1列を表示します。

ACCDB_PATH = '//127.0.0.1/db/Sample.accdb'
OLEDB_PROVIDER = 'Microsoft.ACE.OLEDB.12.0'
ODBC_DRIVER = '{Microsoft Access Driver (*.mdb, *.accdb)}'

db = Sequel.ado(conn_string: "Provider=#{OLEDB_PROVIDER};Data Source=#{ACCDB_PATH}")

ds = db[:TableName].select(:col1, :col2).where(ID: :$n)
r = ds.prepare(:first).call(n: 1)
p r[:col1]

 
Sequelではテーブル名やカラム名をシンボルで指定するため、テーブル名やカラム名が日本語のMS Accessに対し、以下のコードでカラム名エンコーディングを取得してみます。

r.each do |k, v|
  p k                                             #=> `:名前` or `:コメント`
  p k.encoding                                    #=> #<Encoding:Windows-31J>
end

カラム名は日本語のシンボルで、エンコーディングEncoding:Windows-31Jのようです。

 
次に日本語シンボルをEncoding:UTF-8のものとEncoding:Windows-31Jのものを作ってみました。

key = '名前'.force_encoding('cp932').to_sym
p key.encoding                                    #=> <Encoding:Windows-31J>
p Symbol.all_symbols.select{|e| e == key}.count   #=> `1`となり、登録されている

## 日本語シンボル(UTF-8)
p :名前.encoding                                  #=> #<Encoding:UTF-8>
p Symbol.all_symbols.select{|e| e == :名前}.count #=> `1`となり、登録されている

シンボルとして登録されていて、エンコーディングも指定された通りのようです。

 

日本語シンボルを使ったデータ取得

基本形を上記のシンボルに変えて、日本語カラムからのデータ取得を試してみました。

ds1 = db[:日本語サンプル].select(:名前, :コメント).where(ID: :$n)
r1 = ds1.prepare(:first).call(n: 1)

### 取得できたかを確認: 取得できている
p r1                                              #=> {:名前=>"ほげ", :コメント=>"ホゲ"}

### 事前に用意したシンボルで、特定の列を取得してみる
p r1[key]                                         #=> nil (CP932のシンボルで列を取得できない)
p r1[:名前]                                       #=> nil (UTF-8のシンボルで列を取得できない)

ソースコードのコメント通り、どちらのシンボルを使っても日本語カラムからデータを取得することができませんでした。

Sequelではエンコードを変更していなさそうなので、これ以上追求することはやめておきました。
MSSQL-Server/ruby-gem sequel: How to read UTF-8 values? - Stack Overflow

 

エイリアスを使ったデータ取得

Sequelではselectメソッドを使うときに:名前___nameとしてエイリアスを付けることができるため、日本語カラム名に英語のエイリアスを付けて試してみました。

ds2 = db[:日本語サンプル].select(:名前___name, :コメント___comment).where(ID: :$n)
r2 = ds2.prepare(:first).call(n: 1)

### 取得できたかを確認: 取得できている
p r2                                              #=> {:name=>"ほげ", :comment=>"ホゲ"}

# エイリアスで、特定の列を取得してみる
p r2[:name]                                       #=> "ほげ"
p r2[:comment]                                    #=> "ホゲ"

コメント通り、取得することができました。

 
ただ、本当にこれでいいのかという気もするので、何かあればご指摘ください。

 

検証時のコード

Gistに上げました。
Ruby + Sequelを使って、テーブル名やカラム名が日本語のMS Accessからデータを抽出する

データベースファイルはSinatraToMSAccess-SampleのSample.accdbを使いました。
thinkAmi/SinatraToMSAccess-Sample · GitHub

 

その他

プリペアドステートメント

以下のドキュメントが参考になりました。

 

filterメソッドとwhereメソッド

filterメソッドはwhereメソッドエイリアスのようだったため、見慣れているwhereメソッドを使いました。
method filter - Sequel::Dataset