[pgsql-jp: 32880] replaceやsubstringを大量に重ねると文字が変になる?

minoyama minoyama @ t-tsc.co.jp
2004年 4月 29日 (木) 00:41:09 JST


postgres初心者のminoyamaと申します。
皆様のお知恵をお貸しください。

バージョン 7.3.4 を Redhat Linux ES2.1上で使っています。
DBのエンコーディング・OSの文字コードは、EUC_JPです。


次のような後方ブランク(半角・全角とも)を取り除く関数を作りました。
単純に、引数の後ろから文字を1文字ずつチェックし、ブランクであれば、
取り除く処理です。

create function f_rtrim(varchar(256)) returns varchar(256) as '
declare

  sWork varchar(500);
  aLen int4;
  sMoji varchar(2);

begin
  sWork := $1;
  loop
    aLen := length(sWork);
    sMoji := substring(sWork,aLen,1);
    if sMoji = '' '' or sMoji = '' '' then
      sWork := substring(sWork,1,aLen-1);
    else
      exit;
    end if;
  end loop;
  return sWork;
end;
'language 'plpgsql';




次のような、半角カタカナを全角カタカナに変換する関数を
つくりました。
replace関数をつかって、半角アなら全角アに、半角イなら全角イに
という処理をひたすら重ねています。

[半角の]と書いているのは、本MLルールで半角カタカナが使えない
ため、[半角の]ア等の表現をしていますが、実際には、本当に半角のア
が記載されているものとして呼んでください。

create or replace function f_hantozen(varchar(256))
returns varchar(256) as '
declare
  sWork varchar(500);

begin

  sWork := $1;

    sWork := replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(replace(replace(replace(replace
             (replace(replace(sWork, ''ガ'', ''ガ'')
             , ''[半角の]ギ'', ''ギ''), ''[半角の]グ'', ''グ'')
             , ''[半角の]ゲ'', ''ゲ''), ''[半角の]ゴ'', ''ゴ'')
             , ''[半角の]ザ'', ''ザ''), ''[半角の]ジ'', ''ジ'')
             , ''[半角の]ズ'', ''ズ''), ''[半角の]ゼ'', ''ゼ'')
             , ''[半角の]ゾ'', ''ゾ''), ''[半角の]ダ'', ''ダ'')
             , ''[半角の]ヂ'', ''ヂ''), ''[半角の]ヅ'', ''ヅ'')
             , ''[半角の]デ'', ''デ''), ''[半角の]ド'', ''ド'')
             , ''[半角の]バ'', ''バ''), ''[半角の]パ'', ''パ'')
             , ''[半角の]ビ'', ''ビ''), ''[半角の]ピ'', ''ピ'')
             , ''[半角の]ブ'', ''ブ''), ''[半角の]プ'', ''プ'')
             , ''[半角の]ベ'', ''ベ''), ''[半角の]ペ'', ''ペ'')
             , ''[半角の]ボ'', ''ボ''), ''[半角の]ポ'', ''ポ'')
             , ''[半角の]ヴ'', ''ヴ''), ''[半角の]ァ'', ''ァ'')
             , ''[半角の]ア'', ''ア''), ''[半角の]ィ'', ''ィ'')
             , ''[半角の]イ'', ''イ''), ''[半角の]ゥ'', ''ゥ'')
             , ''[半角の]ウ'', ''ウ''), ''[半角の]ェ'', ''ェ'')
             , ''[半角の]エ'', ''エ''), ''[半角の]ォ'', ''ォ'')
             , ''[半角の]オ'', ''オ''), ''[半角の]カ'', ''カ'')
             , ''[半角の]キ'', ''キ''), ''[半角の]ク'', ''ク'')
             , ''[半角の]ケ'', ''ケ''), ''[半角の]コ'', ''コ'')
             , ''[半角の]サ'', ''サ''), ''[半角の]シ'', ''シ'')
             , ''[半角の]ス'', ''ス''), ''[半角の]セ'', ''セ'')
             , ''[半角の]ソ'', ''ソ''), ''[半角の]タ'', ''タ'')
             , ''[半角の]チ'', ''チ''), ''[半角の]ッ'', ''ッ'')
             , ''[半角の]ツ'', ''ツ''), ''[半角の]テ'', ''テ'')
             , ''[半角の]ト'', ''ト''), ''[半角の]ナ'', ''ナ'')
             , ''[半角の]ニ'', ''ニ''), ''[半角の]ヌ'', ''ヌ'')
             , ''[半角の]ネ'', ''ネ''), ''[半角の]ノ'', ''ノ'')
             , ''[半角の]ハ'', ''ハ''), ''[半角の]ヒ'', ''ヒ'')
             , ''[半角の]フ'', ''フ''), ''[半角の]ヘ'', ''ヘ'')
             , ''[半角の]ホ'', ''ホ''), ''[半角の]マ'', ''マ'')
             , ''[半角の]ミ'', ''ミ''), ''[半角の]ム'', ''ム'')
             , ''[半角の]メ'', ''メ''), ''[半角の]モ'', ''モ'')
             , ''[半角の]ャ'', ''ャ''), ''[半角の]ヤ'', ''ヤ'')
             , ''[半角の]ュ'', ''ュ''), ''[半角の]ユ'', ''ユ'')
             , ''[半角の]ョ'', ''ョ''), ''[半角の]ヨ'', ''ヨ'')
             , ''[半角の]ラ'', ''ラ''), ''[半角の]リ'', ''リ'')
             , ''[半角の]ル'', ''ル''), ''[半角の]レ'', ''レ'')
             , ''[半角の]ロ'', ''ロ''), ''[半角の]ワ'', ''ワ'')
             , ''[半角の]ヲ'', ''ヲ''), ''[半角の]ン'', ''ン'')
             , ''[半角の]ー'', ''ー''), ''[半角の]、'', ''、'')
             , ''[半角の]。'', ''。''), ''[半角の]「'', ''「'')
             , ''[半角の]」'', ''」'');

  return sWork;
