7

したがって、外部キーの作成方法と FK の目的を理解しています。しかし、それらの使用方法を理解するのに問題があります。ここで外部キーに関する質問をしました(リンクをクリック)

これが私が作ったものです:

CREATE TABLE user(
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  password VARCHAR(20) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE items(
  i_id INT(11) NOT NULL AUTO_INCREMENT,
  name TINYTEXT NOT NULL,
  price DECIMAL(8,2) NOT NULL,
  PRIMARY KEY (i_id)
);

CREATE TABLE user_purchase(
  i_id INT(11) NOT NULL,
  name TINYTEXT NOT NULL,
  id INT(11) NOT NULL,
  FOREIGN KEY (i_id) REFERENCES items(i_id),
  FOREIGN KEY (name) REFERENCES items(name),
  FOREIGN KEY (id) REFERENCES user(id)
);

ここで私の質問は、PHP を使用してこれを最大限に活用するにはどうすればよいかということです。上記のリンクから、user_purchase テーブルで外部キーを 1 つだけ使用するのがよいと提案されていますが、複数の列が必要な場合はどうすればよいでしょうか? 同じテーブルの異なる列に複数の外部キーを使用しないのはなぜですか?

私はmysqlとphpを使用しています。MYSQLコマンドを使用して情報を取得するために、外部キーを持つテーブルでPHPを使用する方法の例をいくつか示していただければ幸いです。本当に徹底的な説明が必要です。

また、正規化と非正規化という用語も理解する必要があります。これらの用語を例を挙げて詳しく説明しているリンクをいくつか提供していただければ幸いです。または、データベースの設計や実装などの初心者向けの優れた本の提案があれば、本当に感謝しています。

どうもありがとう。

4

5 に答える 5

23

外部キー列/制約の曖昧さの解消

したがって、外部キーの作成方法と FK の目的を理解しています。しかし、それらの使用方法を理解するのに問題があります。

外部キー制約を参照していると仮定すると、短い答えはそれらを使用しないことです。

そして、ここに長いものがあります:

列を他のテーブルへの外部キーと呼ぶことに慣れています。特に正規化プロセス中は、 「はテーブルへの外部キーですuser_purchase.i_iditemsなどのフレーズが非常に一般的です。これは関係を説明するのに完全に有効な方法ですが、実装段階に達すると少し曖昧になる可能性があります。

なしでテーブルを作成したとします。FOREIGN KEY

CREATE TABLE user(
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  password VARCHAR(20) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE items(
  i_id INT(11) NOT NULL AUTO_INCREMENT,
  name TINYTEXT NOT NULL,
  price DECIMAL(8,2) NOT NULL,
  PRIMARY KEY (i_id)
);

CREATE TABLE user_purchase(
  i_id INT(11) NOT NULL,
  name TINYTEXT NOT NULL,
  id INT(11) NOT NULL,
);

関係に関しては、外部キーまだ実装されていることに注意してください。テーブル ( )を参照する列と、userテーブル ( )idを参照する別の列があります。この列はしばらく脇に置いておきます。次のデータを検討してください。itemsi_idname

  user              user_purchase    items
| id  username |    | id  i_id |    | i_id  name            price |
| 23  john     |    | 55   10  |    |  10   chocolate bar    3.42 |
| 55  mary     |    | 70   10  |    |  33   mobile phone    82.11 |
| 70  fred     |    | 70   33  |    |  54   toothpaste       8.67 |
                    | 55   10  |    |  26   toy car          6.00 |
                    | 70   26  |

関係はそこにあります。これは、誰が何を購入したかuser_purchaseに関する情報を保持するテーブルによって実装されます。関連するレポートについてデータベースにクエリを実行する場合は、次のようにします。

select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)

これが、関連するリレーションと外部キーを使用する方法です。

では、次のようにするとどうなるでしょうか。

insert into user_purchase (id,i_id) values (23,99)

どうやら、これは無効なエントリです。のユーザーはいますがid=23、 のアイテムはありませんi_id=99。RDBMS はそれ以上のことを知らないので、それを可能にします。まだ。

ここで、外部キー制約の出番です。テーブル定義で指定することによりFOREIGN KEY (i_id) REFERENCES items(i_id)、本質的に RDBMS に従うべきルールを与えます: 列に含まれていない値を持つエントリは受け入れられません。つまり、外部キー列が参照を実装する一方で、外部キー制約は参照整合性を強制します。user_purchasei_iditems.i_id

ただし、selectFK 制約を定義したからといって、上記は変更されないことに注意してください。したがって、データを保護するために FK 制約を使用するのではなく、RDBMS が使用します。

冗長性

...複数の列が必要な場合はどうすればよいですか? 同じテーブルの異なる列に複数の外部キーを使用しないのはなぜですか?

自問してみてください: なぜそれが必要なのですか? 2 つの外部キーが同じ目的で使用される場合、冗長性によって最終的に問題が発生します。次のデータを検討してください。

 user_purchase                   items
| id  i_id  name           |    | i_id  name            price |
| 55   10   chocolate bar  |    |  10   chocolate bar    3.42 |
| 70   10   chocolate bar  |    |  33   mobile phone    82.11 |
| 70   33   mobile phone   |    |  54   toothpaste       8.67 |
| 55   10   toothpaste     |    |  26   toy car          6.00 |
| 70   26   toy car        |

この写真の何が問題になっていますか? ユーザー55はチョコレート バーを 2 つ購入しましたか、それともチョコレート バーと歯磨き粉を購入しましたか? この種のあいまいさは、データの同期を維持するために多くの労力を必要とする可能性がありますが、外部キーの 1 つを保持するだけであれば不要です。name実際、関係によって暗示されているため、列を完全に削除しないでください。

もちろん、複合外部キーを実装PRIMARY KEY(i_id,name)し、テーブルを設定してitems(または追加のインデックスを定義UNIQUE(i_id,name)しても問題ありません) FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)、. このように、テーブルに存在する (i_id,name) カップルのみitemsが有効になりますuser_purchasesまだ1 つの外部キーがあるという事実は別として、列がアイテムを識別するのに十分である場合、このアプローチはまったく不要ですi_id(列について同じことは言えませんname...)。

