郵便番号データから都道府県・市町村リストを作成するためのスクリプト


#前提となるテーブル定義#

```sql
CREATE TABLE `mst_address` (
  `officialCode` char(11) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '全国地方公共団体コード(JIS X0401、X0402)',
  `postalCode5` char(5) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '(旧)郵便番号(5桁)',
  `postalCode7` char(7) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '郵便番号(7桁)',
  `kana_pref` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '都道府県名（カタカナ）',
  `kana_city` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '市区町村名（カタカナ）',
  `kana_town` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '町域名（カタカナ）',
  `pref` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '都道府県名',
  `city` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '市区町村名',
  `town` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '町域名',
  `flag_doubleCode` tinyint(1) NOT NULL COMMENT '一町域が二以上の郵便番号で表される場合の表示　(注3)　(「1」は該当、「0」は該当せず)',
  `flag_banchi` tinyint(1) NOT NULL COMMENT '小字毎に番地が起番されている町域の表示　(注4)　(「1」は該当、「0」は該当せず)',
  `flag_chome` tinyint(1) NOT NULL COMMENT '丁目を有する町域の場合の表示　(「1」は該当、「0」は該当せず)',
  `flag_double_area` tinyint(1) NOT NULL COMMENT '一つの郵便番号で二以上の町域を表す場合の表示　(注5)　(「1」は該当、「0」は該当せず)',
  `flag_update` int(1) NOT NULL COMMENT '更新の表示（注6）（「0」は変更なし、「1」は変更あり、「2」廃止（廃止データのみ使用））',
  `flag_update_reason` int(1) NOT NULL COMMENT '変更理由　(「0」は変更なし、「1」市政・区政・町政・分区・政令指定都市施行、「2」住居表示の実施、「3」区画整理、「4」郵便区調整等、「5」訂正、「6」廃止(廃止データのみ使用))',
  KEY `postalCode7` (`postalCode7`),
  KEY `postalCode5` (`postalCode5`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='[Master]郵便番号データファイル';
```

```sql
CREATE TABLE `mst_address_mini` (
  `officialCode` int(5) unsigned zerofill NOT NULL COMMENT '全国地方公共団体コード(JIS X0401、X0402)',
  `pref` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '都道府県名',
  `city` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '市区町村名',
  PRIMARY KEY (`officialCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='[Master]住所コード（縮小版）';
```

#データ作成#

```bash
#!/bin/bash

DBUSER=
DBPASS=
DBNAME=

echo "Downloading..."
wget -q http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip

echo 'Melting...'
unzip -o -q ken_all.zip

echo "Convert SJIS to UTF8"
nkf -w KEN_ALL.CSV > mst_address.csv

# 元ファイルを削除
rm -f KEN_ALL.CSV

echo 'Importing to MySQL'
mysqlimport -s -u ${DBUSER} -p${DBPASS} --local --delete --fields-terminated-by=, --fields-enclosed-by="\"" --fields-escaped-by="\\" --lines-terminated-by="\r\n" ${DBNAME} mst_address.csv;
mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "TRUNCATE mst_address_mini;INSERT INTO mst_address_mini SELECT officialCode, pref, city FROM mst_address GROUP BY officialCode"

# CSV削除
rm -f KEN_ALL.CSV
rm -f mst_address.csv
rm -f ken_all.zip
```

jQuery を利用する前提です。

```javascript:javascript
$(function () {
	var parent = $(".ajax-pref");
	var child = $(".ajax-city");
	parent.on("change", function () {
		var selectedPrefCode = $(this).val();
		var param = {
			pref: selectedPrefCode
		};
		child.html('<option value="-1">-- 市区郡選択 --</option>');
		var defaultCityCode = ("" != child.attr("default")) ? child.attr("default") : -1;

		if (-1 != selectedPrefCode) {
			$.getJSON("/ajax/getcity.php", param, function (json) {
				$.each(json, function (i) {
					child.append(
							'<option value="' + json[i].code + '">' +
							json[i].name + '</option>');
				});
				child.val(defaultCityCode);
			});
		}
	}).change();
});
```

```html:html
<select name="pref" class="ajax-pref">
<option value="-1">都道府県</option>
<option value="1">北海道</option>
<option value="2">青森</option>
…
<option value="47">沖縄県</option>
</select>

<select name="city" class="ajax-city">
<option value="-1">市区郡</option>
</select>
```
#ajax/getcity.php#

```php:php
<?php
try {
	$strPrefCode = filter_input(INPUT_GET, 'pref');

	$sql = "SELECT ";
	$sql .= "`officialCode` as `code` ";
	$sql .= ", `city` as `name` ";
	$sql .= "FROM `mst_address_mini` ";
	$sql .= "WHERE 1 ";
	$sql .= "AND SUBSTRING(`officialCode`, 1, 2) = :officialCode ";
	$arr = array();
	$arr[':officialCode'] = $strPrefCode;

	$objPdo = new \PDO('mysql:dbname=testdb;host=localhost;charset=utf8'
		, $username
		, $passwd
		, array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));

	$stmt = $objPdo->prepare($sql);
	$stmt->execute($arr);
	$res = $stmt->fetchAll();
} catch (Exception $e) {
	$res = array(
		'error' => $e->getMessage()
		, 'code' => $e->getCode()
	);
} finally {
	header('Content-type: application/json');
	echo json_encode($res);
}
```

利用データはこれ[郵便番号データダウンロード](http://www.post.japanpost.jp/zipcode/download.html)