목표 데이터 베이스 구조

공공데이터포털에서 기본으로 제공되는 csv파일은 현재 폐지된 주소까지 알려준다. 그런데 폐지유무는 표시해주지않아 중복된 주소가 많아 사용하기 힘들다.
대신 국토교통부에서 제공해주는 데이터를 이용하면 폐지유무를 쉽게 알 수 있다.
https://www.code.go.kr/stdcode/regCodeL.do

위와 같은 텍스트 파일을 제공해준다.
이것을 변환하여 사용하면 된다.
방법1(id동적부여)
#### 이 코드는 중복처리와 id조회를 디비에서 진행하기 때문에 디비에 데이터가 들어있어도 사용할 수 있다. 하지만 디비에서 중복조회를 하고 쿼리가 각각 들어가 디비에 무리가 갈 수 있다.
###### 장점: id가 동적으로 정해진다. 디비에 데이터가 있어도 적용가능하다.
###### 단점: 디비에 비교적 무리가 갈 수 있다. 느리다.
import pandas as pd
# 텍스트 파일을 CSV 파일로 변환
def text_to_csv(text_file_path, csv_path):
# 텍스트 파일을 데이터프레임으로 읽기
df = pd.read_csv(text_file_path, sep='\t', names=["법정동코드", "법정동명", "폐지여부"])
# 폐지여부가 "폐지"인 행은 삭제
df = df[df['폐지여부'] != '폐지']
# 법정동명을 띄어쓰기 기준으로 나누어 시도, 시군구, 읍명동으로 분할
split_result = df['법정동명'].str.split(n=2, expand=True)
df['시도명'] = split_result[0]
df['시군구명'] = split_result[1]
df['읍면동명'] = split_result[2].str.split().str[0] # 읍면동의 앞부분만 선택
# null 값이 들어가 있는 행 삭제
df.dropna(inplace=True)
# '시도명', '시군구명', '읍면동명'이 동일한 행 중에서 맨 위의 행만 남김
df = df.drop_duplicates(subset=['시도명', '시군구명', '읍면동명'], keep='first')
# 결과 데이터프레임을 CSV 파일로 저장
df.to_csv(csv_path, index=False, encoding='utf-8')
print("CSV 파일 생성완료")
def csv_to_sql(csv_path, sql_path):
# CSV 파일 읽기
df = pd.read_csv('법정동코드.csv')
# SQL 문을 저장할 파일 열기
with open('법정동코드.sql', 'w') as sql_file:
# city_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
"""
sql_file.write(sql_statement)
# country_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
"""
sql_file.write(sql_statement)
# district_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
"""
sql_file.write(sql_statement)
# 데이터 삽입 코드 작성
for index, row in df.iterrows():
# 시도 테이블에 데이터 삽입 (중복 무시)
sql_statement = f"INSERT INTO city_tb (name) SELECT '{row['시도명']}' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '{row['시도명']}');\n"
# 시도명에 해당하는 id 가져오기
sql_statement += f"SET @city_id = (SELECT id FROM city_tb WHERE name = '{row['시도명']}');\n"
# 시군구 테이블에 데이터 삽입 (중복 확인)
sql_statement += f"INSERT INTO country_tb (city_id, name) SELECT @city_id, '{row['시군구명']}' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}');\n"
# 읍면동 테이블에 데이터 삽입 (중복 확인)
sql_statement += f"INSERT INTO district_tb (statutory_code, country_id, name) SELECT {row['법정동코드']}, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}'), '{row['읍면동명']}' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}') AND name = '{row['읍면동명']}');\n"
# SQL 문을 파일에 쓰기
sql_file.write(sql_statement)
print("SQL 파일 생성완료")
if __name__ == "__main__":
text_file_path = '법정동코드.txt'
csv_path = '법정동코드.csv'
sql_path = '법정동코드.sql'
# 텍스트 파일을 CSV 파일로 변환
text_to_csv(text_file_path, csv_path)
# CSV 파일을 SQL파일로 변환
csv_to_sql(csv_path,sql_path)
파싱된 csv파일

생성된 sql문 일부
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010100, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '청운동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '청운동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010200, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '신교동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '신교동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010300, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '궁정동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '궁정동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010400, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '효자동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '효자동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010500, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '창성동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '창성동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010600, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '통의동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '통의동');
DB에 목적대로 잘 들어가는 것을 볼 수 있다.



방법1(id동적부여)
######### 이 코드는 id를 미리 정하여서 sql문을 생성하기 때문에 서버실행시에 맨 처음 데이터를 주입하여야 한다.
######### 장점: 빠름
######### 단점: id가 정해져 있어 초기실행시 맨 처음 데이터가 들어가야함
import pandas as pd
# 텍스트 파일을 CSV 파일로 변환
def text_to_csv(text_file_path, csv_path):
# 텍스트 파일을 데이터프레임으로 읽기
df = pd.read_csv(text_file_path, sep='\\t', names=["법정동코드", "법정동명", "폐지여부"])
# 폐지여부가 "폐지"인 행은 삭제
df = df[df['폐지여부'] != '폐지']
# 법정동명을 띄어쓰기 기준으로 나누어 시도, 시군구, 읍명동으로 분할
split_result = df['법정동명'].str.split(n=2, expand=True)
df['시도명'] = split_result[0]
df['시군구명'] = split_result[1]
df['읍면동명'] = split_result[2].str.split().str[0] # 읍면동의 앞부분만 선택
# null 값이 들어가 있는 행 삭제
df.dropna(inplace=True)
# '시도명', '시군구명', '읍면동명'이 동일한 행 중에서 맨 위의 행만 남김
df = df.drop_duplicates(subset=['시도명', '시군구명', '읍면동명'], keep='first')
# 결과 데이터프레임을 CSV 파일로 저장
df.to_csv(csv_path, index=False, encoding='utf-8')
print("CSV 파일 생성완료")
def csv_to_sql(csv_path, sql_path):
# CSV 파일 읽기
df = pd.read_csv('법정동코드.csv')
# SQL 문을 저장할 파일 열기
with open('법정동코드.sql', 'w') as sql_file:
# city_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
"""
sql_file.write(sql_statement)
# country_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
"""
sql_file.write(sql_statement)
# district_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
"""
sql_file.write(sql_statement)
city_list=[]
country_list= []
district_list= []
city_sql = "INSERT INTO city_tb (name) VALUES \\n"
country_sql = "INSERT INTO country_tb (city_id, name) VALUES \\n"
district_sql = "INSERT INTO district_tb (statutory_code, country_id, name) VALUES \\n"
# 데이터 삽입 코드 작성
for index, row in df.iterrows():
statutory_code = row['법정동코드']
city_name = row['시도명']
country_name = row['시군구명']
district_name = row['읍면동명']
#시도명 중복처리 및 시도명id 설정
if city_name not in city_list:
city_list.append(city_name)
city_sql += f"('{city_name}'),\\n"
city_id= city_list.index(city_name)+1
#시군구 중복처리 및 시군구id설정
if (city_id,country_name) not in country_list:
country_list.append((city_id,country_name))
country_sql += f"({city_id}, '{country_name}'),\\n"
country_id = country_list.index((city_id,country_name))+1
if (country_id,district_name) not in district_list:
district_list.append((country_id,district_name))
district_sql += f"({statutory_code}, {country_id}, '{district_name}'),\\n"
district_id = district_list.index((country_id,district_name))+1
city_sql = city_sql.rstrip(',\\n') + ";\\n"
country_sql = country_sql.rstrip(',\\n') + ";\\n"
district_sql = district_sql.rstrip(',\\n') + ";\\n"
# SQL 문을 파일에 쓰기
sql_file.write("\\n")
sql_file.write(city_sql)
sql_file.write(country_sql)
sql_file.write(district_sql)
print("SQL 파일 생성완료")
if __name__ == "__main__":
text_file_path = '법정동코드.txt'
csv_path = '법정동코드.csv'
sql_path = '법정동코드.sql'
# 텍스트 파일을 CSV 파일로 변환
text_to_csv(text_file_path, csv_path)
# CSV 파일을 SQL파일로 변환
csv_to_sql(csv_path,sql_path)
실행결과 sql
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
INSERT INTO city_tb (name) VALUES
('서울특별시'),
('부산광역시'),
('대구광역시'),
('인천광역시'),
('광주광역시'),
('대전광역시'),
('울산광역시'),
('세종특별자치시'),
('경기도'),
('충청북도'),
('충청남도'),
('전라북도'),
('전라남도'),
('경상북도'),
('경상남도'),
('제주특별자치도'),
('강원특별자치도');
INSERT INTO country_tb (city_id, name) VALUES
(1, '종로구'),
(1, '중구'),
(1, '용산구'),
(1, '성동구'),
(1, '광진구'),
(1, '동대문구'),
(1, '중랑구'),
(1, '성북구'),
(1, '강북구'),
(1, '도봉구'),
(1, '노원구'),
(1, '은평구'),
(1, '서대문구'),
(1, '마포구'),
(1, '양천구'),
(1, '강서구'),
(1, '구로구'),
(1, '금천구'),
(1, '영등포구'),
(1, '동작구'),
(1, '관악구'),
(1, '서초구'),
(1, '강남구'),
(1, '송파구'),
(1, '강동구'),
(2, '중구'),
(2, '서구'),
(2, '동구'),
(2, '영도구'),
(2, '부산진구'),
(2, '동래구'),
(2, '남구'),
(2, '북구'),
(2, '해운대구'),
(2, '사하구'),
(2, '금정구'),
(2, '강서구'),
(2, '연제구'),
(2, '수영구'),
(2, '사상구'),
(2, '기장군'),
(3, '중구'),
(3, '동구'),
(3, '서구'),
(3, '남구'),
(3, '북구'),
(3, '수성구'),
(3, '달서구'),
(3, '달성군'),
(3, '군위군'),
(4, '중구'),
(4, '동구'),
(4, '미추홀구'),
(4, '연수구'),
(4, '남동구'),
(4, '부평구'),
(4, '계양구'),
(4, '서구'),
(4, '강화군'),
(4, '옹진군'),
(5, '동구'),
(5, '서구'),
(5, '남구'),
(5, '북구'),
(5, '광산구'),
(6, '동구'),
(6, '중구'),
(6, '서구'),
(6, '유성구'),
(6, '대덕구'),
(7, '중구'),
(7, '남구'),
(7, '동구'),
(7, '북구'),
(7, '울주군'),
(8, '조치원읍'),
(8, '연기면'),
(8, '연동면'),
(8, '부강면'),
(8, '금남면'),
(8, '장군면'),
(8, '연서면'),
(8, '전의면'),
(8, '전동면'),
(8, '소정면'),
(9, '수원시'),
(9, '성남시'),
(9, '의정부시'),
(9, '안양시'),
(9, '부천시'),
(9, '광명시'),
(9, '평택시'),
(9, '동두천시'),
(9, '안산시'),
(9, '고양시'),
(9, '과천시'),
(9, '구리시'),
(9, '남양주시'),
(9, '오산시'),
(9, '시흥시'),
(9, '군포시'),
(9, '의왕시'),
(9, '하남시'),
(9, '용인시'),
(9, '파주시'),
(9, '이천시'),
(9, '안성시'),
(9, '김포시'),
(9, '화성시'),
(9, '광주시'),
(9, '양주시'),
(9, '포천시'),
(9, '여주시'),
(9, '연천군'),
(9, '가평군'),
(9, '양평군'),
(10, '청주시'),
(10, '충주시'),
(10, '제천시'),
(10, '보은군'),
(10, '옥천군'),
(10, '영동군'),
(10, '증평군'),
(10, '진천군'),
(10, '괴산군'),
(10, '음성군'),
(10, '단양군'),
(11, '천안시'),
(11, '공주시'),
(11, '보령시'),
(11, '아산시'),
(11, '서산시'),
(11, '논산시'),
(11, '계룡시'),
(11, '당진시'),
(11, '금산군'),
(11, '부여군'),
(11, '서천군'),
(11, '청양군'),
(11, '홍성군'),
(11, '예산군'),
(11, '태안군'),
(12, '전주시'),
(12, '군산시'),
(12, '익산시'),
(12, '정읍시'),
(12, '남원시'),
(12, '김제시'),
(12, '완주군'),
(12, '진안군'),
(12, '무주군'),
(12, '장수군'),
(12, '임실군'),
(12, '순창군'),
(12, '고창군'),
(12, '부안군'),
(13, '목포시'),
(13, '여수시'),
(13, '순천시'),
(13, '나주시'),
(13, '광양시'),
(13, '담양군'),
(13, '곡성군'),
(13, '구례군'),
(13, '고흥군'),
(13, '보성군'),
(13, '화순군'),
(13, '장흥군'),
(13, '강진군'),
(13, '해남군'),
(13, '영암군'),
(13, '무안군'),
(13, '함평군'),
(13, '영광군'),
(13, '장성군'),
(13, '완도군'),
(13, '진도군'),
(13, '신안군'),
(14, '포항시'),
(14, '경주시'),
(14, '김천시'),
(14, '안동시'),
(14, '구미시'),
(14, '영주시'),
(14, '영천시'),
(14, '상주시'),
(14, '문경시'),
(14, '경산시'),
(14, '의성군'),
(14, '청송군'),
(14, '영양군'),
(14, '영덕군'),
(14, '청도군'),
(14, '고령군'),
(14, '성주군'),
(14, '칠곡군'),
(14, '예천군'),
(14, '봉화군'),
(14, '울진군'),
(14, '울릉군'),
(15, '창원시'),
(15, '진주시'),
(15, '통영시'),
(15, '사천시'),
(15, '김해시'),
(15, '밀양시'),
(15, '거제시'),
(15, '양산시'),
(15, '의령군'),
(15, '함안군'),
(15, '창녕군'),
(15, '고성군'),
(15, '남해군'),
(15, '하동군'),
(15, '산청군'),
(15, '함양군'),
(15, '거창군'),
(15, '합천군'),
(16, '제주시'),
(16, '서귀포시'),
(17, '춘천시'),
(17, '원주시'),
(17, '강릉시'),
(17, '동해시'),
(17, '태백시'),
(17, '속초시'),
(17, '삼척시'),
(17, '홍천군'),
(17, '횡성군'),
(17, '영월군'),
(17, '평창군'),
(17, '정선군'),
(17, '철원군'),
(17, '화천군'),
(17, '양구군'),
(17, '인제군'),
(17, '고성군'),
(17, '양양군');
INSERT INTO district_tb (statutory_code, country_id, name) VALUES
(1111010100, 1, '청운동'),
(1111010200, 1, '신교동'),
(1111010300, 1, '궁정동'),
(1111010400, 1, '효자동'),
(1111010500, 1, '창성동'),
(1111010600, 1, '통의동'),
(1111010700, 1, '적선동'),
(1111010800, 1, '통인동'),
(1111010900, 1, '누상동'),
(1111011000, 1, '누하동'),
(1111011100, 1, '옥인동'),
(1111011200, 1, '체부동'),
(1111011300, 1, '필운동'),
(1111011400, 1, '내자동'),
(1111011500, 1, '사직동'),
(1111011600, 1, '도렴동'),
(1111011700, 1, '당주동'),
(1111011800, 1, '내수동'),
(1111011900, 1, '세종로'),
(1111012000, 1, '신문로1가'),
(1111012100, 1, '신문로2가'),
(1111012200, 1, '청진동'),
(1111012300, 1, '서린동'),
(1111012400, 1, '수송동'),
(1111012500, 1, '중학동'),
(1111012600, 1, '종로1가'),
(1111012700, 1, '공평동'),
(1111012800, 1, '관훈동'),
(1111012900, 1, '견지동'),
(1111013000, 1, '와룡동'),
(1111013100, 1, '권농동'),
(1111013200, 1, '운니동'),
(1111013300, 1, '익선동'),
(1111013400, 1, '경운동'),
(1111013500, 1, '관철동'),
(1111013600, 1, '인사동'),
(1111013700, 1, '낙원동'),
(1111013800, 1, '종로2가'),
(1111013900, 1, '팔판동'),
(1111014000, 1, '삼청동'),
(1111014100, 1, '안국동'),
(1111014200, 1, '소격동'),
(1111014300, 1, '화동'),
(1111014400, 1, '사간동'),
(1111014500, 1, '송현동'),
(1111014600, 1, '가회동'),
(1111014700, 1, '재동'),
(1111014800, 1, '계동'),
(1111014900, 1, '원서동'),
(1111015000, 1, '훈정동'),
(1111015100, 1, '묘동'),
(1111015200, 1, '봉익동'),
(1111015300, 1, '돈의동'),
(1111015400, 1, '장사동'),
(1111015500, 1, '관수동'),
(1111015600, 1, '종로3가'),
....
https://github.com/yunzae/districtCodeTextToSql
GitHub - yunzae/districtCodeTextToSql: 대한민국 법정동 코드를 DB에 넣기 위한 sql변환기
대한민국 법정동 코드를 DB에 넣기 위한 sql변환기. Contribute to yunzae/districtCodeTextToSql development by creating an account on GitHub.
github.com
GitHub - yunzae/districtCodeTextToSql: 대한민국 법정동 코드를 DB에 넣기 위한 sql변환기
대한민국 법정동 코드를 DB에 넣기 위한 sql변환기. Contribute to yunzae/districtCodeTextToSql development by creating an account on GitHub.
github.com
목표 데이터 베이스 구조

