MySQL4.1でlatin1なテーブルに格納された日本語データのサルベージ
全回のRails勉強会で相談したネタですが、以前作成したDBでlatin1のテーブルにEUC-JPの日本語を格納してしまい、ダンプツールなどでうまく読み出せなくなってしまっていました。*1
とりあえずRailsからはbinaryで読みだし、日本語として表示できていました。でも、やっぱりUTF-8のほうが楽だよね、ということでMySQL5.0+UTF-8のテーブルに移行するため、データをダンプした際にこの過去のミスがもとでハマった、と。
Rails勉強会の場では「ActiveRecord経由で読み出せば救えるんじゃない?」というアドバイスをいただきまして、その結果うまく救出できたのでまとめをば。
与件
改めて状況をまとめますと、以下の感じでした。
対処内容
ActiveRecord経由でつないでstringなフィールドをkconvでString#toutf8した上でYAMLに保存。ロード時も同じくActiveRecordのオブジェクトを読み込んで保存、と。
ActiveRecordでつなぐあたりはid:secondlifeさんのiar.rbを流用させてもらいました。最下部のIrb.startをコメントアウトしオプションに追加したり、オプションのパース結果をグローバル変数にしたり。
ダンプ側コード
ご参考まで。
# dump_dirとyaml_file_for(table)はそれぞれダンプ先ディレクトリと # ダンプするテーブル名.ymlなファイルを返すユーティリティメソッド def dump(opts = {}) opts = { :excludes => ['schema_info'] }.merge(opts) Dir.mkdir dump_dir unless File.directory? dump_dir show_tables.each do |table| next if opts[:excludes].to_a.include?(table) table_class = self.class.const_get(table.classify) instances = table_class.find(:all).map do |obj| block_given? ? (yield obj) : obj end File.open(yaml_file_for(table),"wb") do |dump_file| YAML.dump(instances, dump_file) end end end if __FILE__ == $0 dump do |obj| obj.attributes.each do |k,v| obj.__send__("#{k}=".to_sym, v.toutf8) if v.is_a? String end obj end end