かっちゃんのプログラミング奮闘記

このブログは、僕がプログラミング学習をしていく上で、知識のインプットを図るためのアウトプット場所として活用している場所です。

SQLの4大命令の覚え方

SQLには命令文で「INSERT」「UPDATE」「SELECT」「DELETE」の4つの代表的な命令がある。

これらの命令にはそれぞれ法則(型)があるので、それを覚えることで、スムーズに使い分けることができる。

4大命令をスッキリ学ぶ3つのコツ

①4大命令の構造と修飾語の全体をしっかり把握する
②4大命令の2通りの分類方法を理解する。
③4大命令に共通するテーブル指定を先に書く

4大命令の分類方法(検索・更新)

分類は以下の様に「更新系」と「検索系」の2つに分類できる。

・検索系: SELECT(DBを更新しない)
・更新系: UPDATE、DELETE、INSERT (DBを更新する)

SERECTは既存のDBの表から情報を検索して取り出したり並べ替えたりする時に使用し、残りのUPDATE、DELETE、INSERTはDB内に新しくデータを追加したり、DB内のデータを更新・削除したりして書き換える(更新)することを行うので、大きく分けて2分類で理解することができる。

この様に分類で考えれると、例えば修飾語で検索結果の表を並べ替える「ORDER BY」という修飾語を使用したい時に、必然と更新系ではなく、すでにある表を検索するSELECTでしか利用できないということがわかる。

なので、どんな修飾語を使いたいか、どんな条件でデータを扱いたいかを考えた時に、必然と対応する命令文が定まる。

4大命令の分類方法(既存・新規)

次に既にDB内にある既存のデータを扱う命令なのか、それともまだDB内に存在しないデータで新規でDB内に追加する命令なのかの2つでも分類ができる。

・既存系: SELECT、UPDATE、DELETE ・新規系: INSERT

この様に分類することで、条件つきで、例えば修飾語の「WHERE句」を用いて条件をつけて何かしたい時に、必然と既にあるデータに対してしか条件付きで実行することができないということがわかる。

WHEREはデータに対しての処理なので、今から新たに新規登録しようとしているデータに対しては利用することができない。というか使う場面が理屈上無い。

SQLをスッキリ書くには

f:id:kazuki13070311:20210829112235j:plain
各命令で固有の部分を再現した図

SQLをスッキリ書くには上記図を覚えることが一番手っ取り早い。

①まず、命令文(SELECTなど)を記述する。
②次にテーブルの指定(FROM、INTO)を記述する。
③テーブル指定の記述より後ろの「SET」や「VALUES」を記述する。
④最後にSELECT文のみ、テーブル指定の前の選択する列名(カラム名)を記述する。

この様に記述して当てはめていくことで、迷わずスッキリと記述することができる。

スッキリわかるSQL入門 #1

書籍スッキリわかるSQL入門を読んで学んだことのアウトプットをしていきます。

SQL

SQLはDBから情報を検索したり取り出したりしたい時にDBMSに命令をして望む情報を検索・登録・更新・削除する時に発行される命令言語のこと。

SQLは直接DBを参照して操作しているのではなく、DBMS(データベース管理システム)に命令をして、DBMSにDBから情報を取って来させる。

なので直接DBに命令を送っているのではない。

SQL

・SELECT → 検索したいカラム(列)を選択する
・FROM → 参照するテーブルを選択する
・WHERE → 条件付きで検索したい時に使う
・INSERT INTO → 既存のDBに情報を追加する
・UPDATE → 更新
・DELETE → 削除

SELECT(選択)

検索したいカラムを選択してくれる。
SELECTで選択したカラムを全て取得してくれる。
なので、例えば「SELECT エンタメ, 広告」と選択したら、検索条件にある情報を取り出す時にエンタメと広告の中身だけを取得してくれる。

・例文

SELECT 検索したいカラム名
FROM 参照したいテーブル
↓
SELECT メモ(カラム名)
FROM 家計簿(テーブル名)

