Re:SALOON & VBA

住所分解&コード化ツール(PL/SQL)

住所分解&コード化をPL/SQL化してみました。
実行中、ダンマリになる(経過が見えない)ので、長く感じますが、
EXCEL VBA版よりは、若干速い気はします。
私のPCで、1,000件10分ぐらいの速度です。(EXCEL VBAは、600件で10分ぐらいです。)
PL/SQLのデバッグの勉強にはなりました。※その後、高速化しました。


create or replace PROCEDURE ANALYZE_ADRS IS
/**********************************************************************************/
/* 処理名:住所分解処理                       ANALYZE_ADRS */
/*  ①住所を、市区名(県名+市区町村名)、字名(大字名+小字名)、番地、方書に分類する */
/*  ②各々の構成要素ごとにコード化する(住所マスタ使用)              */
/**********************************************************************************/
  CURSOR csr
  IS
   SELECT ADRS,YUBIN,ROWID
    FROM ADRS_ANALYZE
   ORDER BY ADRS;

-- 制御ワーク
  J     PLS_INTEGER;     -- 文字位置
  K     PLS_INTEGER;     -- 添字
  L     PLS_INTEGER;     -- 文字長
  UPDCNT  NUMBER;        -- 更新件数
  RECCNT  NUMBER;        -- 件数ワーク
  WERRMSG  VARCHAR2(255);    -- エラーメッセージ
  WERRNO  NUMBER;        -- エラー№

-- 編集ワーク
  WADRS   VARCHAR2(200);    -- 住所中間編集ワーク
  WYUBIN  VARCHAR2(8);     -- 郵便番号編集ワーク
  WKENCD  NUMBER;        -- 都道府県コード
  WSIKUCD  NUMBER;        -- 市区町村コード
  WOAZACD  VARCHAR2(4);     -- 大字コード
  WKOAZACD VARCHAR2(4);     -- 小字コード
  WSIKUMEI VARCHAR2(60);     -- 市区町村名編集ワーク
  WAZAMEI  VARCHAR2(144);    -- 字名編集ワーク
  WKATAGAKI VARCHAR2(100);    -- 方書編集ワーク
  WBANTI  VARCHAR2(60);     -- 番地コード編集ワーク
  DISPTIME VARCHAR2(20);     -- 時刻編集ワーク
  WBANTICD VARCHAR2(20);     -- 番地コード
  TEMPBAN  VARCHAR2(10);     -- 番地コード編集用ワーク

-- 市区町村省略住所検索用
  MYKENCD  NUMBER    := 25; -- 自自治体県コード(滋賀県)
  MYSIKUCD NUMBER    := 201; -- 自自治体市区町村コード(大津市)

-- 前データ保持
  BKENCD  NUMBER    := 23;
  BKENMEI  VARCHAR2(12) := '愛知県';
  BSIKUCD  NUMBER    := 0;
  BSIKUMEI VARCHAR2(60) := NULL;
  BOAZACD  VARCHAR2(4)  := NULL;
  BKOAZACD VARCHAR2(4)  := NULL;
  BYUBIN  VARCHAR2(8)  := NULL;
  BAZAMEI  VARCHAR2(144) := NULL;

-- 市区名分割例外表…市・区・町・村の文字で単純に分割できない地名
  CURSOR csr_reigai IS
   SELECT A2.KEYKENCD,  -- 都道府県
      A2.KEYSIKUCD, -- 市区コード
      A2.SIKUMEI,  -- 例外市区名
      A1.KENMEI,   -- 都道府県名
      A2.KENMEIKBN  -- 県名有無区分
    FROM MST_ADRS1 A1,MST_ADRS2 A2
   WHERE A2.KEYKENCD = A1.KEYKENCD
    AND A2.KEYKENCD || A2.KEYSIKUCD IN (1409,3215,4322,7212,10464,
      12203,12219,13361,13362,13363,13364,13381,13382,13401,13402,
      13421,17212,21219,23214,24202,29203,29212,29402,34213,41423);
  REIGAI_REC csr_reigai%ROWTYPE;
  TYPE REIGAI_TYPE IS TABLE OF csr_reigai%ROWTYPE INDEX BY BINARY_INTEGER;
  REIGAI REIGAI_TYPE;
  IX   PLS_INTEGER := 0; -- 配列カウンタ