ただし、テーブルに対して複数の外部キーを使用することに対する規則はありません。実際、そのようなアプローチが必要な状況があります。次のデータを含むperson(id,name)テーブルとテーブルを考えてみましょう。parent(person,father,mother)

 person             parent
| id  name    |    | person  father  mother |
| 14  John    |    |   21      14      59   |
| 43  Jane    |    |   14      76      43   |
| 21  Mike    |
| 76  Frank   |
| 59  Mary    |

明らかに、parentテーブルの 3 つの列はすべて への外部キーpersonです。ただし、同じリレーションではなく、 3 つの異なるリレーションの場合: 個人の親も個人であるため、対応する 2 つの列は同じテーブルを参照する必要がありますperson。ただし、3 つのフィールドは同じ行の異なるを参照できるだけでなく、参照する必要があることに注意してください。これは、誰も自分の親ではなく、父親も母親でもないためです。personparent

于 2013-11-03T15:20:54.997 に答える
4

結合には外部キーが使用されます。たとえば、特定のアイテムを購入したユーザー名を知りたい場合は、次のように記述します。

select u.username
from items i
join user_purchase up on i.i_id = up.i_id
join user u on u.id = up.id
where i.name = "Some product name"

また、データベース エンジン自体によって使用される場合もあります。行または列user_purchaseが他のテーブルの参照された列と一致しない行を作成したかどうかを検出できます。idi_id

テーブル内の列を複製しないでください。はの単なる属性であり、特定の購入に固有のものではありません。購入したアイテムの名前を取得する必要がある場合は、テーブルに参加します。nameuser_purchasenameitemitems

于 2013-11-03T08:31:37.003 に答える
1

非常に多くのリンクを読む代わりに、単純なプロジェクトにこれを実装してみてください。上記の表をどのように使用するかを説明しているだけです。

テーブルに 3 人のユーザーがいて、userテーブルに 5 つのアイテムがあるとしitemsます。

userテーブル

id  |  username |  password 
 1      abc         123
 2      def         456
 3      qwe         987 

itemsテーブル

i_id  |  name   |  price 
 1      item 1    6
 2      item 2    8
 3      item 3    11 
 4      item 4    3
 5      item 5    14  

あなたのuser_purchaseテーブルはこのように見えます

CREATE TABLE user_purchase( i_id INT(11) NOT NULL, id INT(11) NOT NULL, FOREIGN KEY (i_id) REFERENCES items(i_id), FOREIGN KEY (id) REFERENCES user(id) );

この表では、項目名は不要です。だから私は削除しました。

i_id |  id  
 1      1      
 1      2
 2      2      
 3      3      

上記のテーブルでは、ユーザー 1 がアイテム 1 を購入し、ユーザー 2 がアイテム 1、アイテム 2 を購入し、ユーザー 3 がアイテム 3 を購入したことがわかります。

これが正規化の仕組みです。ユーザー名とアイテムの詳細を取得するためにMySQL JOINを使用できます

SELECT B.user_name,C.name AS item_name,C.price
FROM user_purchase A 
JOIN user B ON A.id = B.id
JOIN items C ON A.i_id = C.i_id

参加するための外部キーの使用は次のとおりです

A.id = B.id
A.i_id = C.i_id
于 2013-11-03T08:42:21.137 に答える
0

あたかも外部キーがないかのように、php で外部キーを持つテーブルを同じ方法でツリー化します。外部キーはデータベースで定義され、php とは (ほとんど) 関係ありません。PHP で行う必要がある唯一のことは、外部キー制約 (通常は DELETE クエリ) にブレーキをかける SQL クエリによって返される可能性のある潜在的なエラーに対応することです。

また、データベース スキーマでは、「テーブル user_purchase」から列「name」を削除する必要があります。冗長です。

于 2013-11-03T08:32:45.760 に答える
0

正規化/非正規化ポイントを見るだけです:

正規化は、データベースの冗長性を取り除こうとするプロセスです - あなたの例では、のnameフィールドuser_purchaseは冗長です.itemsi_id

したがって、正規化user_purchaseを検討する場合は、おそらくnameフィールドを削除し、JOIN必要なときに a を使用してそれを取得します。FOREIGN KEYもちろん、これは への 2 番目の参照が必要ないことも意味しitemsます。

非正規化は基本的に反対の方向に進みます - 冗長性を追加します - 通常はパフォーマンス上の理由で行われます。

ただし、あなたの例では、ビジネス上の理由からも非正規化を検討する場合があります。たとえば、請求書を再印刷できるようにする必要がある場合に備えて、(現在の名前ではなく) ユーザーが実際に購入したときの製品名を保存することが重要であると判断する場合があります。ただし、この場合でも、FOREIGN KEY背面は必要ありませんitems(製品の名前が変更されると「壊れる」ため)。

于 2013-11-03T08:35:21.853 に答える