▼条件付きで検索したいときはWHEREを使う
SELECT メモ(カラム名)
FROM 家計簿(テーブル名)
WHERE 日付 = "2018-02-12"

INSERT INTO

情報を追加したい時に使用する。
追加したい情報はVALUESの記述の後に記述される。 (VALUESとセット)

・例文

INSERT INTO 家計簿(テーブル名)
VALUES ('2021-12-21','メモ',20000,199)

追加したいテーブルを決めてVALUESで追加する。

また、INSERT INTOでテーブルを指定した後に()でカラムを指定してあげると、データを追加したいカラムを絞って登録することができる。

INSERT INTO 家計簿
               ( 費目, 日付, 出金額 )
    VALUES ( '通信費' , '2020-02-23' , 2000 ) 

⤴︎これで家計簿テーブルの費目カラム、日付カラム、出金カラムの3つにのみそれぞれVALUESで指示したデータを追加できる。

UPDATE(更新)

情報を更新したい時に使用する。
更新される情報は行(row)が更新される。

・例文

家計簿テーブル内の入金額が10000円以上の情報を出金額(カラム)10000円に更新する。  
↓
UPDATE 家計簿
SET 出金額 = 10000
WHERE 入金額 > 10000

SETで更新したいカラム名にどんな情報を入力したいかを考えて書く。
また、更新時はWHEREで条件をしてして、どの行を変更するかを指定しないと全ての行が更新されてしまうので、注意する。

DELETE(削除)

検索してきて当てはまった情報を削除するもの。
DELETEでカラムを削除したい場合は、FROMで対象のテーブルを指定する。

DELETE FROM 家計簿
WHERE 出金額>10000

※DELETE削除する時は、WHEREで条件を指定してあげないと、FROMで指定したテーブルごと削除されてしまうので注意

【書籍】達人に学ぶDB設計徹底指南書を読んで学んだこと【第4章】

第4章 ~ ER図に関する内容~

3種類の関係

テーブル同士の関係には以下の3種類がある

  • 1対1
  • 1対多
  • 多対多

基本的に1対1の関係は正規化する必要がなく、1対1の関係なら同じテーブル内に情報を入れてやれば良いので、1対1の関係の時は正規化しなくて良い。

正規化が必要なのは、1対多と多対多の関係の時。

1対多

社員テーブルに会社コード(主キー)と社員ID(主キー)と社員名があり、会社テーブルに会社コード(主キー)と会社名が@とする。

1つの会社に対して複数の社員が働いていることが想定される為、この場合は、会社が「1」で社員が「多」になる。

💡ポイント

RDSの場合、多対多の関係性を作ってはダメみたいです。
後ほど多対多の場合でも関係性を作っても良い解消方法を書くので、下記を読んでみて。

ER図の書き方

ER図を書くときはIDEFIXと言う表記法やIE表記法がある。
個人的に馴染みのあるのはIE表記法かな。
IDEFIXは細かく表記できる様だけど、IE表記法より書くのが複雑で理解字すらいみたい。

外部キー

他のテーブルの主キーを参照するキーを外部キーと呼び、表記法ではFK(foreign key)と呼ばれる。
良く「foreigin_key」とRailsで見かけるが、あれは外部キーのことを表していたらしい。

f:id:kazuki13070311:20210716233041p:plain
IE表記法

1対多の関係性の時に0人やNULLのが存在する可能性がある場合は「O」を使用する。

1対多の関係性で通常のNULLがない場合は鳥の足みたいなので書く。

多対多

上述した通り、基本的にRDSでは多対多の関係性は作ってはダメ。
しかし、それを解消する方法があり、人為的に多対多を実質解消することができる。

それは中間テーブルを作成してやること。

※中間テーブルは外部キーのみが格納されたテーブルのこと