공공데이터포털에서 기본으로 제공되는 csv파일은 현재 폐지된 주소까지 알려준다. 그런데 폐지유무는 표시해주지않아 중복된 주소가 많아 사용하기 힘들다.
대신 국토교통부에서 제공해주는 데이터를 이용하면 폐지유무를 쉽게 알 수 있다.
https://www.code.go.kr/stdcode/regCodeL.do

위와 같은 텍스트 파일을 제공해준다.
이것을 변환하여 사용하면 된다.
방법1(id동적부여)
#### 이 코드는 중복처리와 id조회를 디비에서 진행하기 때문에 디비에 데이터가 들어있어도 사용할 수 있다. 하지만 디비에서 중복조회를 하고 쿼리가 각각 들어가 디비에 무리가 갈 수 있다.
###### 장점: id가 동적으로 정해진다. 디비에 데이터가 있어도 적용가능하다.
###### 단점: 디비에 비교적 무리가 갈 수 있다. 느리다.
import pandas as pd
# 텍스트 파일을 CSV 파일로 변환
def text_to_csv(text_file_path, csv_path):
# 텍스트 파일을 데이터프레임으로 읽기
df = pd.read_csv(text_file_path, sep='\t', names=["법정동코드", "법정동명", "폐지여부"])
# 폐지여부가 "폐지"인 행은 삭제
df = df[df['폐지여부'] != '폐지']
# 법정동명을 띄어쓰기 기준으로 나누어 시도, 시군구, 읍명동으로 분할
split_result = df['법정동명'].str.split(n=2, expand=True)
df['시도명'] = split_result[0]
df['시군구명'] = split_result[1]
df['읍면동명'] = split_result[2].str.split().str[0] # 읍면동의 앞부분만 선택
# null 값이 들어가 있는 행 삭제
df.dropna(inplace=True)
# '시도명', '시군구명', '읍면동명'이 동일한 행 중에서 맨 위의 행만 남김
df = df.drop_duplicates(subset=['시도명', '시군구명', '읍면동명'], keep='first')
# 결과 데이터프레임을 CSV 파일로 저장
df.to_csv(csv_path, index=False, encoding='utf-8')
print("CSV 파일 생성완료")
def csv_to_sql(csv_path, sql_path):
# CSV 파일 읽기
df = pd.read_csv('법정동코드.csv')
# SQL 문을 저장할 파일 열기
with open('법정동코드.sql', 'w') as sql_file:
# city_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
"""
sql_file.write(sql_statement)
# country_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
"""
sql_file.write(sql_statement)
# district_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
"""
sql_file.write(sql_statement)
# 데이터 삽입 코드 작성
for index, row in df.iterrows():
# 시도 테이블에 데이터 삽입 (중복 무시)
sql_statement = f"INSERT INTO city_tb (name) SELECT '{row['시도명']}' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '{row['시도명']}');\n"
# 시도명에 해당하는 id 가져오기
sql_statement += f"SET @city_id = (SELECT id FROM city_tb WHERE name = '{row['시도명']}');\n"
# 시군구 테이블에 데이터 삽입 (중복 확인)
sql_statement += f"INSERT INTO country_tb (city_id, name) SELECT @city_id, '{row['시군구명']}' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}');\n"
# 읍면동 테이블에 데이터 삽입 (중복 확인)
sql_statement += f"INSERT INTO district_tb (statutory_code, country_id, name) SELECT {row['법정동코드']}, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}'), '{row['읍면동명']}' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '{row['시군구명']}') AND name = '{row['읍면동명']}');\n"
# SQL 문을 파일에 쓰기
sql_file.write(sql_statement)
print("SQL 파일 생성완료")
if __name__ == "__main__":
text_file_path = '법정동코드.txt'
csv_path = '법정동코드.csv'
sql_path = '법정동코드.sql'
# 텍스트 파일을 CSV 파일로 변환
text_to_csv(text_file_path, csv_path)
# CSV 파일을 SQL파일로 변환
csv_to_sql(csv_path,sql_path)
파싱된 csv파일

생성된 sql문 일부
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010100, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '청운동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '청운동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010200, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '신교동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '신교동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010300, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '궁정동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '궁정동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010400, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '효자동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '효자동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010500, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '창성동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '창성동');
INSERT INTO city_tb (name) SELECT '서울특별시' WHERE NOT EXISTS (SELECT 1 FROM city_tb WHERE name = '서울특별시');
SET @city_id = (SELECT id FROM city_tb WHERE name = '서울특별시');
INSERT INTO country_tb (city_id, name) SELECT @city_id, '종로구' WHERE NOT EXISTS (SELECT 1 FROM country_tb WHERE city_id = @city_id AND name = '종로구');
INSERT INTO district_tb (statutory_code, country_id, name) SELECT 1111010600, (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구'), '통의동' WHERE NOT EXISTS (SELECT 1 FROM district_tb WHERE country_id = (SELECT id FROM country_tb WHERE city_id = @city_id AND name = '종로구') AND name = '통의동');
DB에 목적대로 잘 들어가는 것을 볼 수 있다.



방법1(id동적부여)
######### 이 코드는 id를 미리 정하여서 sql문을 생성하기 때문에 서버실행시에 맨 처음 데이터를 주입하여야 한다.
######### 장점: 빠름
######### 단점: id가 정해져 있어 초기실행시 맨 처음 데이터가 들어가야함
import pandas as pd
# 텍스트 파일을 CSV 파일로 변환
def text_to_csv(text_file_path, csv_path):
# 텍스트 파일을 데이터프레임으로 읽기
df = pd.read_csv(text_file_path, sep='\\t', names=["법정동코드", "법정동명", "폐지여부"])
# 폐지여부가 "폐지"인 행은 삭제
df = df[df['폐지여부'] != '폐지']
# 법정동명을 띄어쓰기 기준으로 나누어 시도, 시군구, 읍명동으로 분할
split_result = df['법정동명'].str.split(n=2, expand=True)
df['시도명'] = split_result[0]
df['시군구명'] = split_result[1]
df['읍면동명'] = split_result[2].str.split().str[0] # 읍면동의 앞부분만 선택
# null 값이 들어가 있는 행 삭제
df.dropna(inplace=True)
# '시도명', '시군구명', '읍면동명'이 동일한 행 중에서 맨 위의 행만 남김
df = df.drop_duplicates(subset=['시도명', '시군구명', '읍면동명'], keep='first')
# 결과 데이터프레임을 CSV 파일로 저장
df.to_csv(csv_path, index=False, encoding='utf-8')
print("CSV 파일 생성완료")
def csv_to_sql(csv_path, sql_path):
# CSV 파일 읽기
df = pd.read_csv('법정동코드.csv')
# SQL 문을 저장할 파일 열기
with open('법정동코드.sql', 'w') as sql_file:
# city_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
"""
sql_file.write(sql_statement)
# country_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
"""
sql_file.write(sql_statement)
# district_tb 테이블 생성
sql_statement = """
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
"""
sql_file.write(sql_statement)
city_list=[]
country_list= []
district_list= []
city_sql = "INSERT INTO city_tb (name) VALUES \\n"
country_sql = "INSERT INTO country_tb (city_id, name) VALUES \\n"
district_sql = "INSERT INTO district_tb (statutory_code, country_id, name) VALUES \\n"
# 데이터 삽입 코드 작성
for index, row in df.iterrows():
statutory_code = row['법정동코드']
city_name = row['시도명']
country_name = row['시군구명']
district_name = row['읍면동명']
#시도명 중복처리 및 시도명id 설정
if city_name not in city_list:
city_list.append(city_name)
city_sql += f"('{city_name}'),\\n"
city_id= city_list.index(city_name)+1
#시군구 중복처리 및 시군구id설정
if (city_id,country_name) not in country_list:
country_list.append((city_id,country_name))
country_sql += f"({city_id}, '{country_name}'),\\n"
country_id = country_list.index((city_id,country_name))+1
if (country_id,district_name) not in district_list:
district_list.append((country_id,district_name))
district_sql += f"({statutory_code}, {country_id}, '{district_name}'),\\n"
district_id = district_list.index((country_id,district_name))+1
city_sql = city_sql.rstrip(',\\n') + ";\\n"
country_sql = country_sql.rstrip(',\\n') + ";\\n"
district_sql = district_sql.rstrip(',\\n') + ";\\n"
# SQL 문을 파일에 쓰기
sql_file.write("\\n")
sql_file.write(city_sql)
sql_file.write(country_sql)
sql_file.write(district_sql)
print("SQL 파일 생성완료")
if __name__ == "__main__":
text_file_path = '법정동코드.txt'
csv_path = '법정동코드.csv'
sql_path = '법정동코드.sql'
# 텍스트 파일을 CSV 파일로 변환
text_to_csv(text_file_path, csv_path)
# CSV 파일을 SQL파일로 변환
csv_to_sql(csv_path,sql_path)
실행결과 sql
CREATE TABLE IF NOT EXISTS city_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE IF NOT EXISTS country_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
city_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (city_id) REFERENCES city_tb(id),
CONSTRAINT unique_city_name UNIQUE (city_id, name)
);
CREATE TABLE IF NOT EXISTS district_tb (
id INT AUTO_INCREMENT PRIMARY KEY,
statutory_code BIGINT UNIQUE NOT NULL,
country_id INT,
name VARCHAR(255) NOT NULL,
FOREIGN KEY (country_id) REFERENCES country_tb(id),
CONSTRAINT unique_country_name UNIQUE (country_id, name)
);
INSERT INTO city_tb (name) VALUES
('서울특별시'),
('부산광역시'),
('대구광역시'),
('인천광역시'),
('광주광역시'),
('대전광역시'),
('울산광역시'),
('세종특별자치시'),
('경기도'),
('충청북도'),
('충청남도'),
('전라북도'),
('전라남도'),
('경상북도'),
('경상남도'),
('제주특별자치도'),
('강원특별자치도');
INSERT INTO country_tb (city_id, name) VALUES
(1, '종로구'),
(1, '중구'),
(1, '용산구'),
(1, '성동구'),
(1, '광진구'),
(1, '동대문구'),
(1, '중랑구'),
(1, '성북구'),
(1, '강북구'),
(1, '도봉구'),
(1, '노원구'),
(1, '은평구'),
(1, '서대문구'),
(1, '마포구'),
(1, '양천구'),
(1, '강서구'),
(1, '구로구'),
(1, '금천구'),
(1, '영등포구'),
(1, '동작구'),
(1, '관악구'),
(1, '서초구'),
(1, '강남구'),
(1, '송파구'),
(1, '강동구'),
(2, '중구'),
(2, '서구'),
(2, '동구'),
(2, '영도구'),
(2, '부산진구'),
(2, '동래구'),
(2, '남구'),
(2, '북구'),
(2, '해운대구'),
(2, '사하구'),
(2, '금정구'),
(2, '강서구'),
(2, '연제구'),
(2, '수영구'),
(2, '사상구'),
(2, '기장군'),
(3, '중구'),
(3, '동구'),
(3, '서구'),
(3, '남구'),
(3, '북구'),
(3, '수성구'),
(3, '달서구'),
(3, '달성군'),
(3, '군위군'),
(4, '중구'),
(4, '동구'),
(4, '미추홀구'),
(4, '연수구'),
(4, '남동구'),
(4, '부평구'),
(4, '계양구'),
(4, '서구'),
(4, '강화군'),
(4, '옹진군'),
(5, '동구'),
(5, '서구'),
(5, '남구'),
(5, '북구'),
(5, '광산구'),
(6, '동구'),
(6, '중구'),
(6, '서구'),
(6, '유성구'),
(6, '대덕구'),
(7, '중구'),
(7, '남구'),
(7, '동구'),
(7, '북구'),
(7, '울주군'),
(8, '조치원읍'),
(8, '연기면'),
(8, '연동면'),
(8, '부강면'),
(8, '금남면'),
(8, '장군면'),
(8, '연서면'),
(8, '전의면'),
(8, '전동면'),
(8, '소정면'),
(9, '수원시'),
(9, '성남시'),
(9, '의정부시'),
(9, '안양시'),
(9, '부천시'),
(9, '광명시'),
(9, '평택시'),
(9, '동두천시'),
(9, '안산시'),
(9, '고양시'),
(9, '과천시'),
(9, '구리시'),
(9, '남양주시'),
(9, '오산시'),
(9, '시흥시'),
(9, '군포시'),
(9, '의왕시'),
(9, '하남시'),
(9, '용인시'),
(9, '파주시'),
(9, '이천시'),
(9, '안성시'),
(9, '김포시'),
(9, '화성시'),
(9, '광주시'),
(9, '양주시'),
(9, '포천시'),
(9, '여주시'),
(9, '연천군'),
(9, '가평군'),
(9, '양평군'),
(10, '청주시'),
(10, '충주시'),
(10, '제천시'),
(10, '보은군'),
(10, '옥천군'),
(10, '영동군'),
(10, '증평군'),
(10, '진천군'),
(10, '괴산군'),
(10, '음성군'),
(10, '단양군'),
(11, '천안시'),
(11, '공주시'),
(11, '보령시'),
(11, '아산시'),
(11, '서산시'),
(11, '논산시'),
(11, '계룡시'),
(11, '당진시'),
(11, '금산군'),
(11, '부여군'),
(11, '서천군'),
(11, '청양군'),
(11, '홍성군'),
(11, '예산군'),
(11, '태안군'),
(12, '전주시'),
(12, '군산시'),
(12, '익산시'),
(12, '정읍시'),
(12, '남원시'),
(12, '김제시'),
(12, '완주군'),
(12, '진안군'),
(12, '무주군'),
(12, '장수군'),
(12, '임실군'),
(12, '순창군'),
(12, '고창군'),
(12, '부안군'),
(13, '목포시'),
(13, '여수시'),
(13, '순천시'),
(13, '나주시'),
(13, '광양시'),
(13, '담양군'),
(13, '곡성군'),
(13, '구례군'),
(13, '고흥군'),
(13, '보성군'),
(13, '화순군'),
(13, '장흥군'),
(13, '강진군'),
(13, '해남군'),
(13, '영암군'),
(13, '무안군'),
(13, '함평군'),
(13, '영광군'),
(13, '장성군'),
(13, '완도군'),
(13, '진도군'),
(13, '신안군'),
(14, '포항시'),
(14, '경주시'),
(14, '김천시'),
(14, '안동시'),
(14, '구미시'),
(14, '영주시'),
(14, '영천시'),
(14, '상주시'),
(14, '문경시'),
(14, '경산시'),
(14, '의성군'),
(14, '청송군'),
(14, '영양군'),
(14, '영덕군'),
(14, '청도군'),
(14, '고령군'),
(14, '성주군'),
(14, '칠곡군'),
(14, '예천군'),
(14, '봉화군'),
(14, '울진군'),
(14, '울릉군'),
(15, '창원시'),
(15, '진주시'),
(15, '통영시'),
(15, '사천시'),
(15, '김해시'),
(15, '밀양시'),
(15, '거제시'),
(15, '양산시'),
(15, '의령군'),
(15, '함안군'),
(15, '창녕군'),
(15, '고성군'),
(15, '남해군'),
(15, '하동군'),
(15, '산청군'),
(15, '함양군'),
(15, '거창군'),
(15, '합천군'),
(16, '제주시'),
(16, '서귀포시'),
(17, '춘천시'),
(17, '원주시'),
(17, '강릉시'),
(17, '동해시'),
(17, '태백시'),
(17, '속초시'),
(17, '삼척시'),
(17, '홍천군'),
(17, '횡성군'),
(17, '영월군'),
(17, '평창군'),
(17, '정선군'),
(17, '철원군'),
(17, '화천군'),
(17, '양구군'),
(17, '인제군'),
(17, '고성군'),
(17, '양양군');
INSERT INTO district_tb (statutory_code, country_id, name) VALUES
(1111010100, 1, '청운동'),
(1111010200, 1, '신교동'),
(1111010300, 1, '궁정동'),
(1111010400, 1, '효자동'),
(1111010500, 1, '창성동'),
(1111010600, 1, '통의동'),
(1111010700, 1, '적선동'),
(1111010800, 1, '통인동'),
(1111010900, 1, '누상동'),
(1111011000, 1, '누하동'),
(1111011100, 1, '옥인동'),
(1111011200, 1, '체부동'),
(1111011300, 1, '필운동'),
(1111011400, 1, '내자동'),
(1111011500, 1, '사직동'),
(1111011600, 1, '도렴동'),
(1111011700, 1, '당주동'),
(1111011800, 1, '내수동'),
(1111011900, 1, '세종로'),
(1111012000, 1, '신문로1가'),
(1111012100, 1, '신문로2가'),
(1111012200, 1, '청진동'),
(1111012300, 1, '서린동'),
(1111012400, 1, '수송동'),
(1111012500, 1, '중학동'),
(1111012600, 1, '종로1가'),
(1111012700, 1, '공평동'),
(1111012800, 1, '관훈동'),
(1111012900, 1, '견지동'),
(1111013000, 1, '와룡동'),
(1111013100, 1, '권농동'),
(1111013200, 1, '운니동'),
(1111013300, 1, '익선동'),
(1111013400, 1, '경운동'),
(1111013500, 1, '관철동'),
(1111013600, 1, '인사동'),
(1111013700, 1, '낙원동'),
(1111013800, 1, '종로2가'),
(1111013900, 1, '팔판동'),
(1111014000, 1, '삼청동'),
(1111014100, 1, '안국동'),
(1111014200, 1, '소격동'),
(1111014300, 1, '화동'),
(1111014400, 1, '사간동'),
(1111014500, 1, '송현동'),
(1111014600, 1, '가회동'),
(1111014700, 1, '재동'),
(1111014800, 1, '계동'),
(1111014900, 1, '원서동'),
(1111015000, 1, '훈정동'),
(1111015100, 1, '묘동'),
(1111015200, 1, '봉익동'),
(1111015300, 1, '돈의동'),
(1111015400, 1, '장사동'),
(1111015500, 1, '관수동'),
(1111015600, 1, '종로3가'),
....
https://github.com/yunzae/districtCodeTextToSql
GitHub - yunzae/districtCodeTextToSql: 대한민국 법정동 코드를 DB에 넣기 위한 sql변환기
대한민국 법정동 코드를 DB에 넣기 위한 sql변환기. Contribute to yunzae/districtCodeTextToSql development by creating an account on GitHub.
github.com
GitHub - yunzae/districtCodeTextToSql: 대한민국 법정동 코드를 DB에 넣기 위한 sql변환기
대한민국 법정동 코드를 DB에 넣기 위한 sql변환기. Contribute to yunzae/districtCodeTextToSql development by creating an account on GitHub.
github.com