end;
'language 'plpgsql';


これら2つの関数を重ね合わせて、半角−>全角変換しながら、
後方ブランクを取り除くSQLを次のように作り、psqlから実行しました。
select '''' || col1 || ''''
     , '''' || f_hantozen(f_rtrim(col1)) || ''''
from tbl1
order by col1;

すると、

            col1                |         ?column?
--------------------------------+--------------------------
 'ミツビシ               '      | 'ミツビシ'
 'ミツビシ               '      | 'ミツビシ'
 'ミツビシ               '      | 'ミツビシ'
 'ミツビシ               '      | 'ミツビシ'
 'ミツビシ               '      | 'ミツビシウ'  <−−
 'ミツビシ               '      | 'ミツビシウ'  <−−
 'ミツビシ               '      | 'ミツビシウ'  <−−
 'ミツビシ               '      | 'ミツビシウ'  <−−
 'ミツビシ               '      | 'ミツビシウ'  <−−
 'メルセデスベンツ          '   | 'メルセデスベンツ'
 'メルセデスベンツ          '   | 'メルセデスベンツ'
 'メルセデスベンツ          '   | 'メルセデスベンツウ'  <−−
 'メルセデスベンツ          '   | 'メルセデスベンツ'
 'メルセデスベンツ          '   | 'メルセデスベンツウ'  <−−

のような答えが返ってきます。
問題なのは、"<−−"を付けた行なのですが、ウという文字が最後について
きます。
しかも、同じ、「メルセデスベンツ          」という文字を同じ関数に
通しているのに。
また、単純に、
select f_hantozen(f_rtrim('メルセデスベンツ          '))
とやっても、決して、「メルセデスベンツウ」とはならないのに、
テーブルからselectした場合のみ、不特定多数の行でこの「ウ」が
うしろについてきます。

また、f_hantozenを単体で試した場合や、f_rtrimを単体で試した
場合にも問題は発生しません。

この原因は何なのでしょうか?
また、回避方法はあるのでしょうか?

原因、対策について、皆様のお知恵をお貸し頂きたく。
よろしく御願いします。








pgsql-jp メーリングリストの案内