BEGIN
  SELECT TO_CHAR(SYSDATE,'YYYY/MM/DD HH24:MI:SS') INTO DISPTIME FROM DUAL;
  DBMS_OUTPUT.PUT_LINE('開始時刻 ' || DISPTIME);
  UPDCNT  := 0;

-- 例外分割市区名配列設定
  FOR REIGAI_REC IN csr_reigai
  LOOP
   IX := IX + 1;
   REIGAI(IX) := REIGAI_REC;
  END LOOP;

  FOR rec IN csr
  LOOP
 --【ワーク項目の初期化】
   WKENCD  := -1;   -- 都道府県コード
   WSIKUCD  := -1;   -- 市区町村コード
   WOAZACD  := '0000'; -- 大字コード
   WKOAZACD := '0000'; -- 小字コード
   WBANTICD := NULL;  -- 番地コード
   TEMPBAN  := NULL;  -- 番地コードワーク
   WSIKUMEI := NULL;  -- 市区町村名
   WAZAMEI  := NULL;  -- 字名
   WKATAGAKI := NULL;  -- 方書
   WBANTI  := NULL;  -- 番地

 --【整形処理】
  -- ①全角化
   WADRS := TO_MULTI_BYTE(rec.ADRS);

  -- ②カンマ除去
   WADRS := REPLACE(WADRS,'.','');

  -- ③空白除去
   WADRS := REPLACE(REPLACE(WADRS,' ',''),' ','');

  -- ④郵便番号の整形(XXX-XXXX)
   WYUBIN := rec.YUBIN;
   CASE
   WHEN LENGTH(WYUBIN) = 8
    AND SUBSTR(WYUBIN, 4, 1) = '-' THEN
     WYUBIN := REPLACE(WYUBIN,' ','0');
   WHEN LENGTH(WYUBIN) = 7
    AND LENGTH(TRANSLATE(WYUBIN,'0123456789','')) = 0 THEN
     WYUBIN := SUBSTR(WYUBIN,1,3) || '-' || NVL(SUBSTR(WYUBIN,-4),WYUBIN);
   ELSE
     NULL;
   END CASE;
   L := LENGTH(WADRS);

 --【市区町村字名と番地を分離】
  -- ①丁目で分割
   J := INSTR(WADRS,'丁目');
   CASE
   WHEN J > 0 THEN
     CASE
     WHEN J = L - 1 THEN
      NULL;
     WHEN SUBSTR(WADRS,J + 2,1) IN ('東','西','南','北') THEN
      WBANTI := SUBSTR(WADRS,J + 3);
      WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 2));
     ELSE
      WBANTI := SUBSTR(WADRS,J + 2);
      WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
     END CASE;

  -- ②北海道は、条も字名
   WHEN SUBSTR(WADRS,1,3) = '北海道'
    AND (INSTR(WADRS,'条') > 1 OR
      INSTR(WADRS,'線') > 1) THEN
     J := INSTR(WADRS,'条');
     IF J < 1 THEN
      J := INSTR(WADRS,'線');
     END IF; 
     IF ISZNUMBER(SUBSTR(WADRS,J - 1,1)) THEN
     -- 条・線の前後が数字なら条・線で分割
      CASE
      WHEN ISANUMBER(SUBSTR(WADRS,J + 1,1)) THEN
        WBANTI := SUBSTR(WADRS,J + 1);
        WADRS := ASU2KSU(SUBSTR(WADRS,1,J));
     -- 条・線の前と1字後が数字なら1字後で分割
      WHEN ISANUMBER(SUBSTR(WADRS,J + 2)) THEN
        WBANTI := SUBSTR(WADRS,J + 2);
        WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
     -- 条・線の前と2字後が数字なら2字後で分割
      WHEN ISANUMBER(SUBSTR(WADRS,J + 3)) THEN
        WBANTI := SUBSTR(WADRS,J + 3);
        WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 2));
      ELSE
        NULL;
      END CASE;
     END IF;
     WKENCD  := 1;             -- 北海道

  -- ③大阪府堺市は、丁で分割 (丁ありは丁目なし)
   WHEN SUBSTR(WADRS,1,5) = '大阪府堺市'
    AND INSTR(WADRS,'丁') > 1 THEN
     J := INSTR(WADRS,'丁');
   -- 丁の前後が数字なら丁で分割
     IF ISZNUMBER(SUBSTR(WADRS,J - 1,1)) AND
      ISZNUMBER(SUBSTR(WADRS,J + 1,1)) THEN
      WBANTI := SUBSTR(WADRS,J + 1);
      WADRS := ASU2KSU(SUBSTR(WADRS,1,J));
     END IF;
     WKENCD  := 27;            -- 大阪府
    
  -- ④岩手県の「地割」は字名
   WHEN SUBSTR(WADRS,1,3) = '岩手県'
    AND INSTR(WADRS,'地割') > 1 THEN
     J := INSTR(WADRS,'地割');
     WADRS := ASU2KSU(SUBSTR(WADRS,1,J)) || SUBSTR(WADRS,J + 1);
     WKENCD  := 3;             -- 岩手県

  -- ⑤○番町という字名
   WHEN INSTR(WADRS,'番町') > 0 THEN
     J := INSTR(WADRS,'番町');
     IF ISZNUMBER(SUBSTR(WADRS,J + 2,1)) THEN
      WBANTI := SUBSTR(WADRS,J + 2);
      WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
     END IF;

  -- ⑥アラビア数字で分割
   WHEN WBANTI IS NULL THEN      -- 未分割
     FOR I IN 1..L LOOP
      IF ISANUMBER(SUBSTR(WADRS,I,1)) THEN
        WBANTI := SUBSTR(WADRS,I);
        WADRS := SUBSTR(WADRS,1,I - 1);
        EXIT;
      END IF;
     END LOOP;
   ELSE
     NULL;
   END CASE;

  -- ⑦丁目なしの'-'が二つ以上の場合、一つ目の'-'の以前は丁目とみなす
   IF INSTR(WADRS,'丁') = 0 AND
     INSTR(WBANTI,'-') > 0 AND
     INSTR(WBANTI,'-') < INSTR(WBANTI,'-',-1) THEN
     CASE
     WHEN SUBSTR(WBANTI,2,1) = '-' THEN
      WADRS := WADRS || ASU2KSU(SUBSTR(WBANTI,1,1)) || '丁目';
      WBANTI := SUBSTR(WBANTI,3);
     WHEN SUBSTR(WBANTI, 3, 1) = '-' THEN
      WADRS := WADRS || ASU2KSU(SUBSTR(WBANTI,1,2)) || '丁目';
      WBANTI := SUBSTR(WBANTI,4);
     ELSE
      NULL;
     END CASE;
   END IF;

 --【都道府県コードの設定】
   IF WKENCD = -1 THEN
     IF SUBSTR(WADRS,1,3) = BKENMEI THEN
      WKENCD   := BKENCD;
      IF WSIKUMEI = BSIKUMEI THEN
        WSIKUCD := BSIKUCD;
      END IF;
     ELSE
      CASE
      WHEN SUBSTR(WADRS,1,3) = '北海道'  THEN
        WKENCD := 1;
      WHEN SUBSTR(WADRS,1,3) = '東京都'  THEN
        WKENCD := 13;
      WHEN SUBSTR(WADRS,1,4) = '神奈川県' THEN
        WKENCD := 14;
      WHEN SUBSTR(WADRS,1,3) = '京都府'  THEN
        WKENCD := 26;
      WHEN SUBSTR(WADRS,1,3) = '大阪府'  THEN
        WKENCD := 27;
      WHEN SUBSTR(WADRS,1,4) = '和歌山県' THEN
        WKENCD := 30;
      WHEN SUBSTR(WADRS,1,4) = '鹿児島県' THEN
        WKENCD := 46;
      WHEN SUBSTR(WADRS,3,1) = '県'    THEN
        BEGIN
         SELECT A1.KEYKENCD
          INTO WKENCD
          FROM MST_ADRS1 A1
          WHERE A1.KENMEI = SUBSTR(WADRS,1,3);
        EXCEPTION
         WHEN NO_DATA_FOUND THEN NULL;
        END;
      ELSE
        NULL;
      END CASE;
     END IF;
   END IF;

 --【市区名と字名を分離】
  -- ①例外市区名
   FOR I IN 1..IX LOOP
     IF INSTR(WADRS,REIGAI(I).SIKUMEI) > 0 AND
     ( WKENCD  = -1 OR
      WKENCD  = REIGAI(I).KEYKENCD ) THEN
      J    := INSTR(WADRS,REIGAI(I).SIKUMEI);
      L    := LENGTH(REIGAI(I).SIKUMEI);
      WSIKUMEI := SUBSTR(WADRS,1,J + L -1);
      IF REIGAI(I).KENMEIKBN = 1 THEN
        WSIKUMEI := REPLACE(WSIKUMEI,REIGAI(I).KENMEI,'');
      ELSE
        IF INSTR(WSIKUMEI,REIGAI(I).KENMEI) = 0 THEN
         WSIKUMEI := REIGAI(I).KENMEI || WSIKUMEI;
        END IF; 
      END IF;
      WAZAMEI := SUBSTR(WADRS,J + L);
      WKENCD  := REIGAI(I).KEYKENCD;
      WSIKUCD := REIGAI(I).KEYSIKUCD;
      EXIT;
     END IF;
   END LOOP;

   CASE
   WHEN WAZAMEI IS NOT NULL THEN      -- 例外市区名
     NULL;
  -- ②町で分割
   WHEN INSTR(WADRS,'郡') > 0 AND INSTR(WADRS,'町') > 0 AND
      INSTR(WADRS,'郡') < INSTR(WADRS,'町') AND
     (INSTR(WADRS,'村') < 1 OR
      INSTR(WADRS,'村') > INSTR(WADRS,'町') OR
      INSTR(WADRS,'村') < INSTR(WADRS,'郡')) THEN
     WSIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'町'));
     WAZAMEI := SUBSTR(WADRS,INSTR(WADRS,'町') + 1);

  -- ③区で分割 (郡を含む)
   WHEN INSTR(WADRS,'区') > 0 THEN
     WSIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'区'));
     WAZAMEI := SUBSTR(WADRS,INSTR(WADRS,'区') + 1);

  -- ④市で分割
   WHEN INSTR(WADRS,'市') > 0 THEN
     WSIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'市'));
     WAZAMEI := SUBSTR(WADRS,INSTR(WADRS,'市') + 1);

  -- ⑤村で分割 (郡を含む)
   WHEN INSTR(WADRS,'郡') > 0 AND INSTR(WADRS,'村') > 0 AND
      INSTR(WADRS,'郡') < INSTR(WADRS,'村') THEN
     WSIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'村'));
     WAZAMEI := SUBSTR(WADRS,INSTR(WADRS,'村') + 1);

  -- ⑥上記なし…自市区町村の字名で検索し、自市区名を補完
   ELSE
     BEGIN
      SELECT A3.KEYKENCD,A3.KEYSIKUCD,A3.KEYOAZACD,A3.KEYKOAZACD,
          DECODE(A2.KENMEIKBN,1,A2.SIKUMEI,A1.KENMEI || A2.SIKUMEI),
          A3.YUBIN
       INTO WKENCD,WSIKUCD,WOAZACD,WKOAZACD,WSIKUMEI,WYUBIN
       FROM MST_ADRS1 A1,MST_ADRS2 A2,MST_ADRS3 A3
       WHERE A3.KEYKENCD = A1.KEYKENCD
        AND A3.KEYKENCD = A2.KEYKENCD
        AND A3.KEYKENCD = MYKENCD
        AND A3.KEYSIKUCD = A2.KEYSIKUCD
        AND A3.KEYSIKUCD = MYSIKUCD
        AND A3.OAZAMEI || A3.KOAZAMEI
         = SUBSTR(WADRS,1,LENGTH(A3.OAZAMEI || A3.KOAZAMEI));
     EXCEPTION
      WHEN NO_DATA_FOUND THEN NULL;
      WHEN OTHERS THEN
        WERRMSG := SQLERRM;
        WERRNO := SQLCODE;
        DBMS_OUTPUT.PUT_LINE('ERR:' || WERRNO || ' ' || WERRMSG || ' ' || WADRS);
     END;
   END CASE;

 --【字名と番地を分割】
   IF WBANTI IS NULL THEN
     WADRS   := WAZAMEI;
     L     := LENGTH(WADRS);
     IF L > 0 THEN
      WBANTI := WADRS;
      FOR I IN REVERSE 1..L LOOP
        IF NOT ISANUMBER(SUBSTR(WADRS,I,1)) AND
         NOT ISBANTI(SUBSTR(WADRS,I,1)) THEN
         WAZAMEI := SUBSTR(WADRS,1,I);
         WBANTI := SUBSTR(WADRS,I + 1);
         EXIT;
        END IF;
      END LOOP;
     END IF;
   END IF; 
   WAZAMEI := ASU2KSU(WAZAMEI);

 --【番地と方書の分割】
   WADRS := WBANTI;
   L   := LENGTH(WADRS);
  -- ①数字と番地用漢字以外でないのは方書とする
   IF L > 0 THEN
     FOR I IN 1..L LOOP
      IF NOT ISANUMBER(SUBSTR(WADRS,I,1)) AND
        NOT ISBANTI(SUBSTR(WADRS,I,1)) THEN
        WBANTI  := SUBSTR(WADRS,1,I - 1);
        WKATAGAKI := SUBSTR(WADRS,I);
        EXIT;
      END IF;
     END LOOP;
   END IF;
 
 --【市区町村コードの設定】
  -- ①市区名で住所テーブルを検索 (県コードありなしの2パターン)
  -- 市区名も県名ありなしの2バターン
   IF WSIKUCD  = -1 THEN
     BEGIN
      IF WKENCD = -1 THEN
        SELECT A2.KEYKENCD,A2.KEYSIKUCD,
           CASE A2.KENMEIKBN
           WHEN 1 THEN
              A2.SIKUMEI
           ELSE
              A1.KENMEI || A2.SIKUMEI
           END
         INTO WKENCD,WSIKUCD,WSIKUMEI
         FROM MST_ADRS1 A1,MST_ADRS2 A2
        WHERE A2.KEYKENCD = A1.KEYKENCD
         AND A2.SIKUMEI = WSIKUMEI;
      ELSE
        SELECT A2.KEYSIKUCD,
           CASE A2.KENMEIKBN
           WHEN 1 THEN
             REPLACE(WSIKUMEI,A1.KENMEI,'')
           ELSE
             A1.KENMEI || A2.SIKUMEI
           END
         INTO WSIKUCD,WSIKUMEI FROM MST_ADRS1 A1,MST_ADRS2 A2
        WHERE A2.KEYKENCD = A1.KEYKENCD
         AND A2.KEYKENCD = WKENCD
         AND(A2.SIKUMEI = WSIKUMEI OR
           A1.KENMEI || A2.SIKUMEI = WSIKUMEI);
      END IF;
     EXCEPTION
      WHEN NO_DATA_FOUND THEN NULL;
     END;  
   END IF;

  -- ②郡名を除いた市区名で再検索
   IF WSIKUCD  = -1 AND INSTR(WSIKUMEI,'郡') > 0 THEN
     BEGIN
      IF WKENCD = -1 THEN
        SELECT A2.KEYKENCD,A2.KEYSIKUCD,
           CASE A2.KENMEIKBN
           WHEN 1 THEN
             REPLACE(WSIKUMEI,A1.KENMEI,'')
           ELSE
             A1.KENMEI || REPLACE(WSIKUMEI,A1.KENMEI,'')
           END
         INTO WKENCD,WSIKUCD,WSIKUMEI
         FROM MST_ADRS1 A1,MST_ADRS2 A2
        WHERE A2.KEYKENCD = A1.KEYKENCD
         AND A2.SIKUMEI
          = SUBSTR(WSIKUMEI,INSTR(WSIKUMEI,'郡')+ 1)
         AND A2.HAISIFLG = 0;
      ELSE
        SELECT A2.KEYKENCD,A2.KEYSIKUCD,
           CASE A2.KENMEIKBN
           WHEN 1 THEN
             REPLACE(WSIKUMEI,A1.KENMEI,'')
           ELSE
             A1.KENMEI || REPLACE(WSIKUMEI,A1.KENMEI,'')
           END
         INTO WKENCD,WSIKUCD,WSIKUMEI
         FROM MST_ADRS1 A1,MST_ADRS2 A2
        WHERE A2.KEYKENCD = A1.KEYKENCD
         AND A2.KEYKENCD = WKENCD
         AND A2.SIKUMEI
          = SUBSTR(WSIKUMEI,INSTR(WSIKUMEI,'郡')+ 1)
         AND A2.HAISIFLG = 0;
      END IF;
     EXCEPTION
      WHEN NO_DATA_FOUND THEN NULL;
      WHEN OTHERS THEN
        WERRMSG := SQLERRM;
        WERRNO := SQLCODE;
        DBMS_OUTPUT.PUT_LINE('ERR:' || WERRNO || ' ' || WERRMSG || ' ' || WADRS);
        DBMS_OUTPUT.PUT_LINE('市区名検索ERR:' || SUBSTR(WSIKUMEI,INSTR(WSIKUMEI,'郡')+ 1));
     END;  
   END IF;

  -- ③異体字での再検索…異体字を見つけたら追加する
   IF WSIKUCD = -1 THEN
     WADRS := ITAIJI(WSIKUMEI);
     IF WADRS <> WSIKUMEI THEN       -- 置換されているとき
      L := LENGTH(WADRS);
      IF INSTR(WADRS,'郡') > 0 THEN
        WADRS := SUBSTR(WADRS,INSTR(WADRS,'郡') + 1);
      END IF;
      IF INSTR(WADRS,'県') > 0 THEN
        WADRS := SUBSTR(WADRS,INSTR(WADRS,'県') + 1);
      END IF;
      WADRS := REPLACE(WADRS,'大阪府','');
      WADRS := REPLACE(WADRS,'京都府','');
      WADRS := REPLACE(WADRS,'東京都','');
      WADRS := REPLACE(WADRS,'北海道','');
     -- DBMS_OUTPUT.PUT_LINE('異体字市区名:' || WKENCD || ' ' || WADRS);
      BEGIN
        SELECT A2.KEYKENCD,A2.KEYSIKUCD,
           CASE A2.KENMEIKBN
           WHEN 1 THEN
             REPLACE(WSIKUMEI,A1.KENMEI,'')
           ELSE
             A1.KENMEI || REPLACE(WSIKUMEI,A1.KENMEI,'')
           END
         INTO WKENCD,WSIKUCD,WSIKUMEI
         FROM MST_ADRS2 A2,MST_ADRS1 A1
        WHERE A2.KEYKENCD = A2.KEYKENCD
         AND A2.KEYKENCD = WKENCD
         AND A2.SIKUMEI = WADRS
         AND ROWNUM < 2;
      -- DBMS_OUTPUT.PUT_LINE('異体字市区CD:' || WSIKUCD || ' ' || WSIKUMEI);
      EXCEPTION
        WHEN NO_DATA_FOUND THEN NULL;
      END;
     END IF;
   END IF;
   BSIKUCD   := WSIKUCD;
   BSIKUMEI  := WSIKUMEI;

   IF WAZAMEI  = BAZAMEI THEN
     WOAZACD := BOAZACD;
     WKOAZACD := BKOAZACD;
     WYUBIN  := BYUBIN;
   END IF;

 --【字コードの設定】
  -- ①県コード、市区町村コードと字名で住所テーブルを検索
   IF WKENCD <> -1 AND WSIKUCD <> -1 AND WOAZACD = '0000' THEN
     BEGIN
      SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
       INTO WYUBIN,WOAZACD,WKOAZACD
       FROM MST_ADRS3 A3
       WHERE A3.KEYKENCD = WKENCD
        AND A3.KEYSIKUCD = WSIKUCD
        AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
         = REPLACE(REPLACE(WAZAMEI,'大字',''),'字','')
        AND A3.HAISIFLG = 0;
     EXCEPTION
      WHEN NO_DATA_FOUND THEN NULL;
     END;
   END IF;

  -- ②郵便番号での検索 (但し、複数存在する時は採用しない)
   IF WOAZACD = '0000' AND WYUBIN IS NOT NULL AND WYUBIN <> '000-0000' THEN
     SELECT COUNT(*) INTO RECCNT
      FROM MST_ADRS3 A3
     WHERE A3.YUBIN = WYUBIN
      AND HAISIFLG = 0;
     IF RECCNT = 1 THEN
      SELECT A3.KEYKENCD,A3.KEYSIKUCD,A3.KEYOAZACD,A3.KEYKOAZACD
       INTO WKENCD,WSIKUCD,WOAZACD,WKOAZACD
       FROM MST_ADRS3 A3
       WHERE A3.YUBIN  = WYUBIN
        AND A3.HAISIFLG = 0;
     END IF;
   END IF;

  -- ③大字名の異体字での検索
   IF WOAZACD = '0000' AND WKENCD <> -1 AND WSIKUCD <> -1 THEN
     WADRS := ITAIJI(WAZAMEI);
     IF WADRS <> WAZAMEI THEN        -- 置換されているとき
      BEGIN
        SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
         INTO WYUBIN,WOAZACD,WKOAZACD
         FROM MST_ADRS3 A3
        WHERE A3.KEYKENCD = WKENCD
         AND A3.KEYSIKUCD = WSIKUCD
         AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
          = REPLACE(REPLACE(WADRS,'大字',''),'字','')
         AND A3.HAISIFLG = 0;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN NULL;
      END;
     END IF;
   END IF;

  -- ④丁目追加で再検索
   IF WOAZACD = '0000' AND WKENCD <> -1 AND WSIKUCD <> -1 AND
     INSTR(WAZAMEI,'丁目') < 1 AND INSTR(WBANTI,'-') > 0 THEN
     J := INSTR(WBANTI, '-');
     WADRS := WAZAMEI || ASU2KSU(SUBSTR(WBANTI,1,J - 1)) || '丁目';
     BEGIN
      SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
       INTO WYUBIN,WOAZACD,WKOAZACD
       FROM MST_ADRS3 A3
       WHERE A3.KEYKENCD = WKENCD
        AND A3.KEYSIKUCD = WSIKUCD
        AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
         = REPLACE(REPLACE(WADRS,'大字',''),'字','')
        AND A3.HAISIFLG = 0;
      WAZAMEI := WADRS;
      WBANTI := SUBSTR(WBANTI,J + 1);
     EXCEPTION
      WHEN NO_DATA_FOUND THEN NULL;
     END;   
   END IF;
   BKENCD  := WKENCD;
   BKENMEI := SUBSTR(WSIKUMEI,1,3);
   BOAZACD := WOAZACD;
   BKOAZACD := WKOAZACD;
   BAZAMEI := WAZAMEI;
   BYUBIN  := WYUBIN;

 --【番地のコード化】
   IF WBANTI IS NULL THEN
     WBANTICD := '00000000000000000000';
   ELSE 
     L := LENGTH(WBANTI);
     WADRS := WBANTI;
     K := 1;
     FOR I IN 1..L LOOP
      IF ISANUMBER(SUBSTR(WADRS,I,1)) THEN      -- 数字ならば
        TEMPBAN := TEMPBAN || TO_SINGLE_BYTE(SUBSTR(WADRS,I,1));  -- 末尾に追加する
      END IF;
      IF I = L OR NOT ISANUMBER(SUBSTR(WADRS,I,1)) THEN
        IF TEMPBAN IS NOT NULL THEN    -- 最後かセット済なら次へ
         IF K < 3 THEN
           TEMPBAN := LPAD(TEMPBAN,5,'0');
           TEMPBAN := SUBSTR(TEMPBAN,LENGTH(TEMPBAN) - 4,5);
         ELSE
           TEMPBAN := LPAD(TEMPBAN,10,'0');
           TEMPBAN := SUBSTR(TEMPBAN,LENGTH(TEMPBAN) - 9,10);
         END IF;
         WBANTICD := WBANTICD || TEMPBAN;
         TEMPBAN := NULL;
         K := K + 1;
         IF K > 3 THEN         -- フルセットなら終了
           EXIT;
         END IF; 
        END IF;
      END IF;
     END LOOP;
     WBANTICD := RPAD(WBANTICD,20,'0');
   END IF;

 --【住所分解テーブルの更新】
   UPDATE ADRS_ANALYZE
     SET YUBIN    = WYUBIN,
       TODOUFUKENCD = WKENCD,
       SICHOSONCD  = WSIKUCD,
       OAZACD    = WOAZACD,
       KOAZACD   = WKOAZACD,
       BANTICD   = WBANTICD,
       SICHOSONMEI = WSIKUMEI,
       AZAMEI    = WAZAMEI,
       BANTI    = WBANTI,
       KATAGAKI   = WKATAGAKI
    WHERE ROWID    = rec.ROWID; 
   UPDCNT := UPDCNT + 1;
   IF UPDCNT = TRUNC(UPDCNT / 100) * 100 THEN
     COMMIT;
   END IF;

  END LOOP;
  COMMIT;
 
  SELECT TO_CHAR(SYSDATE,'YYYY/MM/DD HH24:MI:SS') INTO DISPTIME FROM DUAL;
  DBMS_OUTPUT.PUT_LINE('終了時刻 ' || DISPTIME);
  DBMS_OUTPUT.PUT_LINE('更新件数 ' || UPDCNT);

END;
/

create or replace FUNCTION ASU2KSU (ASU_STR IN VARCHAR2) RETURN VARCHAR2
IS
  WK_STR VARCHAR2(60);
  I   PLS_INTEGER;
  L   PLS_INTEGER;
BEGIN
  IF ASU_STR IS NULL THEN
   RETURN NULL;
  END IF; 
  WK_STR := TRIM(TRANSLATE(ASU_STR,'1234567890','一二三四五六七八九十'));
-- 丁目漢数字の10以上編集(十を挿入)
  L   := LENGTH(WK_STR) - 1;
  IF L < 3 THEN
   RETURN WK_STR;
  END IF;
  I := 1;
  WHILE I < L LOOP
   IF ISKNUMBER(SUBSTR(WK_STR,I,1)) THEN
     IF ISKNUMBER(SUBSTR(WK_STR,I + 1,1)) THEN 
      WK_STR := SUBSTR(WK_STR,1,I) || '十' || TRIM(SUBSTR(WK_STR,I + 1,L));
      I := I + 1;
     END IF;
   END IF;
   I := I + 1;
  END LOOP;
  WK_STR := REPLACE(WK_STR,'十十','十');
  WK_STR := REPLACE(WK_STR,'一十','十');
  RETURN WK_STR;
END;
/

