import pandas as pd
import re
import os
# DDLを解析する関数
def parse_ddl(ddl):
tables = {}
# テーブル定義部分とTABLESPACEを取得する正規表現
table_pattern = re.compile(r'CREATE TABLE (\w+)\s*\((.*?)\)\s*TABLESPACE\s*(\w+);', re.DOTALL)
# カラム定義部分を取得する正規表現
column_pattern = re.compile(
r'(\w+)\s+'
r'(NUMBER\(\d+(?:,\s*\d+)?\)|CHAR\(\d+\)|CLOB|BLOB|TIMESTAMP(?: WITH TIME ZONE)?|\w+)'
r'(?:\s+(NOT NULL|NULL))?'
r'(?:\s+DEFAULT\s+(.*?))?',
re.DOTALL
)
# CONSTRAINT定義を取得する正規表現
constraint_pattern = re.compile(
r'CONSTRAINT\s+(\w+)\s+(PRIMARY KEY|FOREIGN KEY)\s*\((.*?)\)'
)
for table_match in table_pattern.finditer(ddl):
table_name = table_match.group(1) # テーブル名
table_body = table_match.group(2).strip() # テーブル定義(カラムとCONSTRAINT)
tablespace_name = table_match.group(3) # テーブルスペース名
table_info = [] # カラム情報を保持するリスト
primary_keys = [] # プライマリキーのリスト
# カラム定義部分を解析
for column_match in column_pattern.finditer(table_body):
col_name = column_match.group(1) # カラム名
col_type = column_match.group(2) # カラムデータタイプ(NUMBER, CHAR, CLOBなど)
null_option = column_match.group(3) if column_match.group(3) else '' # NULL/NOT NULLオプション
default_value = column_match.group(4) if column_match.group(4) else '' # デフォルト値
# カラム情報をリストに追加
table_info.append((col_name, col_type, '', null_option, default_value))
# CONSTRAINT定義部分を解析
for constraint_match in constraint_pattern.finditer(table_body):
constraint_name = constraint_match.group(1) # CONSTRAINT名
constraint_type = constraint_match.group(2) # PRIMARY KEY or FOREIGN KEY
constraint_columns = constraint_match.group(3).split(',') # キーに指定されたカラム
if constraint_type == 'PRIMARY KEY':
primary_keys.extend([col.strip() for col in constraint_columns]) # PKのカラムを追加
# カラムリストにプライマリキーの設定を反映
for idx, (col_name, col_type, key_type, null_option, default_value) in enumerate(table_info):
if col_name in primary_keys:
table_info[idx] = (col_name, col_type, '(PK)', null_option, default_value)
# テーブル情報を辞書に追加
tables[table_name] = (tablespace_name, table_info)
return tables
# テーブル定義書をExcelに書き込む関数
def create_excel(tables, output_file):
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
# テーブル一覧シートを作成
table_list = []
for idx, (table_name, (tablespace_name, columns)) in enumerate(tables.items(), start=1):
logical_name = '' # 論理テーブル名は空欄
physical_name = table_name
description = '' # テーブルの内容は空欄
# ハイパーリンクを追加
table_list.append([idx, tablespace_name, logical_name, f'=HYPERLINK("#{table_name}","{physical_name}")', description])
# テーブル一覧をExcelに書き込む
df_table_list = pd.DataFrame(table_list, columns=['No', 'テーブルスペース名', '論理テーブル名', '物理テーブル名', 'テーブルの内容'])
df_table_list.to_excel(writer, sheet_name='テーブル一覧', startrow=5, index=False)
# 各テーブルのシートを作成
for table_name, (tablespace_name, columns) in tables.items():
df_columns = pd.DataFrame(columns, columns=['カラム名', 'カラムデータタイプ', 'キー', 'NULLオプション', 'デフォルト値'])
df_columns['属性コメント'] = '' # 属性コメントは空欄
# Excelにカラム情報を書き込む
sheet_name = table_name
df_columns.to_excel(writer, sheet_name=sheet_name, startrow=6, index=False)
# Excelの書式設定
workbook = writer.book
worksheet = writer.sheets[sheet_name]
# セルの結合
worksheet.merge_cells('A1:C2') # 「基本設計書」と表示
worksheet['A1'] = '基本設計書'
worksheet.merge_cells('A3:C5') # 「テーブル仕様書」と表示
worksheet['A3'] = 'テーブル仕様書'
worksheet.merge_cells('D1:H5') # テーブル名を表示
worksheet['D1'] = table_name
# 6行目のフォントを太字にする
for row in worksheet.iter_rows(min_row=6, max_row=6, min_col=1, max_col=8):
for cell in row:
cell.font = cell.font.copy(bold=True)
# サンプルDDL
ddl = '''
CREATE TABLE TES_TABLE (
ID NUMBER(6,2) NOT NULL,
NAME CHAR(50),
DESCRIPTION CLOB,
CREATED_AT TIMESTAMP WITH TIME ZONE,
DATA BLOB,
CONSTRAINT PK_TES_TABLE PRIMARY KEY (ID, NAME)
) TABLESPACE TES_SPACE;
'''
# DDLをパースしてテーブル情報を抽出
tables = parse_ddl(ddl)
# 抽出したテーブル情報をExcelに書き込む
output_file = 'table_definitions.xlsx'
create_excel(tables, output_file)
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme