なぜカラム名から決めるのか
一言でいうと
カラム名を先に決める理由は見た目の美しさではありません。標準がないと、同じ意味のカラムが名前も長さも違う形で3つできてしまい、その代償を3年後の移行で払うことになるからです。
なぜこれが問題なのか
標準がなくても、開発はうまく回ります。各チームがそれぞれ合理的に名前を付けるからです。問題は、その3つを統合するときに初めて表面化します。統合照会画面、精算の突合、そして次世代システムへの移行です。
いちばん痛手になるのは長さです。顧客名をある所では50文字、別の所では30文字で定義していると、長い名前が入ってくる日に、黙って切り詰められたままロードされます。エラーが出ないので誰も気づかず、数か月後に「この顧客の名前がなぜこうなっているのか」という問い合わせで発覚します。
3年後に起きること
プロジェクトの初期にデータ標準を決めないと、こうなります。
고객관리 팀: CUSTOMER (CUST_NAME VARCHAR(50))
주문 팀: ORDERS (CUSTOMER_NM VARCHAR(100))
정산 팀: SETTLEMENT (CUST_NM VARCHAR(30))
同じ顧客名なのに、名前が3つ、長さも3つあります。最初は何の問題もありません。問題は、テーブルを結合するとき、統合照会を作るとき、そして3年後にデータを移行するときに噴き出します。
- 統合検索画面を作ろうとすると、3つのテーブルのカラム名をそのつど違う名前で書く必要があります
- 精算チームのテーブルに50文字の名前を入れようとすると切り詰められます。黙って切り詰められます
- 次世代プロジェクトで移行しようとすると、マッピング表を人が手で作らなければなりません
だからSIプロジェクトでは、開発を始める前にデータ標準を確定します。公共事業なら、「公共機関のデータベース標準化指針」に従って、標準単語・標準ドメイン・標準用語・標準コードの定義書を成果物として提出します。
標準の4段階
1. 표준단어사전 의미의 최소 단위와 그 약어
고객→CUST, 주문→ORD, 상품→PROD, 명칭→NM, 일자→DT,
금액→AMT, 수량→QTY, 번호→NO, 여부→YN, 코드→CD
2. 표준도메인 같은 성격의 값이 갖는 타입·길이 규칙
금액 → NUMBER(15,2) 일자 → CHAR(8)
여부 → CHAR(1) Y/N 코드 → VARCHAR(10)
명칭 → VARCHAR(100) 번호(내부키) → NUMBER(18)
3. 표준용어 단어를 조합한 논리명과 물리명
고객명 → CUST_NM (도메인: 명칭)
주문금액 → ORD_AMT (도메인: 금액)
주문일자 → ORD_DT (도메인: 일자)
4. 컬럼 정의 실제 DDL
ORD_AMT NUMBER(15,2) NOT NULL DEFAULT 0
このコードブロックの韓国語は、標準単語辞書(意味の最小単位とその略語。顧客→CUST、注文→ORD、商品→PROD、名称→NM、日付→DT、金額→AMT、数量→QTY、番号→NO、フラグ→YN、コード→CD)、標準ドメイン(同じ性質の値が持つ型・長さのルール)、標準用語(単語を組み合わせた論理名と物理名)、カラム定義(実際のDDL)の4段階についての説明です。
この順序を守れば、誰が作っても同じ名前と同じ型が出てきます。そして新しいカラムが必要なとき、「これはどのドメインか」だけを決めれば、残りは自動で決まります。
慣行についての率直な話
韓国のSIには、気に入らないかもしれない慣行があります。
- 日付を
CHAR(8) YYYYMMDDで持つ: DATE型のほうが優れています。そのとおりです。 - YesかNoかを
CHAR(1) Y/Nで持つ: BOOLEANのほうが優れています。そのとおりです。 - すべてのテーブルに
REG_DT、REG_ID、UPD_DT、UPD_IDを持たせる: 監査カラムです。これはかなり有用です。 - 論理削除(
DEL_YN): 物理削除をしません。復旧と監査のためです。
前の2つはレガシー互換のためです。新しいシステムだけ違う方式にすると、連携・移行の箇所ごとに変換コードが必要になり、1か所でも漏れると、黙って誤ったデータが溜まります。そのコストが、型を改善する利点より大きくなることがあります。
標準は「最善」ではなく「合意」です。この文を理解すると、「なぜこんな古いやり方を使うのですか」という質問ではなく、「この標準をいつ、どのように変えられるか」を問うようになります。
ただし、論理削除には注意が必要です。DEL_YN='N'の条件を漏らしたクエリ1つが、削除されたデータを画面に表示してしまいます。そのため、照会は常にビューを経由するよう設計するか、最低でもコードレビューのチェックリストに入れます。
制約条件は文書ではなくコード
テーブル定義書に「必須項目」と書いてあるのに、DDLにNOT NULLがなければ、その文書は守られません。制約はDBに設定して初めて強制されます。
| 制約 | 何を防ぐか | SIでの現実 |
|---|---|---|
| PRIMARY KEY | 重複行 | 必ず設定します |
| NOT NULL | 必須値の欠落 | 必ず設定します |
| CHECK | 値の範囲・コード値の違反 | よく省略されます。設定すべきです |
| UNIQUE | 業務キーの重複 | よく省略されます。重複データ事故の元凶です |
| FOREIGN KEY | 参照整合性 | 議論が分かれます |
| DEFAULT | 想定外のNULL | 設定しておくとコードが単純になります |
FKが議論になる理由があります。大量バッチでFKチェックが性能を食い、移行時にロード順を強制し、論理削除と衝突します。そのため「FKは開発環境にだけ設定し、本番環境では外す」という組織もあります。
どちらにするにせよ、明示的に決めて文書化してください。最悪なのは、「あるテーブルにはあり、あるテーブルにはない」状態です。そうなると、整合性をアプリケーションが保証しているのかDBが保証しているのか、誰にもわかりません。
インデックスは設計の成果物
インデックスを「遅ければあとで追加するもの」として扱うと、サービスイン後に苦労します。設計段階で照会パターンを整理し、インデックスも一緒に設計します。
화면 SCR-021 주문조회: WHERE CUST_ID = ? AND ORD_DT BETWEEN ? AND ?
→ IX_ORDERS_01 (CUST_ID, ORD_DT)
배치 BAT-005 일마감: WHERE ORD_DT = ? AND ORD_STS_CD = '완료'
→ IX_ORDERS_02 (ORD_DT, ORD_STS_CD)
複合インデックスのカラム順序が核心です。ルールは次のとおりです。
- 等価条件(
=)で使うカラムを前に - 範囲条件(
BETWEEN、>、<)で使うカラムを後ろに - 選択度の高い(値の種類が多い)カラムを前のほうに
(CUST_ID, ORD_DT)と(ORD_DT, CUST_ID)は完全に別のインデックスです。WHERE CUST_ID = ? AND ORD_DT BETWEEN ? AND ?には前者が適しています。後者は日付範囲全体を走査し、その中から顧客を絞り込まなければなりません。
そしてインデックスはタダではありません。INSERT/UPDATE/DELETEのたびにインデックスも更新されるため、インデックスが10個あるテーブルに大量にロードすると非常に遅くなります。データ移行のときにインデックスを削除してロードし、そのあと作り直す理由がこれです。
コードテーブル: ハードコーディングとの戦い
注文ステータスを'01'、'02'、'03'として保存するとします。この値の意味はどこにあるでしょうか。
- アプリケーションの定数: 画面ごとに違う形でハードコーディングされます
- 共通コードテーブル: 1か所で管理でき、運用中に追加できます
SIでは、ほとんどの場合、後者です。そして多くは次のような構造です。
CREATE TABLE COMMON_CODE (
GRP_CD VARCHAR(20) NOT NULL, -- 'ORD_STS'
CD VARCHAR(20) NOT NULL, -- '01'
CD_NM VARCHAR(100) NOT NULL, -- '접수'
SORT_NO INTEGER NOT NULL,
USE_YN CHAR(1) NOT NULL DEFAULT 'Y',
PRIMARY KEY (GRP_CD, CD)
);
注意点が1つあります。共通コードにあるからといって、何でも入ってきてはいけません。ステータスカラムにCHECKを設定するか、最低でもコード値の検証をどこで行うかを決める必要があります。「共通コードテーブルがあるから大丈夫」という言葉は、誰も検証していないという意味であることが多いです。
テーブル定義書はDBから生成します
設計の成果物としてテーブル定義書を提出しますが、開発が終わるころには、文書と実際のスキーマがずれています。いつもそうです。
そこで実務のコツです。最終的なテーブル定義書は、実際のDBメタデータから生成します。カラム一覧・型・NULL可否・デフォルト値・制約は、クエリで取り出せます。人が埋める必要があるのは説明(comment)だけです。
そして、その説明をDBのCOMMENT機能に入れておけば、文書とスキーマがいつまでも一緒に進みます。これができないDBMSを使っているなら、最低でも生成スクリプトを構成管理に置き、そこから文書を作ります。文書を手で維持した瞬間、その文書はやがて嘘になります。
現場での姿
標準を決めておきながら守られないことのほうが、よくある失敗です。定義書はあるのに、テーブルには標準にない名前が混ざっていて、誰もそれを検査しません。
そのため標準は、文書ではなく検査できる形で置く必要があります。テーブル定義書を手で書かず、pragma_table_infoやシステムカタログから生成するのも同じ理由です。手で書いた定義書は必ず実際のスキーマとずれ、ずれた定義書はないより悪いものです。読む人がそれを信じるからです。
制約条件も同じです。「数量は1以上でなければなりません」が文書にしかなければ、いつか0が入ってきます。CHECKで設定しておけば、その文章はコードになり、守られない方法がなくなります。