2019年7月30日火曜日

EUC_JPの亡霊

文字コード問題、嫌ですよね。
ちょっと古いシステムだと文字コードが「EUC-JP」だったりします。
これを「UTF-8」で扱っても通常は問題は無いのですが、1部の特殊な文字でおかしくなります。
代表的なのが
タカ、ハマ、サキ。
高、浜、崎、それぞれの旧字体。はしごだか、とか言われているやつです。
これらがデータベースに入っていると、例えば、
Select * from ~
のアスタリスクで全レコードを取得した時に、0x8f系のencoding “EUC_JP” has no equivalent in “UTF8”エラーで目出度く失敗します。
一般的な解決方法は、データベースのダンプを取って、文字コード変換処理をしてリストアになるはず。

だけれども。

そんなDBの外側にアクセス出来ない、OSに触れないなんて時もある。
SELECT文で正規表現を使って、とりあえず別の文字にする方法もありますが、僕はそれでは上手くいきませんでした。

超力業としては、作成・更新の時刻のカラムがあるテーブルであれば、徐々に攻めていくなんてのもあります。
WHERE句にて日付を指定しつつ、エラーが起こった周辺で細かく見ていく的な。
件数が少なければ、それもアリでしょう。
今回は16万件ほどだったので・・・普通にムリー。

そもそも、上記のエラーはその特定のアイテムにさえ触れなければ発生しません。
「*」では無く、文字コードが関係していない箇所を選んでセレクトすれば、同じレコードだとしても値を返してくれます。
流石に主キーで文字コード問題は発生…しませんよね?
という事で、こんな風にやってみました。

使うのは勿論、.netです。
仕事ではエクセルを覚えたら、次の順番としてC#もしくはJavaScriptという事には異論無いはず。
これがサラリーマン、あー、今だと色々ややこしいから、ビジネスパーソンとしてあるべき姿。
データベースからデータを取得する方法はいくつかありますが、しょせん1回使って捨てるコードです。
1番簡単で便利な「DataSet」を使いましょう。
EntityFrameworkは、ここではちょっと過剰ですね。

データセットのデザイン画面でクエリを追加し、主キーだけを取得するメソッドを用意します。
後はテーブルから全主キーを取得し(メモリに全乗せするためにtoList()してしまう)、ひたすらForeachで回す。
try句で囲って、その中で改めて、主キーを渡して1行分のデータを取得。
もしそこで文字コードのエラーで出るようなら、例外が発生。
chatchでその主キーを収集しておく。

とりあえず、これで問題のある行だけは特定できるので、そこを修正すればOKです。
やってみたところ、おかしかったのは1レコードのみ。
16万件中のたった1件です。

僕が作ったシステムでは無く、引き継ぎ引き継ぎで流れてきたものなので、そもそも仕様すら把握しておらず。
アチコチのコードを見ながら、ようやく全体像が掴めてきたところ。
ああ、まだまだ先は長そうだな!

これで何とかなる事が分かったので、次に同じ問題が発生しても大丈夫。
レアケースだし、今後は無いだろうけれども…。


see more info at JRDV.sp