UnicodeからSJISだと文字化け⇒SQL抽出

UnicodeからSJISにすると文字化け

Unicode(UTF-8)からSJISに文字コードを変換すると文字化けする文字があります。Unicodeの方が文字の範囲が広く、SJISでは表せない文字が多数あるからです。

AccessとPostgresでのUTF-8

AccessではUTF-8コード正常に表示できます。うちの環境ではPostgresqlを利用していますが、ODBCドライバよくできていて、UTF8コードで接続できるので、Access上で、UTF8コードのPostgresテーブル上のレコードを文字化けなく扱う事ができます。

AccessからCSV掃き出し

AccessからCSVに吐き出すときに問題が起きます。何も指定しないとSJISで吐き出されますが、この時変換できないため文字化け文字は?として表示されます。

文字化け文字のみを抽出

文字化けを起こす文字を含むレコードだけを抽出したいです。惨々探し回りましたが、文字化け文字をExcel上で検索する方法はありますが、SQLを書いて、文字化けしそうなものだけを抽出する事は出来なさそうです。

PL/PgSQLを利用

仕方がないので、自分で関数を作ります。順序立てて説明します。

Postgresで、SJISコードに変換関数

Postgresでは文字列操作の関数の中に、文字コード変換の関数が準備されています。
その中に、ShiftJISコードに変換する関数があります。

注意 バージョンによって、関数の書き方が異なります。
https://www.postgresql.jp/document/7.4/html/functions-string.html

https://www.postgresql.jp/document/9.5/html/functions-string.html

convert_to(string text, dest_encoding name)

文字列をdest_encodingに変換します。

Posgresで、SJIS変換のエラー

convert_toをかけた時に、SJISにない文字コードを変換しようとするとエラーが出ます。

SQL文 name1にSJISに変換できな文字有

select id,convert_to(name1,'SJIS') as hantei FROM persons

ERROR: 符号化方式"UTF8"における0xe6 0xa1 0xbaバイトシーケンスを持つ文字は"SJIS"符号化方式では等しくありません
********** エラー **********

ERROR: 符号化方式"UTF8"における0xe6 0xa1 0xbaバイトシーケンスを持つ文字は"SJIS"符号化方式では等しくありません
SQLステート:22P05

エラーを取得するPL/pgSQL

このエラーを利用して、SQLステート:22P05を吐いたら、UTF8から、SJISに変換できないコードを持っているという判定を行う関数を自作します。

CREATE OR REPLACE FUNCTION can_convert_sjis(name1 TEXT)
RETURNS INTEGER AS $$
DECLARE
sjis_name text;
BEGIN
-- SJISに変換できれば0を返す
sjis_name := convert_to(name1,'SJIS');
RETURN 0;
EXCEPTION
-- SJISに変換できないというエラーがでたら1を返す
WHEN untranslatable_character THEN
RETURN 1;
WHEN OTHERS THEN
-- それ以外のエラーがでたら2を返す
RETURN 2;
END;
$$ LANGUAGE plpgsql;

エラーコードについて

Postgresのエラーコード一覧はこちらに掲載があります。

https://www.postgresql.jp/document/9.4/html/errcodes-appendix.html

22P05 untranslatable_character

WHENで取得Exceptionは条件名で指定します。

エラーを吐くIDを抽出

name1にShitJISからUTF8に変換できないコードを持っているものを抽出します。

SELECT * FROM
(select id,can_convert_sjis(name1) as hantei FROM persons) as h
where hantei = 1