0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DDLからつくりてぇな

Last updated at Posted at 2024-09-11
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)


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?