create or replace FUNCTION ISANUMBER (NUM_STR IN VARCHAR2) RETURN BOOLEAN
IS
BEGIN
  IF INSTR(TRANSLATE(NUM_STR,'0123456789','@@@@@@@@@@'),'@') > 0 THEN
   RETURN TRUE;
  ELSE
   RETURN FALSE;
  END IF;
END ISANUMBER;
/

create or replace FUNCTION ISBANTI (BAN_STR IN VARCHAR2) RETURN BOOLEAN
IS
  WK_STR VARCHAR2(50);
BEGIN
  WK_STR := REPLACE(REPLACE(BAN_STR,' ',''),' ','');
  WK_STR := TRANSLATE(WK_STR,'0123456789','@@@@@@@@@@');
  WK_STR := TRANSLATE(WK_STR,'番地号の-割街区部線・','@@@@@@@@@@@');
  IF LENGTH(REPLACE(WK_STR,'@','')) > 0 THEN
   RETURN FALSE;
  ELSE 
   RETURN TRUE;
  END IF; 
END ISBANTI;
/

create or replace FUNCTION ISKNUMBER (NUM_STR IN VARCHAR2) RETURN BOOLEAN
IS
BEGIN
  IF INSTR(TRANSLATE(NUM_STR,'一二三四五六七八九十','@@@@@@@@@@'),'@') > 0 THEN
   RETURN TRUE;
  ELSE
   RETURN FALSE;
  END IF;
