Вашите грешки са причинени от неправилен синтаксис на външния ключ.
Въпреки това, Мисля, че трябва да използвате полета за идентификационен номер, вместо да правите съставни низови първични ключове . Има няколко проблема с вашия метод...
-
Това ще направи по-трудно за DB да обедини таблици заедно в сравнение с използването на цяло число (ID) поле за присъединяване (по-трудно ==повече време за обработка).
-
Валидно е да имате няколко души с едно и също име, дори да използвате среден инициал.
-
Какво ще стане, ако трябва да промените името на някого? Или защото е било съхранено неправилно, или са се оженили или нещо подобно... Това означава, че ще трябва не само да актуализирате своя
employee
таблица, ноworks
таблица и всяка друга таблица, чието име сте използвали като външен ключ.
Разгледайте това:http://sqlfiddle.com/#! 2/2dc8c/3/0
Добавих идентификатор на таблица към всяка таблица . Това е unsigned int
, което означава, че не може да бъде отрицателно (защото това няма да има много смисъл). Също така е auto_increment
, което означава, че всеки път, когато добавите ред към таблицата, този идентификатор ще се генерира автоматично и ще се увеличава с 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
ще стане автоматично генериран идентификатор. Той ще бъде уникален за всеки ред.
Също така, уникално ограничение означава, че комбинацията от тези полета трябва да бъде уникална в таблицата. Въпреки това, с достатъчно голяма компания, обзалагам се, че двама души ще имат едно и също име. В реалния живот бих предложил да премахнете това уникално ограничение.
Направих подобни промени в таблицата на компанията...
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
.... вместо да съхраняваме пълното име на всяко лице и пълното име на фирмата отново и отново в тази таблица, сега трябва да съхраняваме само идентификационните номера.
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');
Тъй като Джон Смит беше първият ни служител, неговият Employee_ID ще бъде 1. За да потвърдите това, просто опитайте select * from Employee where FirstName='John' and LastName='Smith'
. Taco Bell също ще получи company_id =1. Като вмъкне тези стойности в works
, това означава, че Джон сега работи в Taco Bell.
Също така бих ви предложил да добавите полета като 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]
в имена, ако искате, но това може да причини много проблеми по-късно. -
Имената на таблици не трябва да са множествено число. Това е моето недоволство и ето защо:Знаем, че една маса ще съдържа много записи... много хора/лица, много служители, множество компании, множество вписвания от всякакъв тип или вид. Всеки ред описва само един от тези неща. Понякога просто няма смисъл името да е множествено число. Друг път е под въпрос - като
works
маса. Ако понякога го направите множествено число, а понякога го направите единствено, може да се обърка по-късно. Като направите всичко единствено, това все още има идеален смисъл и не превключвате напред-назад или трябва да търсите точното име, когато пишете заявки. -
Типовете данни са важни и се опитайте да бъдете последователни в таблиците за подобни полета (като всички
id
е от същия тип; направи всички булеви полета всички битове или цели числа или каквото и да е, просто ги направете еднакви). Има различни размери на цели числа, от които можете да избирате. Помислете за размера, производителността и това, което е подходящо за вашите нужди. Решете дали наистина имате нужда от nvarchar или дали varchar е наред.- Дати не трябва никога да се съхранява като низ. Използвайте подходящия тип данни за дата, час, час или клеймо за дата . Това ще ви помогне много по-късно, когато трябва да го извлечете, да го сравните или да го използвате при изчисления. Друго важно решение е как сте избрали да обработвате часовите зони . Обичам да съхранявам всичко в UTC и да обработвам всякакви измествания на часовата зона в предния край, когато информацията се представя на потребителя. Това поддържа всичко последователно и не е нужно да се притеснявам дали редът е бил вмъкнат в 18:00 въз основа на компютърното време на потребителя, времето на браузъра на потребителя, времето на моята база данни или времето на сървъра.
- Дати не трябва никога да се съхранява като низ. Използвайте подходящия тип данни за дата, час, час или клеймо за дата . Това ще ви помогне много по-късно, когато трябва да го извлечете, да го сравните или да го използвате при изчисления. Друго важно решение е как сте избрали да обработвате часовите зони . Обичам да съхранявам всичко в UTC и да обработвам всякакви измествания на часовата зона в предния край, когато информацията се представя на потребителя. Това поддържа всичко последователно и не е нужно да се притеснявам дали редът е бил вмъкнат в 18:00 въз основа на компютърното време на потребителя, времето на браузъра на потребителя, времето на моята база данни или времето на сървъра.
-
Включете
ID
полета което е уникално за реда във всяка таблица. Най-лесният начин да направите това е да използватеauto_increment
(mysql) илиidentity(1,1)
(sql сървър), така че базата данни да го следи вместо вас. Тези стойности могат да бъдат нулирани или повторно заредени, ако имате нужда. -
Научете се да използвате normalization .
-
Научете какви транзакции правете и защо са важни... дори и да не ги използвате.
-
Научете за различните видове съединения . Това е едно от най-добрите обяснения Виждал съм. Основното нещо, на което трябва да обърнете внимание, е дали съединението трябва да бъде външно или вътрешно.
-
Научете за SQL инжекция и по-важното, как за да го предотврати (тази връзка е за PHP).
-
Ако използвате PHP, не използвайте стария
mysql_
клас. Вместо това използвайтеPDO
илиMySQLi_
. Информация... -
Голямото нещо при базите данни е целостта на данните, валидирането и санирането . Потребителите ще искат да поставят всякакви небрежни, мръсни данни във вашите таблици. Дали е МО или Мисури? Жена, Ж, жена, момиче или да? Заплатата е 15,00 на час, 50k годишно или 3000 на заплата? Дали е 31.12.2013 г., 31.12.2013 г., 12-31-13, 31 декември 2013 г. или тридесет и първи декември две хиляди и тринадесета година?
-
Решете дали искате да разрешите
NULL
или не. Това прави нещата по-сложни поради логиката на тройното състояние и ще трябва да проверите за това по-късно. Някои хора решават да използват просто празен низ вместо това. NULL е по-скоро състояние, отколкото действителна стойност и означава недефинирана или неизвестна - стойността може да бъде всякаква. Използвам null защото празен низ понякога е валидна стойност за поле. Например задаване наMiddle_Initial
равенството на празен низ може да означава, че лицето няма среден инициал или може да означава, че просто не знаете какво е това. За мен тези неща са различни. За другите хора разликата няма значение. Просто помислете за числата... 0 е същото като неизвестно? -
Ако не друго, просто бъдете последователни.