sql >> データベース >  >> RDS >> Mysql

「多対二」の関係

    この質問は、実体関連を完全に理解していないことを示しています(無礼は意図されていません)。そのうち4つ(技術的には3つのみ)のタイプがあります:

    One to One
    One to Many
    Many to One
    Many to Many
    

    1対1(1:1): この場合、テーブルは、正規化、またはより一般的にはオープンクローズド原則に準拠するために2つの部分に分割されています。

    正規化 コンプライアンス:各顧客が1つのアカウントしか持たないというビジネスルールがある場合があります。技術的には、この場合、顧客とアカウントがすべて同じテーブルにあると言うことができますが、これは正規化のルールに違反するため、それらを分割して1:1にします。

    オープンクローズ原則 コンプライアンス:顧客テーブルには、ID、姓名、住所が含まれる場合があります。後で誰かが生年月日を追加することを決定し、それを使用して、他の非常に必要なフィールドの束と一緒に年齢を計算する機能を追加します。これは1対1の非常に単純化された例ですが、主な用途は、既存のコードを壊さずにデータベースを拡張することです。 (悲しいことに)書かれたコードの多くはデータベースと緊密に結合されているため、テーブルの構造を変更するとコードが壊れます。このように1:1を追加すると、元のコードを変更せずに新しい要件を満たすようにテーブルが拡張されます。これにより、古いコードは正常に機能し続け、新しいコードは新しいデータベース機能を利用できるようになります。

    このように1:1の関係を使用してテーブルを正規化および拡張することの欠点は、パフォーマンスです。多くの場合、頻繁に使用されるシステムでは、データベースのパフォーマンスを向上させる最初の目標は、そのようなテーブルを非正規化して1つのテーブルに結合し、インデックスを最適化して、結合を使用して複数のテーブルから読み取る必要をなくすことです。正規化/非正規化は、システムのニーズに依存するため、良いことでも悪いことでもありません。ほとんどのシステムは通常、必要に応じて正規化された変更を元に戻しますが、前述のように、この変更は非常に慎重に行う必要があります。コードがDB構造に緊密に結合されている場合、システムはほぼ確実に失敗します。つまり、2つのテーブルを組み合わせると、1つは存在しなくなり、現在存在しないテーブルを含むすべてのコードは、変更されるまで失敗します(db用語では、これらのテーブルを削除すると、1:1のテーブルのいずれかに関係を接続することを想像してください) 、これは関係を壊すので、それを補うために構造を大幅に変更する必要があります。残念ながら、このような悪い設計は、ほとんどの場合、ソフトウェアの世界よりもDBの世界で見つけるのがはるかに簡単であり、通常、何かがうまくいかなかったことに気付くことはありません。システムが関心の分離> 念頭に置いてください。

    これは、オブジェクト指向プログラミングで継承に最も近いものです。しかし、まったく同じではありません。

    1対多(1:M)/多対1(M:1): これらの2つの関係(したがって、4が3になる理由)は、最も一般的な関係タイプです。それらは両方とも同じタイプの関係であり、変化するのはあなたの視点だけです。例顧客が多くの電話番号を持っているか、あるいは、多くの電話番号が顧客に属している可能性があります。

    オブジェクト指向プログラミングでは、これは構成と見なされます。継承ではありませんが、1つのアイテムが多くの部分で構成されていると言っています。これは通常、継承構造ではなく、クラス内の配列/リスト/コレクションなどで表されます。

    多対多 (M:M): 現在の技術とのこの種の関係は不可能です。このため、それらを結合する「関連付け」テーブルを使用して、2つの1対多の関係に分割する必要があります。 2つの1対多の関係の多くの側面は、常に関連付け/リンクテーブルにあります。

    あなたの例では、多対多が必要だと言った人は正しいです。 2対多は事実上多対多(複数を意味する)対多の関係だからです。これが、システムを機能させる唯一の方法です。 関係論理 の分野を調査する予定がない限り これを可能にする新しいタイプの関係を見つけるために。

    また、このような関係(m2m)には、2つの選択肢があります。リンカーテーブルに複合キーを作成して、フィールドの組み合わせが一意のエントリになるようにします(db最適化に関心がある場合、これは遅い選択ですが、必要なスペースが少なくなります)。または、自動生成されたid列を使用して3番目のフィールドを作成し、それを主キーにします(db最適化の場合、これがより高速な選択ですが、より多くのスペースが必要になります)。

    上記の例では...

    これは、企業とユーザーの間のリンカーテーブルとしての電話番号テーブルとの多対多の関係になります。説明したように、電話番号が繰り返されないようにするには、電話番号を主キーとして設定するか、別の主キーを使用して電話番号フィールドを一意に設定します。

    そのような質問の場合、それは本当にあなたがそれらをどのように表現するかにかかっています。これについて混乱する原因は何ですか。また、この混乱を克服して解決策を確認する方法は簡単です。問題を次のように言い換えます。まず、1対1であるかどうかを尋ねます。答えが「いいえ」の場合は、次に進みます。次の質問は、答えが先に進まない場合、1対多です。残っている他の唯一のオプションは多対多です。ただし、先に進む前に、最初の2つの質問を慎重に検討したことを確認してください。多くの経験の浅いデータベースの人々は、1対多、多対多を定義することによって問題を複雑にしすぎることがよくあります。繰り返しになりますが、これまでで最も人気のあるタイプの関係は1対多(私は90%と言います)であり、多対多と1対1で残りの10%を7/3に分割します。しかし、これらの数字は私の個人的な見解にすぎないので、業界標準の統計として引用しないでください。私のポイントは、多対多を選択する前に、それが間違いなく1対多ではないことをさらに確認することです。余分な努力をする価値があります。

    したがって、2つの間のリンカーテーブルを見つけるために、どちらの2つがメインテーブルであり、どのフィールドをそれらの間で共有する必要があるかを決定します。この場合、会社とユーザーのテーブルは両方とも電話を共有する必要があります。リンカとして新しい電話テーブルを作成する必要があります。

    誤解の警告アラームは、3つのうちどれも機能していないと判断するとすぐに表示されます。これは、単に関係の質問を正しく表現していないことを伝えるのに十分なはずです。時間が経つにつれて上手くなりますが、それは不可欠なスキルであり、あなた自身の賢さのためにできるだけ早く習得する必要があります。

    もちろん、「階層型」関係と呼ばれる他のさまざまな関係を可能にするオブジェクト指向データベースにアクセスすることもできます。あなたもプログラマーになることを考えているなら、それは素晴らしいことです。しかし、さまざまなタイプの関係を組み合わせる方法を見つけ始めると頭が痛くなるので、これはお勧めしません。特に、世界中のほぼすべてのデータベースは、特別なものでない限り、これら3種類の関係だけで構成されているため、それほど必要はありません。

    これが合理的な答えであったことを願っています。お時間を割いていただきありがとうございます。



    1. MariaDBでのDAYOFMONTH()のしくみ

    2. MySQLEAVの結果をリレーショナルテーブルとして取得するための最高のパフォーマンスは何ですか

    3. MySQLでのテーブルコメントの長さ

    4. 25行目のエラー1030​​(HY000):ストレージエンジンからエラー168を取得しました