次は、プロシージャを機能単位に分割してみました。
EXCEL VBAから、PL/SQLプロシージャを呼び出す準備です。
制御だけは、EXCEL VBAに残し、SQL発行部分はPL/SQLでさせれば速いかと・・・
ただし、PL/SQLだけの比較では、分割した方が格段に遅くなりました。
分けた為に冗長になった部分もあり、オーバーヘッドもきっとあり、
10倍くらいかかります。
create or replace PROCEDURE ANALYZE_ADRS2 IS
/**********************************************************************************/
/* 処理名:住所分解コード化処理(処理分割版) ANALYZE_ADRS2 */
/* ①住所を、市区名(県名+市区町村名)、字名(大字名+小字名)、番地、方書に分類する */
/* ②各々の構成要素ごとにコード化する(住所マスタ使用) */
/**********************************************************************************/
CURSOR csr
IS
SELECT ADRS,YUBIN,ROWID
FROM ADRS_ANALYZE
ORDER BY ADRS;
-- 制御ワーク
L PLS_INTEGER; -- 文字長
UPDCNT NUMBER; -- 更新件数
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
-- 編集ワーク
WADRS VARCHAR2(200); -- 住所中間編集ワーク
WYUBIN VARCHAR2(8); -- 郵便番号編集ワーク
WKENCD NUMBER; -- 都道府県コード
WSIKUCD NUMBER; -- 市区町村コード
WOAZACD VARCHAR2(4); -- 大字コード
WKOAZACD VARCHAR2(4); -- 小字コード
WSIKUMEI VARCHAR2(100); -- 市区町村名編集ワーク
WAZAMEI VARCHAR2(160); -- 字名編集ワーク
WKATAGAKI VARCHAR2(100); -- 方書編集ワーク
WBANTI VARCHAR2(60); -- 番地コード編集ワーク
DISPTIME VARCHAR2(20); -- 時刻編集ワーク
WBANTICD VARCHAR2(20); -- 番地コード
WREIGAI NUMBER;
-- 前データ保持
BKENCD NUMBER := 23;
BKENMEI VARCHAR2(16) := '愛知県';
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; -- 番地コード
WSIKUMEI := NULL; -- 市区町村名
WAZAMEI := NULL; -- 字名
WKATAGAKI := NULL; -- 方書
WBANTI := NULL; -- 番地
-- ①例外市区名
WADRS := rec.ADRS;
WREIGAI := -1;
FOR I IN 1..IX LOOP
IF INSTR(WADRS,REIGAI(I).SIKUMEI) > 0 THEN
WREIGAI := REIGAI(I).KEYKENCD || REIGAI(I).KEYSIKUCD;
EXIT;
END IF;
END LOOP;
--【市区町村字名と字名、番地を分離】
L := LENGTH(BSIKUMEI || BAZAMEI);
IF BSIKUMEI || BAZAMEI = SUBSTR(WADRS,1,L) THEN
WSIKUMEI := BSIKUMEI;
WAZAMEI := BAZAMEI;
WBANTI := SUBSTR(WADRS,L + 1);
ELSE
ADRS_BUNKAI(WADRS,WREIGAI,WSIKUMEI,WAZAMEI,WBANTI,WKATAGAKI);
END IF;
--【コード化】
IF WSIKUMEI = BSIKUMEI THEN
WKENCD := BKENCD;
WSIKUCD := BSIKUCD;
ELSE
ADRS_SIKUCD(WSIKUMEI,WKENCD,WSIKUCD);
END IF;
IF WAZAMEI = BAZAMEI THEN
WOAZACD := BOAZACD;
WKOAZACD := BKOAZACD;
WYUBIN := BYUBIN;
ELSE
ADRS_AZACD(WKENCD,WSIKUCD,WAZAMEI,WYUBIN,WBANTI,WOAZACD,WKOAZACD);
END IF;
IF WBANTI IS NOT NULL THEN
ADRS_BANTICD(WBANTI,WBANTICD);
ELSE
WBANTICD := '00000000000000000000';
END IF;
-- 次件比較用に退避
BKENCD := WKENCD;
BKENMEI := SUBSTR(WSIKUMEI,1,3);
BSIKUCD := WSIKUCD;
BSIKUMEI := WSIKUMEI;
BOAZACD := WOAZACD;
BKOAZACD := WKOAZACD;
BYUBIN := WYUBIN;
BAZAMEI := WAZAMEI;
--【住所分解テーブルの更新】
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 ANALYZE_ADRS2;
/
create or replace PROCEDURE ADRS_BUNKAI (P_ADRS IN VARCHAR2,
P_REIGAI IN NUMBER,
P_SIKUMEI OUT VARCHAR2,
P_AZAMEI OUT VARCHAR2,
P_BANTI OUT VARCHAR2,
P_KATAGAKI OUT VARCHAR2) IS
/**********************************************************************************/
/* 処理名:住所分解コード化処理 ADRS_BUNKAI */
/* 住所を、市区名(県名+市区町村名)、字名(大字名+小字名)、番地、方書に分類する */
/**********************************************************************************/
-- 制御ワーク
J PLS_INTEGER; -- 文字位置
L PLS_INTEGER; -- 文字長
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
-- 市区町村省略住所検索用
MYKENCD NUMBER := 25; -- 自自治体県コード(滋賀県)
MYSIKUCD NUMBER := 201; -- 自自治体市区町村コード(大津市)
-- 編集ワーク
WADRS VARCHAR2(200); -- 住所中間編集ワーク
WKENCD NUMBER; -- 都道府県コード
WSIKUCD NUMBER; -- 市区町村コード
WKENMEI VARCHAR2(16) := NULL; -- 都道府県名編集ワーク
WSIKUMEI VARCHAR2(100) := NULL; -- 市区町村名編集ワーク
WKENMEIKBN NUMBER := 0; -- 都道府県名有無区分ワーク
BEGIN
--【出力項目の初期化】
P_SIKUMEI := NULL; -- 市区町村名
P_AZAMEI := NULL; -- 字名
P_KATAGAKI := NULL; -- 方書
P_BANTI := NULL; -- 番地
--【整形処理】
-- ①全角化
WADRS := TO_MULTI_BYTE(P_ADRS);
-- ②カンマ除去
WADRS := REPLACE(WADRS,'.','');
-- ③空白除去
WADRS := REPLACE(REPLACE(WADRS,' ',''),' ','');
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
P_BANTI := SUBSTR(WADRS,J + 3);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 2));
ELSE
P_BANTI := 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
P_BANTI := SUBSTR(WADRS,J + 1);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J));
-- 条・線の前と1字後が数字なら1字後で分割
WHEN ISANUMBER(SUBSTR(WADRS,J + 2)) THEN
P_BANTI := SUBSTR(WADRS,J + 2);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
-- 条・線の前と2字後が数字なら2字後で分割
WHEN ISANUMBER(SUBSTR(WADRS,J + 3)) THEN
P_BANTI := 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
P_BANTI := 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
P_BANTI := SUBSTR(WADRS,J + 2);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
END IF;
-- ⑥アラビア数字で分割
WHEN P_BANTI IS NULL THEN -- 未分割
FOR I IN 1..L LOOP
IF ISANUMBER(SUBSTR(WADRS,I,1)) THEN
P_BANTI := SUBSTR(WADRS,I);
WADRS := SUBSTR(WADRS,1,I - 1);
EXIT;
END IF;
END LOOP;
ELSE
NULL;
END CASE;
-- ⑦丁目なしの'-'が二つ以上の場合、一つ目の'-'の以前は丁目とみなす
IF INSTR(WADRS,'丁') = 0 AND
INSTR(P_BANTI,'-') > 0 AND
INSTR(P_BANTI,'-') < INSTR(P_BANTI,'-',-1) THEN
CASE
WHEN SUBSTR(P_BANTI,2,1) = '-' THEN
WADRS := WADRS || ASU2KSU(SUBSTR(P_BANTI,1,1)) || '丁目';
P_BANTI := SUBSTR(P_BANTI,3);
WHEN SUBSTR(P_BANTI, 3, 1) = '-' THEN
WADRS := WADRS || ASU2KSU(SUBSTR(P_BANTI,1,2)) || '丁目';
P_BANTI := SUBSTR(P_BANTI,4);
ELSE
NULL;
END CASE;
END IF;
--【都道府県コードの設定】
IF WKENCD = -1 THEN
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;
--【市区名と字名を分離】
-- ①例外市区名
IF P_REIGAI <> -1 THEN
BEGIN
SELECT A2.SIKUMEI,A1.KENMEI,A2.KENMEIKBN
INTO WSIKUMEI,WKENMEI,WKENMEIKBN
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = DECODE(WKENCD,-1,WKENCD,A2.KEYKENCD)
AND A2.KEYKENCD || A2.KEYSIKUCD = P_REIGAI;
J := INSTR(WADRS,WSIKUMEI);
L := LENGTH(WSIKUMEI);
P_SIKUMEI := SUBSTR(WADRS,1,J + L -1);
IF WKENMEIKBN = 1 THEN
P_SIKUMEI := REPLACE(P_SIKUMEI,WKENMEI,'');
ELSE
P_SIKUMEI := WKENMEI || REPLACE(P_SIKUMEI,WKENMEI,'');
END IF;
P_AZAMEI := SUBSTR(WADRS,J + L);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
WHEN OTHERS THEN
WERRMSG := SQLERRM;
WERRNO := SQLCODE;
DBMS_OUTPUT.PUT_LINE('ERR:' || WERRNO || ' ' || WERRMSG || ' ' || WADRS);
END;
END IF;
CASE
WHEN P_AZAMEI 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
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'町'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'町') + 1);
-- ③区で分割 (郡を含む)
WHEN INSTR(WADRS,'区') > 0 THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'区'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'区') + 1);
-- ④市で分割
WHEN INSTR(WADRS,'市') > 0 THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'市'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'市') + 1);
-- ⑤村で分割 (郡を含む)
WHEN INSTR(WADRS,'郡') > 0 AND INSTR(WADRS,'村') > 0 AND
INSTR(WADRS,'郡') < INSTR(WADRS,'村') THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'村'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'村') + 1);
-- ⑥上記なし…自市区町村の字名で検索し、自市区名を補完
ELSE
BEGIN
SELECT DECODE(A2.KENMEIKBN,1,A2.SIKUMEI,A1.KENMEI || A2.SIKUMEI)
INTO P_SIKUMEI
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 P_BANTI IS NULL THEN
WADRS := P_AZAMEI;
L := LENGTH(WADRS);
IF L > 0 THEN
P_BANTI := WADRS;
FOR I IN REVERSE 1..L LOOP
IF NOT ISANUMBER(SUBSTR(WADRS,I,1)) AND
NOT ISBANTI(SUBSTR(WADRS,I,1)) THEN
P_AZAMEI := SUBSTR(WADRS,1,I);
P_BANTI := SUBSTR(WADRS,I + 1);
EXIT;
END IF;
END LOOP;
END IF;
END IF;
P_AZAMEI := ASU2KSU(P_AZAMEI);
--【番地と方書の分割】
WADRS := P_BANTI;
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
P_BANTI := SUBSTR(WADRS,1,I - 1);
P_KATAGAKI := SUBSTR(WADRS,I);
EXIT;
END IF;
END LOOP;
END IF;
END ADRS_BUNKAI;
/
create or replace PROCEDURE ADRS_SIKUCD (P_SIKUMEI IN OUT VARCHAR2,
P_KENCD OUT NUMBER,
P_SIKUCD OUT NUMBER) IS
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
L NUMBER;
BEGIN
P_KENCD := -1;
P_SIKUCD := -1;
P_SIKUMEI := P_SIKUMEI;
--【都道府県コードの設定】
CASE
WHEN SUBSTR(P_SIKUMEI,1,3) = '北海道' THEN
P_KENCD := 1;
WHEN SUBSTR(P_SIKUMEI,1,3) = '東京都' THEN
P_KENCD := 13;
WHEN SUBSTR(P_SIKUMEI,1,4) = '神奈川県' THEN
P_KENCD := 14;
WHEN SUBSTR(P_SIKUMEI,1,3) = '京都府' THEN
P_KENCD := 26;
WHEN SUBSTR(P_SIKUMEI,1,3) = '大阪府' THEN
P_KENCD := 27;
WHEN SUBSTR(P_SIKUMEI,1,4) = '和歌山県' THEN
P_KENCD := 30;
WHEN SUBSTR(P_SIKUMEI,1,4) = '鹿児島県' THEN
P_KENCD := 46;
WHEN SUBSTR(P_SIKUMEI,3,1) = '県' THEN
BEGIN
SELECT A1.KEYKENCD
INTO P_KENCD
FROM MST_ADRS1 A1
WHERE A1.KENMEI = SUBSTR(P_SIKUMEI,1,3);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
ELSE
NULL;
END CASE;
--【市区町村コードの設定】
-- ①市区名で住所テーブルを検索 (県コードありなしの2パターン)
-- 市区名も県名ありなしの2バターン
BEGIN
IF P_KENCD = -1 THEN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
A2.SIKUMEI
ELSE
A1.KENMEI || A2.SIKUMEI
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.SIKUMEI = P_SIKUMEI;
ELSE
SELECT A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND(A2.SIKUMEI = P_SIKUMEI OR
A1.KENMEI || A2.SIKUMEI = P_SIKUMEI);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
-- ②郡名を除いた市区名で再検索
IF P_SIKUCD = -1 AND INSTR(P_SIKUMEI,'郡') > 0 THEN
BEGIN
IF P_KENCD = -1 THEN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.SIKUMEI
= SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 1)
AND A2.HAISIFLG = 0;
ELSE
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND A2.SIKUMEI
= SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 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 || ' ' || P_SIKUMEI);
DBMS_OUTPUT.PUT_LINE('市区名検索ERR:' || SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 1));
END;
END IF;
-- ③異体字での再検索…異体字を見つけたら追加する
IF P_SIKUCD = -1 THEN
P_SIKUMEI := ITAIJI(P_SIKUMEI);
IF P_SIKUMEI <> P_SIKUMEI THEN -- 置換されているとき
L := LENGTH(P_SIKUMEI);
IF INSTR(P_SIKUMEI,'郡') > 0 THEN
P_SIKUMEI := SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡') + 1);
END IF;
IF INSTR(P_SIKUMEI,'県') > 0 THEN
P_SIKUMEI := SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'県') + 1);
END IF;
P_SIKUMEI := REPLACE(P_SIKUMEI,'大阪府','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'京都府','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'東京都','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'北海道','');
BEGIN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS2 A2,MST_ADRS1 A1
WHERE A2.KEYKENCD = A2.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND A2.SIKUMEI = P_SIKUMEI
AND ROWNUM < 2;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END IF;
END ADRS_SIKUCD;
/
create or replace PROCEDURE ADRS_AZACD (P_KENCD IN NUMBER,
P_SIKUCD IN NUMBER,
P_AZAMEI IN OUT VARCHAR2,
P_YUBIN IN OUT VARCHAR2,
P_BANTI IN OUT VARCHAR2,
P_OAZACD OUT VARCHAR2,
P_KOAZACD OUT VARCHAR2) IS
J NUMBER;
RECCNT NUMBER;
WAZAMEI VARCHAR2(160);
BEGIN
P_OAZACD := '0000';
P_KOAZACD := '0000';
-- 郵便番号の整形(XXX-XXXX)
CASE
WHEN LENGTH(P_YUBIN) = 8
AND SUBSTR(P_YUBIN, 4, 1) = '-' THEN
P_YUBIN := REPLACE(P_YUBIN,' ','0');
WHEN LENGTH(P_YUBIN) = 7
AND LENGTH(TRANSLATE(P_YUBIN,'0123456789','')) = 0 THEN
P_YUBIN := SUBSTR(P_YUBIN,1,3) || '-' || NVL(SUBSTR(P_YUBIN,-4),P_YUBIN);
ELSE
NULL;
END CASE;
--【字コードの設定】
-- ①県コード、市区町村コードと字名で住所テーブルを検索
IF P_KENCD <> -1 AND P_SIKUCD <> -1 AND P_OAZACD = '0000' THEN
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(P_AZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
-- ②郵便番号での検索 (但し、複数存在する時は採用しない)
IF P_OAZACD = '0000' AND
P_YUBIN IS NOT NULL AND
P_YUBIN <> '000-0000' THEN
SELECT COUNT(*) INTO RECCNT
FROM MST_ADRS3 A3
WHERE A3.YUBIN = P_YUBIN
AND A3.HAISIFLG = 0;
IF RECCNT = 1 THEN
SELECT A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.YUBIN = P_YUBIN
AND A3.HAISIFLG = 0;
END IF;
END IF;
-- ③大字名の異体字での検索
IF P_OAZACD = '0000' AND
P_KENCD <> -1 AND
P_SIKUCD <> -1 THEN
WAZAMEI := ITAIJI(P_AZAMEI);
IF WAZAMEI <> P_AZAMEI THEN -- 置換されているとき
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(WAZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END IF;
-- ④丁目追加で再検索
IF P_OAZACD = '0000' AND
P_KENCD <> -1 AND
P_SIKUCD <> -1 AND
INSTR(P_AZAMEI,'丁目') < 1 AND
INSTR(P_BANTI,'-') > 0 THEN
J := INSTR(P_BANTI, '-');
WAZAMEI := P_AZAMEI || ASU2KSU(SUBSTR(P_BANTI,1,J - 1)) || '丁目';
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(WAZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
P_AZAMEI := WAZAMEI;
P_BANTI := SUBSTR(P_BANTI,J + 1);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END ADRS_AZACD;
/
create or replace PROCEDURE ADRS_BANTICD (P_BANTI IN VARCHAR2,
P_BANTICD OUT VARCHAR2) IS
K PLS_INTEGER;
L PLS_INTEGER;
WBANTI VARCHAR2(60);
TEMPBAN VARCHAR2(10) := NULL; -- 番地コード編集用ワーク
BEGIN
IF P_BANTI IS NULL THEN
P_BANTICD := '00000000000000000000';
ELSE
L := LENGTH(P_BANTI);
WBANTI:= P_BANTI;
K := 1;
FOR I IN 1..L LOOP
IF ISANUMBER(SUBSTR(WBANTI,I,1)) THEN -- 数字ならば
TEMPBAN := TEMPBAN || TO_SINGLE_BYTE(SUBSTR(WBANTI,I,1)); -- 末尾に追加する
END IF;
IF I = L OR NOT ISANUMBER(SUBSTR(WBANTI,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;
P_BANTICD := P_BANTICD || TEMPBAN;
TEMPBAN := NULL;
K := K + 1;
IF K > 3 THEN -- フルセットなら終了
EXIT;
END IF;
END IF;
END IF;
END LOOP;
P_BANTICD := RPAD(P_BANTICD,20,'0');
END IF;
END ADRS_BANTICD;
/
EXCEL VBAから、PL/SQLプロシージャを呼び出す準備です。
制御だけは、EXCEL VBAに残し、SQL発行部分はPL/SQLでさせれば速いかと・・・
ただし、PL/SQLだけの比較では、分割した方が格段に遅くなりました。
分けた為に冗長になった部分もあり、オーバーヘッドもきっとあり、
10倍くらいかかります。
create or replace PROCEDURE ANALYZE_ADRS2 IS
/**********************************************************************************/
/* 処理名:住所分解コード化処理(処理分割版) ANALYZE_ADRS2 */
/* ①住所を、市区名(県名+市区町村名)、字名(大字名+小字名)、番地、方書に分類する */
/* ②各々の構成要素ごとにコード化する(住所マスタ使用) */
/**********************************************************************************/
CURSOR csr
IS
SELECT ADRS,YUBIN,ROWID
FROM ADRS_ANALYZE
ORDER BY ADRS;
-- 制御ワーク
L PLS_INTEGER; -- 文字長
UPDCNT NUMBER; -- 更新件数
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
-- 編集ワーク
WADRS VARCHAR2(200); -- 住所中間編集ワーク
WYUBIN VARCHAR2(8); -- 郵便番号編集ワーク
WKENCD NUMBER; -- 都道府県コード
WSIKUCD NUMBER; -- 市区町村コード
WOAZACD VARCHAR2(4); -- 大字コード
WKOAZACD VARCHAR2(4); -- 小字コード
WSIKUMEI VARCHAR2(100); -- 市区町村名編集ワーク
WAZAMEI VARCHAR2(160); -- 字名編集ワーク
WKATAGAKI VARCHAR2(100); -- 方書編集ワーク
WBANTI VARCHAR2(60); -- 番地コード編集ワーク
DISPTIME VARCHAR2(20); -- 時刻編集ワーク
WBANTICD VARCHAR2(20); -- 番地コード
WREIGAI NUMBER;
-- 前データ保持
BKENCD NUMBER := 23;
BKENMEI VARCHAR2(16) := '愛知県';
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; -- 番地コード
WSIKUMEI := NULL; -- 市区町村名
WAZAMEI := NULL; -- 字名
WKATAGAKI := NULL; -- 方書
WBANTI := NULL; -- 番地
-- ①例外市区名
WADRS := rec.ADRS;
WREIGAI := -1;
FOR I IN 1..IX LOOP
IF INSTR(WADRS,REIGAI(I).SIKUMEI) > 0 THEN
WREIGAI := REIGAI(I).KEYKENCD || REIGAI(I).KEYSIKUCD;
EXIT;
END IF;
END LOOP;
--【市区町村字名と字名、番地を分離】
L := LENGTH(BSIKUMEI || BAZAMEI);
IF BSIKUMEI || BAZAMEI = SUBSTR(WADRS,1,L) THEN
WSIKUMEI := BSIKUMEI;
WAZAMEI := BAZAMEI;
WBANTI := SUBSTR(WADRS,L + 1);
ELSE
ADRS_BUNKAI(WADRS,WREIGAI,WSIKUMEI,WAZAMEI,WBANTI,WKATAGAKI);
END IF;
--【コード化】
IF WSIKUMEI = BSIKUMEI THEN
WKENCD := BKENCD;
WSIKUCD := BSIKUCD;
ELSE
ADRS_SIKUCD(WSIKUMEI,WKENCD,WSIKUCD);
END IF;
IF WAZAMEI = BAZAMEI THEN
WOAZACD := BOAZACD;
WKOAZACD := BKOAZACD;
WYUBIN := BYUBIN;
ELSE
ADRS_AZACD(WKENCD,WSIKUCD,WAZAMEI,WYUBIN,WBANTI,WOAZACD,WKOAZACD);
END IF;
IF WBANTI IS NOT NULL THEN
ADRS_BANTICD(WBANTI,WBANTICD);
ELSE
WBANTICD := '00000000000000000000';
END IF;
-- 次件比較用に退避
BKENCD := WKENCD;
BKENMEI := SUBSTR(WSIKUMEI,1,3);
BSIKUCD := WSIKUCD;
BSIKUMEI := WSIKUMEI;
BOAZACD := WOAZACD;
BKOAZACD := WKOAZACD;
BYUBIN := WYUBIN;
BAZAMEI := WAZAMEI;
--【住所分解テーブルの更新】
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 ANALYZE_ADRS2;
/
create or replace PROCEDURE ADRS_BUNKAI (P_ADRS IN VARCHAR2,
P_REIGAI IN NUMBER,
P_SIKUMEI OUT VARCHAR2,
P_AZAMEI OUT VARCHAR2,
P_BANTI OUT VARCHAR2,
P_KATAGAKI OUT VARCHAR2) IS
/**********************************************************************************/
/* 処理名:住所分解コード化処理 ADRS_BUNKAI */
/* 住所を、市区名(県名+市区町村名)、字名(大字名+小字名)、番地、方書に分類する */
/**********************************************************************************/
-- 制御ワーク
J PLS_INTEGER; -- 文字位置
L PLS_INTEGER; -- 文字長
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
-- 市区町村省略住所検索用
MYKENCD NUMBER := 25; -- 自自治体県コード(滋賀県)
MYSIKUCD NUMBER := 201; -- 自自治体市区町村コード(大津市)
-- 編集ワーク
WADRS VARCHAR2(200); -- 住所中間編集ワーク
WKENCD NUMBER; -- 都道府県コード
WSIKUCD NUMBER; -- 市区町村コード
WKENMEI VARCHAR2(16) := NULL; -- 都道府県名編集ワーク
WSIKUMEI VARCHAR2(100) := NULL; -- 市区町村名編集ワーク
WKENMEIKBN NUMBER := 0; -- 都道府県名有無区分ワーク
BEGIN
--【出力項目の初期化】
P_SIKUMEI := NULL; -- 市区町村名
P_AZAMEI := NULL; -- 字名
P_KATAGAKI := NULL; -- 方書
P_BANTI := NULL; -- 番地
--【整形処理】
-- ①全角化
WADRS := TO_MULTI_BYTE(P_ADRS);
-- ②カンマ除去
WADRS := REPLACE(WADRS,'.','');
-- ③空白除去
WADRS := REPLACE(REPLACE(WADRS,' ',''),' ','');
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
P_BANTI := SUBSTR(WADRS,J + 3);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 2));
ELSE
P_BANTI := 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
P_BANTI := SUBSTR(WADRS,J + 1);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J));
-- 条・線の前と1字後が数字なら1字後で分割
WHEN ISANUMBER(SUBSTR(WADRS,J + 2)) THEN
P_BANTI := SUBSTR(WADRS,J + 2);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
-- 条・線の前と2字後が数字なら2字後で分割
WHEN ISANUMBER(SUBSTR(WADRS,J + 3)) THEN
P_BANTI := 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
P_BANTI := 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
P_BANTI := SUBSTR(WADRS,J + 2);
WADRS := ASU2KSU(SUBSTR(WADRS,1,J + 1));
END IF;
-- ⑥アラビア数字で分割
WHEN P_BANTI IS NULL THEN -- 未分割
FOR I IN 1..L LOOP
IF ISANUMBER(SUBSTR(WADRS,I,1)) THEN
P_BANTI := SUBSTR(WADRS,I);
WADRS := SUBSTR(WADRS,1,I - 1);
EXIT;
END IF;
END LOOP;
ELSE
NULL;
END CASE;
-- ⑦丁目なしの'-'が二つ以上の場合、一つ目の'-'の以前は丁目とみなす
IF INSTR(WADRS,'丁') = 0 AND
INSTR(P_BANTI,'-') > 0 AND
INSTR(P_BANTI,'-') < INSTR(P_BANTI,'-',-1) THEN
CASE
WHEN SUBSTR(P_BANTI,2,1) = '-' THEN
WADRS := WADRS || ASU2KSU(SUBSTR(P_BANTI,1,1)) || '丁目';
P_BANTI := SUBSTR(P_BANTI,3);
WHEN SUBSTR(P_BANTI, 3, 1) = '-' THEN
WADRS := WADRS || ASU2KSU(SUBSTR(P_BANTI,1,2)) || '丁目';
P_BANTI := SUBSTR(P_BANTI,4);
ELSE
NULL;
END CASE;
END IF;
--【都道府県コードの設定】
IF WKENCD = -1 THEN
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;
--【市区名と字名を分離】
-- ①例外市区名
IF P_REIGAI <> -1 THEN
BEGIN
SELECT A2.SIKUMEI,A1.KENMEI,A2.KENMEIKBN
INTO WSIKUMEI,WKENMEI,WKENMEIKBN
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = DECODE(WKENCD,-1,WKENCD,A2.KEYKENCD)
AND A2.KEYKENCD || A2.KEYSIKUCD = P_REIGAI;
J := INSTR(WADRS,WSIKUMEI);
L := LENGTH(WSIKUMEI);
P_SIKUMEI := SUBSTR(WADRS,1,J + L -1);
IF WKENMEIKBN = 1 THEN
P_SIKUMEI := REPLACE(P_SIKUMEI,WKENMEI,'');
ELSE
P_SIKUMEI := WKENMEI || REPLACE(P_SIKUMEI,WKENMEI,'');
END IF;
P_AZAMEI := SUBSTR(WADRS,J + L);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
WHEN OTHERS THEN
WERRMSG := SQLERRM;
WERRNO := SQLCODE;
DBMS_OUTPUT.PUT_LINE('ERR:' || WERRNO || ' ' || WERRMSG || ' ' || WADRS);
END;
END IF;
CASE
WHEN P_AZAMEI 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
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'町'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'町') + 1);
-- ③区で分割 (郡を含む)
WHEN INSTR(WADRS,'区') > 0 THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'区'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'区') + 1);
-- ④市で分割
WHEN INSTR(WADRS,'市') > 0 THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'市'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'市') + 1);
-- ⑤村で分割 (郡を含む)
WHEN INSTR(WADRS,'郡') > 0 AND INSTR(WADRS,'村') > 0 AND
INSTR(WADRS,'郡') < INSTR(WADRS,'村') THEN
P_SIKUMEI := SUBSTR(WADRS,1,INSTR(WADRS,'村'));
P_AZAMEI := SUBSTR(WADRS,INSTR(WADRS,'村') + 1);
-- ⑥上記なし…自市区町村の字名で検索し、自市区名を補完
ELSE
BEGIN
SELECT DECODE(A2.KENMEIKBN,1,A2.SIKUMEI,A1.KENMEI || A2.SIKUMEI)
INTO P_SIKUMEI
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 P_BANTI IS NULL THEN
WADRS := P_AZAMEI;
L := LENGTH(WADRS);
IF L > 0 THEN
P_BANTI := WADRS;
FOR I IN REVERSE 1..L LOOP
IF NOT ISANUMBER(SUBSTR(WADRS,I,1)) AND
NOT ISBANTI(SUBSTR(WADRS,I,1)) THEN
P_AZAMEI := SUBSTR(WADRS,1,I);
P_BANTI := SUBSTR(WADRS,I + 1);
EXIT;
END IF;
END LOOP;
END IF;
END IF;
P_AZAMEI := ASU2KSU(P_AZAMEI);
--【番地と方書の分割】
WADRS := P_BANTI;
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
P_BANTI := SUBSTR(WADRS,1,I - 1);
P_KATAGAKI := SUBSTR(WADRS,I);
EXIT;
END IF;
END LOOP;
END IF;
END ADRS_BUNKAI;
/
create or replace PROCEDURE ADRS_SIKUCD (P_SIKUMEI IN OUT VARCHAR2,
P_KENCD OUT NUMBER,
P_SIKUCD OUT NUMBER) IS
WERRMSG VARCHAR2(255); -- エラーメッセージ
WERRNO NUMBER; -- エラー№
L NUMBER;
BEGIN
P_KENCD := -1;
P_SIKUCD := -1;
P_SIKUMEI := P_SIKUMEI;
--【都道府県コードの設定】
CASE
WHEN SUBSTR(P_SIKUMEI,1,3) = '北海道' THEN
P_KENCD := 1;
WHEN SUBSTR(P_SIKUMEI,1,3) = '東京都' THEN
P_KENCD := 13;
WHEN SUBSTR(P_SIKUMEI,1,4) = '神奈川県' THEN
P_KENCD := 14;
WHEN SUBSTR(P_SIKUMEI,1,3) = '京都府' THEN
P_KENCD := 26;
WHEN SUBSTR(P_SIKUMEI,1,3) = '大阪府' THEN
P_KENCD := 27;
WHEN SUBSTR(P_SIKUMEI,1,4) = '和歌山県' THEN
P_KENCD := 30;
WHEN SUBSTR(P_SIKUMEI,1,4) = '鹿児島県' THEN
P_KENCD := 46;
WHEN SUBSTR(P_SIKUMEI,3,1) = '県' THEN
BEGIN
SELECT A1.KEYKENCD
INTO P_KENCD
FROM MST_ADRS1 A1
WHERE A1.KENMEI = SUBSTR(P_SIKUMEI,1,3);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
ELSE
NULL;
END CASE;
--【市区町村コードの設定】
-- ①市区名で住所テーブルを検索 (県コードありなしの2パターン)
-- 市区名も県名ありなしの2バターン
BEGIN
IF P_KENCD = -1 THEN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
A2.SIKUMEI
ELSE
A1.KENMEI || A2.SIKUMEI
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.SIKUMEI = P_SIKUMEI;
ELSE
SELECT A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND(A2.SIKUMEI = P_SIKUMEI OR
A1.KENMEI || A2.SIKUMEI = P_SIKUMEI);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
-- ②郡名を除いた市区名で再検索
IF P_SIKUCD = -1 AND INSTR(P_SIKUMEI,'郡') > 0 THEN
BEGIN
IF P_KENCD = -1 THEN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.SIKUMEI
= SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 1)
AND A2.HAISIFLG = 0;
ELSE
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS1 A1,MST_ADRS2 A2
WHERE A2.KEYKENCD = A1.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND A2.SIKUMEI
= SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 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 || ' ' || P_SIKUMEI);
DBMS_OUTPUT.PUT_LINE('市区名検索ERR:' || SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡')+ 1));
END;
END IF;
-- ③異体字での再検索…異体字を見つけたら追加する
IF P_SIKUCD = -1 THEN
P_SIKUMEI := ITAIJI(P_SIKUMEI);
IF P_SIKUMEI <> P_SIKUMEI THEN -- 置換されているとき
L := LENGTH(P_SIKUMEI);
IF INSTR(P_SIKUMEI,'郡') > 0 THEN
P_SIKUMEI := SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'郡') + 1);
END IF;
IF INSTR(P_SIKUMEI,'県') > 0 THEN
P_SIKUMEI := SUBSTR(P_SIKUMEI,INSTR(P_SIKUMEI,'県') + 1);
END IF;
P_SIKUMEI := REPLACE(P_SIKUMEI,'大阪府','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'京都府','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'東京都','');
P_SIKUMEI := REPLACE(P_SIKUMEI,'北海道','');
BEGIN
SELECT A2.KEYKENCD,A2.KEYSIKUCD,
CASE A2.KENMEIKBN
WHEN 1 THEN
REPLACE(P_SIKUMEI,A1.KENMEI,'')
ELSE
A1.KENMEI || REPLACE(P_SIKUMEI,A1.KENMEI,'')
END
INTO P_KENCD,P_SIKUCD,P_SIKUMEI
FROM MST_ADRS2 A2,MST_ADRS1 A1
WHERE A2.KEYKENCD = A2.KEYKENCD
AND A2.KEYKENCD = P_KENCD
AND A2.SIKUMEI = P_SIKUMEI
AND ROWNUM < 2;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END IF;
END ADRS_SIKUCD;
/
create or replace PROCEDURE ADRS_AZACD (P_KENCD IN NUMBER,
P_SIKUCD IN NUMBER,
P_AZAMEI IN OUT VARCHAR2,
P_YUBIN IN OUT VARCHAR2,
P_BANTI IN OUT VARCHAR2,
P_OAZACD OUT VARCHAR2,
P_KOAZACD OUT VARCHAR2) IS
J NUMBER;
RECCNT NUMBER;
WAZAMEI VARCHAR2(160);
BEGIN
P_OAZACD := '0000';
P_KOAZACD := '0000';
-- 郵便番号の整形(XXX-XXXX)
CASE
WHEN LENGTH(P_YUBIN) = 8
AND SUBSTR(P_YUBIN, 4, 1) = '-' THEN
P_YUBIN := REPLACE(P_YUBIN,' ','0');
WHEN LENGTH(P_YUBIN) = 7
AND LENGTH(TRANSLATE(P_YUBIN,'0123456789','')) = 0 THEN
P_YUBIN := SUBSTR(P_YUBIN,1,3) || '-' || NVL(SUBSTR(P_YUBIN,-4),P_YUBIN);
ELSE
NULL;
END CASE;
--【字コードの設定】
-- ①県コード、市区町村コードと字名で住所テーブルを検索
IF P_KENCD <> -1 AND P_SIKUCD <> -1 AND P_OAZACD = '0000' THEN
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(P_AZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
-- ②郵便番号での検索 (但し、複数存在する時は採用しない)
IF P_OAZACD = '0000' AND
P_YUBIN IS NOT NULL AND
P_YUBIN <> '000-0000' THEN
SELECT COUNT(*) INTO RECCNT
FROM MST_ADRS3 A3
WHERE A3.YUBIN = P_YUBIN
AND A3.HAISIFLG = 0;
IF RECCNT = 1 THEN
SELECT A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.YUBIN = P_YUBIN
AND A3.HAISIFLG = 0;
END IF;
END IF;
-- ③大字名の異体字での検索
IF P_OAZACD = '0000' AND
P_KENCD <> -1 AND
P_SIKUCD <> -1 THEN
WAZAMEI := ITAIJI(P_AZAMEI);
IF WAZAMEI <> P_AZAMEI THEN -- 置換されているとき
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(WAZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END IF;
-- ④丁目追加で再検索
IF P_OAZACD = '0000' AND
P_KENCD <> -1 AND
P_SIKUCD <> -1 AND
INSTR(P_AZAMEI,'丁目') < 1 AND
INSTR(P_BANTI,'-') > 0 THEN
J := INSTR(P_BANTI, '-');
WAZAMEI := P_AZAMEI || ASU2KSU(SUBSTR(P_BANTI,1,J - 1)) || '丁目';
BEGIN
SELECT A3.YUBIN,A3.KEYOAZACD,A3.KEYKOAZACD
INTO P_YUBIN,P_OAZACD,P_KOAZACD
FROM MST_ADRS3 A3
WHERE A3.KEYKENCD = P_KENCD
AND A3.KEYSIKUCD = P_SIKUCD
AND REPLACE(REPLACE(A3.OAZAMEI || A3.KOAZAMEI,'大字',''),'字','')
= REPLACE(REPLACE(WAZAMEI,'大字',''),'字','')
AND A3.HAISIFLG = 0;
P_AZAMEI := WAZAMEI;
P_BANTI := SUBSTR(P_BANTI,J + 1);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END IF;
END ADRS_AZACD;
/
create or replace PROCEDURE ADRS_BANTICD (P_BANTI IN VARCHAR2,
P_BANTICD OUT VARCHAR2) IS
K PLS_INTEGER;
L PLS_INTEGER;
WBANTI VARCHAR2(60);
TEMPBAN VARCHAR2(10) := NULL; -- 番地コード編集用ワーク
BEGIN
IF P_BANTI IS NULL THEN
P_BANTICD := '00000000000000000000';
ELSE
L := LENGTH(P_BANTI);
WBANTI:= P_BANTI;
K := 1;
FOR I IN 1..L LOOP
IF ISANUMBER(SUBSTR(WBANTI,I,1)) THEN -- 数字ならば
TEMPBAN := TEMPBAN || TO_SINGLE_BYTE(SUBSTR(WBANTI,I,1)); -- 末尾に追加する
END IF;
IF I = L OR NOT ISANUMBER(SUBSTR(WBANTI,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;
P_BANTICD := P_BANTICD || TEMPBAN;
TEMPBAN := NULL;
K := K + 1;
IF K > 3 THEN -- フルセットなら終了
EXIT;
END IF;
END IF;
END IF;
END LOOP;
P_BANTICD := RPAD(P_BANTICD,20,'0');
END IF;
END ADRS_BANTICD;
/