END ISKNUMBER;
/

create or replace FUNCTION ISZNUMBER (NUM_STR IN VARCHAR2) RETURN BOOLEAN
IS
BEGIN
  IF ISANUMBER(NUM_STR) OR ISKNUMBER(NUM_STR) THEN
   RETURN TRUE;
  ELSE
   RETURN FALSE;
  END IF;
END ISZNUMBER;
/

create or replace FUNCTION ITAIJI (ITAI_STR IN VARCHAR2) RETURN VARCHAR2
IS
  SEIJ_STR VARCHAR2(32767);
BEGIN
  SEIJ_STR := ITAI_STR;
  SEIJ_STR := TRANSLATE(SEIJ_STR,'ヶッ塚斎檜與澤櫻嵩圓應參實釋條眞數淺曾臺邊槇籔藪豫',
                 'ケツ斉桧与沢桜高円応参実釈条真数瀬浅曽台辺槙薮薮予');
  IF SEIJ_STR = ITAI_STR THEN
   SEIJ_STR := TRANSLATE(SEIJ_STR,'ケツ斉桧与沢桜高円応参実釈条真数瀬浅曽台辺槙薮薮予',
                   'ヶッ塚斎檜與澤櫻嵩圓應參實釋條眞數淺曾臺邊槇籔藪豫');
  END IF;
  RETURN SEIJ_STR;
END ITAIJI;
/
名前:
コメント:

※文字化け等の原因になりますので顔文字の投稿はお控えください。

コメント利用規約に同意の上コメント投稿を行ってください。

 

※ブログ作成者から承認されるまでコメントは反映されません。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最新の画像もっと見る

最近の「PL/SQL」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事