f:id:kazuki13070311:20210717001035p:plain
多対多(アンチパターン

💡中間テーブルを作れば多対多は解消される

それぞれの主キーを持った中間テーブルを作成して、その中間テーブルと「多」のテーブルを関連付けて、1対多の関係性に無理やりしてやることで、RDSでの多対多の問題は解消される。

この多対多を解決する為の手段のことを「関連実態」(associative entitiy) と言うらしい。

中間テーブルにそれぞれ多対多の関係の主キーを入れて、その中間テーブルとそれぞれのテーブルで1対多の関係にする。

f:id:kazuki13070311:20210717002644p:plain
中間テーブル

中間テーブルには外部キーのみが格納されている。

【書籍】達人に学ぶDB設計徹底指南書を読んで学んだこと【第3章】

📖第3章

テーブルについて

テーブルとは2次元表に整理された情報を格納できるもの。

普通の表との違いは、カラム(縦列)やレコード(横列)で一貫して情報が整理された状態で表に入るのが普通の表と違うところ。ただ単に表にたくさんの情報を入れれば良いだけではない。

テーブル内部には複数のたくさんの情報が格納されるので、テーブル名は複数形で命名する。

テーブル構成の要素

テーブルは「列(カラム)」と「行(レコード)」で構成されている。 列は2次元表の縦の列のことで、行は2次元表の横の1行のことを指す。

キー

目には見えないけど、DBのテーブルになくてはならないもの。キーの種類は主に2つある。

  1. 主キー
  2. 外部キー

以上の2つがキーに主に存在する。

主キーとは?

主キーはテーブル内に必ず存在しないといけないキーでして、1行のレコード上に必ず1つだけ主キーを作らないといけない。

テーブル内に1つだけ独立させたキーを作成しておくことで、内部情報が混同したりすることなく、任意の1行のレコード情報を取得することができる。

このことを一意に識別する「unique」という。 migrationファイルによく出てくるやつかな?

外部キー

外部キーは2つの複数のテーブル同士を制約を持して紐付けるものになる。

要は、親子関係(アソシエーション)を作る時に必要になってくる。

外部キーがあることで、複数のテーブルを関連付けた時に、「制約」を定義することができ、間違った情報をDB内で変更や削除してしまう恐れを防いでくれる。(よく言う外部キー制約というやつ)

💡ポイント

外部キー制約を設けて親子関係を作る時は、子のテーブルの内部を先に削除して、親のテーブル内部は後から必要に応じて削除する様にするべし。

そうじゃないと、親子関係の親側が削除された時に、子の親がいなくなるので、エラーが出てしまう。

また、外部キーは変更可能なカラム名で親子関係を結んではいけない。

なぜなら変更されてしまって重複したり、判別をRDMS側が間違えてしてしまう可能があるから。

(親側に「山田 太郎」という名前の間に空白をつくて保存して、子側に「山田太郎」と空白をなしにして保存してしまうと、同じ意味でもRDMS側では違う意味と解釈して紐付けれくれなくなるから注意。)

なので、外部キーで親子関係を作るときは、必ず「ID」の様な人為的ミスがない「固定された表記」で関連付けることが鉄則。(board_idとtag_idを紐づけるなど必ずIDで紐づける)

🔒制約(外部キー)

  1. NOT NULL制約
  2. 一意制約
  3. CHECK制約

外部キーに関して代表な制約が以上の3つあります。

NOT NULL制約

空白の状態でDBに保存できない様にする制約。
NOT NULL制約を入れることで、SQLでDB内に情報を追加したり更新したりする時に、エラーが出て保存できない様にすることができる。

基本的にDBに情報を保存する場合は、空白・空欄で保存できない様にすることが設計をする上で絶対条件なので、テーブル設計する上ではできる限りNOT NULL制約を入れる様にする。

一意制約

列(カラム)に一意性を設定できる制約。
主キーと同じ役割だが、主キーはテーブル1つに一意性を1つしか設定することができないのに対して、こちらは何個でも制約を設けることができる。

CHECK制約

ある列(カラム)の中で取り出したい範囲を指定して、その範囲だけしか取り出せない様に制限をかけること。

例えば年齢の列なら「20〜45までの整数」と範囲の制限を設けることができる。

正規化とは何か?

論理設計事に使われる概念で、正規化を行うことで正規形を定義することができる。

正規形とは?

論理設計事の情報を整理して綺麗にDBを作り上げるために必要な概念。

正規形を行うことで、1つの情報を複数のテーブルに間違えて作成してしまうとかみたいな余分な冗長なことを未然に防いでくれて、開発を効率化してくれる。

正規形は第1正規形〜第5正規形まであり、実際の業務では第1正規形→第3正規形まで考えてつく割れることが多いので、まずは第3正規形まで理解できる様になっておくと良い。

第1正規形

第1正規形の定義は、「1つのセルの中に1つの値しか入っていない状態」のことを指す。

セルはフィールドとも言う。 セルはレコード(行)の中の1つのマスの中に入っている情報のこと。

第1正規化をする際は、このセルの中には1つしか情報、値は1つしか入れてはいけない。

ちなみにこの1つのセルの中に1つだけの値が入っていた場合、その値は「スカラ値」と言われる。

もし1つのセルの中に複数の情報を入れてしまうと、主キーが各列の値を一意にできず、正確に情報を取得することができなくなってしまうから。

関数従属性

第1正規形は、関数従属性と言う概念を採用している。 関数従属生徒は、「Y=10ならばX=5」である。「Y=8なら、X=3」である。みたいに、どちらか片方が決まれば自ずと紐づいているもう片方の情報も特定することができると言うこと。

◇例

「社員ID: X ならば → 社員名: Y 」
「社員ID: 100 ならば → 社員名: 徳川」
の様にX列の値を決めれば、Y列の値が1つだけに絞れて決まると言うこと。

・社員名: 徳川 ならば → 子供: たつお
・社員名: 徳川 ならば → 子供: みっちゃん
と言う主キーでの一意性を認められない形は設計としてダメなので、きちんと正規化して複数のテーブルと紐付ける。
(主キーは物語の主人公の様なもの、主となる基準とする貴キーがいないと始まらない)

第2正規形 〜部分関数従属〜

第2正規形では、部分関数従属という1つの行に複数の主キーで管理している状態を解消し、主キーを構成する行(レコード)の全ての列(カラム)に1つの主キーでの従属(紐付け)させる様にする。

この行の中の1つの主キーで、その行に関わる列を全て管理する状態にすることと「完全関数従属」と言う。

💡ポイント

第2正規形では、部分関数従属を解消して→完全関数従属に変換することを行う。

✅第2正規化の方法

第2正規化する方法は簡単で、1つの行に主キーを1つだけにすれば良いだけ。
要は、テーブルを2つないし、複数に分けて作成し、複数の主キーが1行に集まっていたのを分離すれば解消できる。

例えば、社員テーブルの「会社コード」のカラムだけに従属する「会社名」と言うカラムが1つあり、さらに「会社コード」のカラムの「社員ID」のカラムに従属する「社員名」と言うカラムが1つあった場合、複数の主キーが1行のレコードの複数従属してしまっており、部分関数従属の関係が出来上がってしまっていた場合、

「会社コード」のカラムに属する「会社名」のカラムと言う関係性の表を社員テーブルから独立させてあげれば良い。

その結果、「社員テーブル」が1つだけだったのから→「社員テーブル」と「会社テーブル」の2つのテーブルが出来上がる。

恐らくのちにこの2つの分けたテーブルを親子関係でアソシエーションで結んで使ったりするのだろう。

第3正規形 ~推移的関数従属~

表の中に2段階の関数従属がある場合、それを推移的関数従属と言い、さらに正規化する必要がある。

[会社コード,社員ID]→[部署コードID]→[部署名]
以上の様な部署名にたどり着くまでに2段階になっており、もしかりに社員IDに従属する社員名が空白(NULL)だった場合、下の階層の部署名は社員名がNULLになってしまっていて、一緒にNULLのままRDBに保存することができない。

つまり今回の場合でも、部署に関連づく社員がいない限り、RDBには新規の部署名を登録することができない。

なのでこの様なことが起こりうるので、部署コードIDも独立させて、複数のテーブルに分けてアソシエーションにして独立させる。

今回の場合は、社員テーブルから部署コードを独立させて、部署テーブルを作成する。

その後はその部署テーブルの部署コードを社員テーブルの部署コードとIDでアソシエーションで結びつけて1対1だったり、多対多の関係などを結ばせる。

💡ポイント

原則として第3正規化までは必ず行う。
ただし、正規化してテーブル数を増やしすぎるとSQL文で結合させることが多くなり、結果パフォーマンスが悪化してしまうことにつながるので、そこら辺は気をつけること。

【書籍】達人に学ぶDB設計徹底指南書を読んで学んだこと【第2章】

第2章

論理設計と物理設計

論理設計を行った後に物理設計を行う。

  • 論理設計
    概念スキーマを定義する設計を論理設計という
    何を情報のデータとして保存するか抽象的に決めるイメージ。
    論理設計は名前のイメージ通り「机上」で設計できるので、この設計時はまだパソコンがなくても紙に書いて設計とかもできる。

  • 物理設計 内部スキーマを定義する設計を物理設計という
    論理設計を元に具体的にどんな情報をRDBに保存するか具体名を考えて決めるイメージ

✍️論理設計を行うステップ

  1. エンティティの抽出
  2. エンティティの定義
  3. 正規化
  4. ER図の作成

以上の4つのステップで論理設計を行う。

エンティティとは?

RDBに格納するための「情報」を抽象的に表したもの。

【1】エンティティの抽出

エンティティ(= 情報)は最終的にはRDBに格納され保存されるが、エンティティを抽出した段階ではまだリストアップしただけなので、論理設計の工程的には抽出しただけであればまだRDBに保存できてない。

この工程では、まずRDBに格納する予定の情報をリストアップするということを行う。(顧客、社員、会社みたいなテーブル名を決めるイメージ)

ちなみにエンティティが格納される時は「テーブル」に格納される。

【2】エンティティの定義

エンティティを抽出できたら、次はエンティティをどの様な属性「attribute」で保存するかを決める必要がある。
エンティティを属性で定義しないと、RDBには保存することができない。

属性とは?

テーブルという表のフォーマットの中の縦列のことを属性という。

【3】正規化(重要)

正規化を行うことで、データベース内でエンティティをスムーズに利用することができる様になる。 なのでエンティティを抽出し、属性をつけて定義しても 、この「正規化」を行わないと保持されている情報をシステム側で利用することができない。

【4】ER図

ER図とはエンティティ・リレーションシップ・ディアグラムの略称で、テーブルに保存する情報を可視化して、情報(エンティティ)同士の関係性や格納情報を見やすくした見取り図みたいなもの。

大規模開発になるとER図が無いと全体像の把握が困難になってくるため、ER図がほぼ必須になる。

▼内部スキーマと物理設計

物理設計のステップ

  1. テーブル定義
  2. インデックス定義
  3. ハードウェアのサイジング
  4. ストレージの冗長構成決定
  5. ファイルの物理配置決定

【1】テーブル定義

論理設計で定義された概念スキーマを元にRDMS内へ格納するために「テーブル」という単位に変換する必要がある。
概念スキーマをテーブルに変換して最終的に物理モデルを作成する。(論理設計は最終的に論理モデルを作成する)

【2】インデックス定義

インデックスはパフォーマンスに関係してくる重要な部分で、牽引(目次)の様な役割をしているというイメージをしておけば良い。
インデックスがなくても問題なく機能はするが、特定の単語や情報が多くなってきた時にインデックスを定義していないと探すのが大変になる。
この様な理由から、結果的にパフォーマンスに影響が出てくるから、インデックスを定義することも大事になっってくる。

【3】ハードウェアのサイジング

サイジングとは、データ通信量がどのくらいになって、そのデータサイズはどれくらい大きくなって、それをストレージに保存するにはディスク容量がどのくらい必要になってくるとかの「見積もり」をすること。
どれくらいの画像が保存されるとかそういうDBに保存されるテーブル以外のことも加算して考える必要がある。

DBのディスク容量がパンパンになってくるとデータベースの性能が落ちてきて、システムのパフォーマンスが悪くなるという影響が出てくるので、この見積もりはとても重要。(最悪ストレージ(容量)が足らなくなるということも起きうる)

💡ポイント

精度の高いサイジングは難しいから、スケールしやすい、後から拡張しやすい構成でDBを設計することが大切。コスト面にも関わるところなので、この見積もりは難しいがとても大事になってくる。

ストレージの冗長構成

DB内に保存するデータを1箇所だけのディスク場所に保存しておくのは、何かあった時に全て失いかねないので、何かあった時にでも大丈夫な様にバックアップを持っておく必要がある。

そのために、RAIDと言われる「独立したディスク」を複数持ち、何かあってもいいよに分散さしておく技術を活用しておくと安心できる。

これは同じ情報が保存されたDBが入っているディスクを複数台用意することを指す。

RAIDという技術を使って、仮想的に複数のディスクを1つのグループにまとめたディスクのことを「RAIDグループ」という。

RAIDを活用して複数のバックアップを複数のディスクに保管しておくと安全だが、その分コストもかかってくるので、予算と相談して決める必要がありそう。

ファイルの物理配置

ストレージの冗長構成が決まったら、物理設計の最後にデータベースのファイルをどのディスク(またはどのRAIDグループ)に配置するか考える。

配置するファイルの種類

  1. データファイル
  2. インデックスファイル
  3. システムファイル
  4. 一時ファイル
  5. ログファイル

以上の5つのファイルの保管配置場所を考える。

①データファイル

ユーザー入力した情報をDBに保持するためのファイル。
SQLを通じてDB内部に情報を追加したり更新したりする時にも使用されるファイル。

②インデックスファイル

テーブルに格納されたインデックス(牽引)が格納されるファイル。

このファイルは、ユーザーも開発者も意識することはないファイルみたいです。

理由は、SQLではテーブルへアクセスする記述をすることがあっても、特定のインデックスに対する記述をすることがないから。

③システムファイル

DBMSの内部管理に使用されるデータを格納する。
ユーザーがアクセスすることはない。

④一時ファイル

DBMS内部で一時的にSQLとかで利用されたデータを格納する場所。
検索時やソート時などで一時的にSQLで選択して利用すると思うけど、その時に一時的に引っ張ってきて格納しておく場所のことを一時ファイルという。

⑤ログファイル

RDMSは、データベースに対する変更・更新の指令を受けた時にすぐさま実行しているのではなく、ログファイルに一時的に処理を保管し、一括してデータファイルに変更を反映させている。

その時に一時的に保管しておく場所。これも一時ファイルと同じ様な機能を果たしている。
ユーザーが行動してリクエストしたり指令したりしたときの実行コード(SQLでのクエリ)などを一時的に保管しておく。

【書籍】達人に学ぶDB設計徹底指南書を読んで学んだこと【第1章】

今回は「達人に学ぶDB設計徹底指南書」の第1章に関することのアウトプットを行います。

📖第1章

RDB(リレーショナルデータベース)

現在世の中で一番広く利用されているのデータベース。
保存されているデータをテーブルの様な2次元表で見ることができ、直感的にわかりやすいのが特徴。

DBMS(データベースマネージャーシステム)

データベースを操作したり管理したりするシステムさす。
MySQLPostgreSQLなどが無料オープンソースDBMSにあたる。
Oracle DatabaseやSQL Serverは「有料」のDBMSです。

DB設計時のアプローチ

  • DOA(データ中心アプローチ)
    システム開発時にDBに保持するデータは何かを事前に考えてからプログラムを書いていく「最初にデータありき」で考えて設計するアプローチのことを言う。
    今の時代は、このDOAでの設計手法が一般的。

  • POD(プログラム中心アプローチ) システム開発時に、まずプログラムを書いてどういう処理が必要が考えながらコードを書き、プログラムでの処理ができてから、扱うデータをそれぞれの処理ごとに考えて設計開発するアプローチ。
    要は、ロジックを考えてからその後に必要なデータを考えることかな?

💡ポイント

PODでの設計開発を行うと初めは良くても、だんだん仕様の変更追加などが加わってくると管理が処理ごとに管理していくのが大変になって非効率な開発になってしまう。

それとは対して、DOPでデータありきで考えて設計することで、一括でデータを管理することができるため、今は効率的なDOPでの設計開発のアプローチ支流になっている。

スキーマとは?

データベースを設計するための構図、フォーマットのことを指す。
このスキーマDBの設計情報を入力し、DBを作成する際にスキーマを元にDBの構築が行われる。

3層スキーマ

DBMS内部にデータを格納し作成する際に、この3層スキーマを使用しデータを格納する。
3層スキーマは、文字通り3層のスキーマによって構成されている概念のことを指しまして、以下の3つ概念のスキーマによって構成されています。

「外部スキーマ」「概念スキーマ」「内部スキーマ

外部スキーマ(ビュー)

ユーザー側から見た時に見えるデータを表している。
画面上に表示されるデータを作り出す際に必要になる。

概念スキーマ(開発者)

開発者から見たデータベースのことを表す。
この概念スキーマは、外部スキーマと内部スキーマの中間に位置するスキーマで、緩衝材の様な役割を果たしてくれる。

内部スキーマDBMS

DBMS側から見えるデータベースを表している。
MySQLなどデータベースの内部に入って、中のデータ見るときに、この内部スキーマがあることで保持されて格納されているデータをDBMS側から直接見ることができる。

💡ポイント

【概念スキーマ重要性】
外部スキーマと内部スキーマのみで構成する「2層スキーマ」でも実装することはできるみたいだが、これだと外部スキーマ側を変更した時に内部スキーマ側と直接紐づいているため、内部スキーマ側も同じ様に変更する必要性が出てきてしまう。

そこで「概念スキーマ」内部スキーマと外部スキーマの間に用いることで、内部スキーマと外部スキーマを独立させることが出来、DB内のデータの変更を容易にできる様になる。(概念スキーマが緩衝材の役割になってくれる)

この様に、スキーマを独立させることを「データ独立性」と呼ぶ。

・内部スキーマを独立させることを「物理的データ独立性」と言う。

・外部スキーマを独立させることを「論理的データ独立性」と言う。

なので今では3層スキーマが一般的になっている。

eachに関連する豆知識

◇mapメソッドでのeach メソッド


<%= @blog.tags.map(&:name).join("\\n") %>

上記のコードは以下の書き方を省略して書いたコードになる。

<%= blog.tags.map { |tag| [tag.name] } %>

✍️join

joinは情報を連結して取得する。

✍️("\n")

\nがで情報1つづつ空白で分けて取得してくれる。

◇pluckメソッド

eachメソッドと同じことができる。

blog.tags.pluck(:name).join(', ')

pluckの方がeachよりもパフォーマンスが高い場合もある。

◇結論

・特定の情報のみ取得するときはpluckのが処理が早い

・2000回とか連続して情報を取得する時はmapのが早い(SQLの発行がmapは1回で済むため)

pluckは毎回SQLが発行されるから大量処理には向かない