エラーは、外部キー構文が正しくないことが原因で発生します。
ただし、文字列複合主キーを使用する代わりにIDフィールドを使用する必要があると思います 。メソッドにはいくつかの問題があります...
-
整数(ID)フィールドを使用して結合する場合と比較して、DBがテーブルを結合するのが難しくなります(より困難==より多くの処理時間)。
-
ミドルネームのイニシャルを使用している場合でも、同じ名前の人が複数いることは有効です。
-
誰かの名前を変更する必要がある場合はどうなりますか? 間違って保管されていたか、結婚したかなどの理由で...つまり、
employee
を更新するだけでなく、 テーブルですが、works
テーブルおよびその名前を外部キーとして使用したその他のテーブル。
これを見てください: http://sqlfiddle.com/#! 2 / 2dc8c / 3/0
各テーブルにテーブルIDを追加しました 。これはunsigned int
です 、これは負の値にはなり得ないことを意味します(それはあまり意味がないため)。 auto_increment
でもあります 、つまり、テーブルに行を追加するたびに、このIDが自動生成され、1ずつ増加します。
create table Employee (
Employee_ID int unsigned auto_increment primary key,
Lastname varchar(10),
FirstName varchar(10),
MidInitial char(1),
gender char(1),
street varchar(10),
city varchar(10),
unique (Lastname, FirstName, MidInitial)
);
このテーブルに次のように追加します:
insert into Employee (Employee_ID, LastName, FirstName, MidInitial)
values (null, 'Smith', 'John', 'K');
null
自動生成されたIDになります。行ごとに一意になります。
また、一意の制約 これらのフィールドの組み合わせは、テーブル内で一意である必要があることを意味します。しかし、十分な規模の会社では、2人が同じ名前になるに違いありません。実生活では、この固有の制約を取り除くことをお勧めします。
会社のテーブルにも同様の変更を加えました...
create table company(
company_ID int unsigned auto_increment primary key,
company_name varchar(20),
city varchar(10),
unique (company_name)
);
次のように追加できます:
insert into company values (null, 'Taco Bell', 'Paris');
だから...works
の場合 ....このテーブルに各個人のフルネームとフル会社名を何度も保存する代わりに、IDを保存するだけで済みます。
create table Works (
works_id int unsigned auto_increment primary key,
employee_id int unsigned,
compay_id int unsigned,
salary numeric(8,2),
foreign key (employee_id) references Employee (employee_id),
foreign key (compay_id) references company (company_id)
);
works
に何かを追加できます このように:
insert into Works values (null, 1, 1, '10.00');
John Smithが最初の従業員だったので、彼のEmployee_IDは1になります。これを確認するには、select * from Employee where FirstName='John' and LastName='Smith'
を試してください。 。 TacoBellもcompany_id=1を取得します。これらの値をworks
に挿入することによって 、つまり、ジョンは現在タコベルで働いています。
start_date
のようなフィールドを追加することもお勧めします およびend_date
およびjob_title
あなたの作品のテーブルに。また、このテーブルの固有の制約にも特別な配慮を払う必要があります。人々は同じ会社で複数回働くことができます。彼らはまた異なる仕事をすることができます。
データを元に戻したい場合は、次のようなクエリを使用します。
select FirstName, MidInitial, LastName,
Company_Name,
Salary
from employee
join works
on works.employee_id = employee.employee_id
join company
on works.company_id = company.company_id
これは、これを言うための空想的な言い方です:
select FirstName, MidInitial, LastName,
Company_Name,
Salary
from employee, works, company
where employee.employee_id = works.employee_id and
company.company_id = works.company_id
データベースに関する注意事項...
-
命名規則を選択し、それに固執してください!
CamelCase
を使用する場合 、どこでも使用できます。you_want_to_use
の場合 名前にアンダースコアを付けて、どこでも使用してください。選択できる命名規則はたくさんあります。属性(列/フィールド)の前にテーブル名を付け、一般的な略語を使用して(または使用せず)、大文字を使用する(または使用しない)...これは主に個人的な好みに依存しますが、特定のものを使用することについての賛否両論についてそこにある記事です。最後に、_名前にスペースを使用できるからといって、__はそうする必要があるという意味ではありません。`Almost all`
データベースは[you use spaces]
必要に応じて名前を付けますが、後で多くの問題が発生する可能性があります。 -
テーブル名は複数形であってはなりません。 これは私の愛玩動物であり、その理由は次のとおりです。テーブルには多くのレコードが保持されることがわかっています...多くの人/人、多くの従業員、複数の会社、あらゆる種類または種類の複数のエントリ。各行は1つだけを表します これらのものの。名前を複数形にするのが意味をなさない場合もあります。また、
works
のように疑わしい場合もあります。 テーブル。複数形にしたり、単数形にしたりすると、後で混乱する可能性があります。すべてを特異にするだけで、それでも完全に理にかなっており、クエリを作成するときに前後に切り替えたり、正確な名前を検索したりする必要はありません。 -
データ型は重要です 同様のフィールドのテーブル間で一貫性を保つようにしてください (すべての
id
のように s同じタイプ。すべてのブールフィールドをすべてビットまたは整数などにします。同じにします)。選択できる整数型にはさまざまなサイズがあります。サイズ、パフォーマンス、およびニーズに適したものについて考えてください。本当にnvarcharが必要かどうか、またはvarcharに問題がないかどうかを判断します。- 日付は絶対にすべきではありません 文字列として保存されます。 適切な日付、日時、時刻、またはタイムスタンプのデータ型を使用してください 。これは、後でそれを取得したり、比較したり、計算に使用したりする必要があるときに役立ちます。もう1つの重要な決定は、タイムゾーンの処理方法を選択したことです。 。私はすべてをUTCで保存し、情報がユーザーに提示されるときにフロントエンドでタイムゾーンオフセットを処理するのが好きです。これにより、すべての一貫性が保たれ、ユーザーのコンピューター時間、ユーザーのブラウザー時間、データベースの時間、またはサーバーの時間に基づいて、行が午後6時に挿入されたかどうかを心配する必要はありません。
- 日付は絶対にすべきではありません 文字列として保存されます。 適切な日付、日時、時刻、またはタイムスタンプのデータ型を使用してください 。これは、後でそれを取得したり、比較したり、計算に使用したりする必要があるときに役立ちます。もう1つの重要な決定は、タイムゾーンの処理方法を選択したことです。 。私はすべてをUTCで保存し、情報がユーザーに提示されるときにフロントエンドでタイムゾーンオフセットを処理するのが好きです。これにより、すべての一貫性が保たれ、ユーザーのコンピューター時間、ユーザーのブラウザー時間、データベースの時間、またはサーバーの時間に基づいて、行が午後6時に挿入されたかどうかを心配する必要はありません。
-
ID
を含める フィールド これは、すべてのテーブルの行に固有です。これを行う最も簡単な方法は、auto_increment
を使用することです。 (mysql)またはidentity(1,1)
(SQLサーバー)フィールド。データベースがそれを追跡します。これらの値は、必要に応じてリセットまたは再シードできます。 -
トランザクションについて学ぶ 実行し、なぜそれらが重要なのか...あなたがそれらを使用しなくても。
-
さまざまな種類の結合について学ぶ 。 これは最良の説明の1つです私は今まで見たことがあります。 注意すべき主なことは、結合が外部結合であるか内部結合であるかです。
-
SQLインジェクションについて学ぶ さらに重要なのは、それを防ぐために (そのリンクはPHP用です)。
-
PHPを使用している場合は、古い
mysql_
を使用しないでください クラス。代わりに、PDO
を使用してください またはMySQLi_
。 情報... -
データベースの重要な点は、データの整合性、検証、およびサニタイズです。 。ユーザーは、あらゆる種類のずさんな、汚いデータをテーブルに入れたいと思うでしょう。 MOですか、それともミズーリですか?女性、F、女性、女の子、それともそうですか?給料は1時間あたり15.00、年間5万、それとも給料は3,000ですか。 2013年12月31日、2013年12月31日、2013年12月31日、2013年12月31日ですか、それとも12月35日2千13日ですか。
-
NULL
を許可するかどうかを決定します か否か。三重項論理のために物事がより複雑になり、後でそれをチェックする必要があります。代わりに空の文字列を使用することを決定する人もいます。 NULL は実際の値というよりも状態であり、未定義または不明であることを意味します。値は何でもかまいません。 nullを使用します 空の文字列がフィールドの有効な値である場合があるためです。たとえば、Middle_Initial
を設定します 空の文字列に等しいということは、その人がミドルネームのイニシャルを持っていないことを意味するか、それが何であるかをあなたが知らないことを意味する可能性があります。私にとって、これらは異なります。他の人にとっては、違いは関係ありません。数字を考えてみてください...0は不明と同じですか? -
他に何もない場合は、一貫性を保つだけです。