Dine fejl er forårsaget på grund af forkert fremmednøglesyntaks.
Men Jeg synes, du skal bruge ID-felter i stedet for at lave sammensatte primærnøgler for strenge . Der er et par problemer med din metode...
-
Det vil gøre det sværere for DB'en at sammenføje tabeller sammenlignet med at bruge et heltalsfelt (ID) til at joine (sværere ==mere behandlingstid).
-
Det er gyldigt at have flere personer med samme navn, selv ved at bruge en mellembogstav.
-
Hvad sker der, hvis du bliver nødt til at ændre nogens navn? Enten fordi det blev gemt forkert, eller de blev gift eller noget... Det betyder, at du ikke kun skal opdatere din
employee
tabel, menworks
tabel og enhver anden tabel, du har brugt navnet som en fremmednøgle.
Tag et kig på dette:http://sqlfiddle.com/#! 2/2dc8c/3/0
Jeg har tilføjet et tabel-id til hver tabel . Det er en unsigned int
, hvilket betyder, at det ikke kan være negativt (fordi det ikke giver meget mening). Det er også auto_increment
, hvilket betyder, at hver gang du tilføjer en række til tabellen, bliver dette ID automatisk genereret og stiger med 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)
);
Du ville tilføje ting til denne tabel som denne:
insert into Employee (Employee_ID, LastName, FirstName, MidInitial)
values (null, 'Smith', 'John', 'K');
null
bliver det automatisk genererede ID. Det vil være unikt for hver række.
Også en unik begrænsning betyder, at kombinationen af disse felter skal være unik i tabellen. Men med et stort nok firma vil jeg vædde på, at to personer vil have det samme navn. I det virkelige liv vil jeg foreslå at fjerne denne unikke begrænsning.
Jeg lavede lignende ændringer i firmatabellen...
create table company(
company_ID int unsigned auto_increment primary key,
company_name varchar(20),
city varchar(10),
unique (company_name)
);
Ting kunne tilføjes som:
insert into company values (null, 'Taco Bell', 'Paris');
Så... for works
.... i stedet for at gemme det fulde navn på hver person og det fulde firmanavn igen og igen i denne tabel, skal vi nu kun gemme ID'erne.
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)
);
Du kan tilføje ting til works
sådan her:
insert into Works values (null, 1, 1, '10.00');
Da John Smith var vores første medarbejder, ville hans Employee_ID være 1. For at bekræfte det, prøv bare at select * from Employee where FirstName='John' and LastName='Smith'
. Taco Bell ville også få company_id =1. Ved at indsætte disse værdier i works
, det betyder, at John nu arbejder hos Taco Bell.
Jeg vil også foreslå, at du tilføjer felter som start_date
og end_date
og job_title
til dit arbejdsbord. Og du vil også gerne tage særligt hensyn til eventuelle unikke begrænsninger for dette bord. Folk kan arbejde for den samme virksomhed mere end én gang. De kan også have forskellige jobs.
Når du vil have dine data ud igen, vil du bruge en forespørgsel som denne:
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
hvilket bare er en fancy måde at sige dette på:
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
Nogle bemærkninger om databaseting...
-
Vælg en navnekonvention, og hold dig til den! Hvis du vil bruge
CamelCase
, brug det overalt. Hvisyou_want_to_use
understreger i dine navne, brug dem overalt. Der er tonsvis af navnekonventioner at vælge imellem:præfikser attributter (kolonner/felter) med tabelnavnet, brug af almindelige forkortelser (eller ej), hvor der bruges store bogstaver (eller ej)... dette kommer for det meste ned til personlige præferencer, men der er artikler derude om fordele og ulemper ved at bruge visse. Sidste bemærkning, _bare fordi du kan bruge mellemrum i et navn,__ betyder det ikke, at du skal.`Almost all`
databaser lader[you use spaces]
i navne, hvis du vil, men det kan forårsage en masse problemer senere. -
Tabelnavne bør ikke være i flertal. Dette er et kæledyr for mig, og her er hvorfor:Vi ved, at et bord vil indeholde mange rekorder... mange mennesker/personer, mange ansatte, flere virksomheder, flere poster af hvilken som helst type eller art. Hver række beskriver kun én af disse ting. Nogle gange giver det bare ikke engang mening at have navnet i flertal. Andre gange er det tvivlsomt - ligesom
works
bord. Hvis du nogle gange gør det i flertal, og nogle gange gør det ental, kan det blive forvirrende senere. Ved blot at gøre det hele ental, giver det stadig god mening, og du skifter ikke frem og tilbage eller skal slå det nøjagtige navn op, når du skriver forespørgsler. -
Datatyper er vigtige og prøv at være ensartet på tværs af tabeller for lignende felter (som alle
id
s samme type; gør alle booleske felter alle bits eller heltal eller hvad som helst, bare gør dem ens). Der er forskellige størrelser af heltalstyper, du kan vælge imellem. Tænk over størrelse, ydeevne og hvad der passer til dine behov. Beslut dig for, om du virkelig har brug for en nvarchar, eller om en varchar er i orden.- Datoer bør aldrig gemmes som en streng. Brug den relevante datatype for dato, dato, klokkeslæt eller tidsstempel . Dette vil hjælpe dig meget senere, når du skal hente det, sammenligne det eller bruge det i beregninger. En anden vigtig beslutning er, hvordan du valgte at håndtere tidszoner . Jeg kan godt lide at gemme alt i UTC og håndtere enhver tidszoneoffset ting på frontend, når informationen præsenteres for brugeren. Dette holder alt konsekvent, og jeg behøver ikke bekymre mig om, om rækken blev indsat kl. 18.00 baseret på min brugers computertid, brugerens browsertid, min databases tid eller serverens tid.
- Datoer bør aldrig gemmes som en streng. Brug den relevante datatype for dato, dato, klokkeslæt eller tidsstempel . Dette vil hjælpe dig meget senere, når du skal hente det, sammenligne det eller bruge det i beregninger. En anden vigtig beslutning er, hvordan du valgte at håndtere tidszoner . Jeg kan godt lide at gemme alt i UTC og håndtere enhver tidszoneoffset ting på frontend, når informationen præsenteres for brugeren. Dette holder alt konsekvent, og jeg behøver ikke bekymre mig om, om rækken blev indsat kl. 18.00 baseret på min brugers computertid, brugerens browsertid, min databases tid eller serverens tid.
-
Medtag et
ID
felt det er unikt for rækken i hver tabel. Den nemmeste måde at gøre dette på er at bruge enauto_increment
(mysql) elleridentity(1,1)
(sql server) felt, så databasen holder styr på det for dig. Disse værdier kan nulstilles eller genindsættes, hvis du har brug for det. -
Lær at bruge normalisering .
-
Lær hvilke transaktioner gør og hvorfor de er vigtige... også selvom du ikke bruger dem.
-
Lær om de forskellige slags joinforbindelser . Dette er en af de bedste forklaringer Jeg har nogensinde set. Det vigtigste at være opmærksom på er, om sammenføjningen skal være en ydre eller indre sammenføjning.
-
Lær om SQL-injektion og endnu vigtigere, hvordan for at forhindre det (Dette link er til PHP).
-
Hvis du bruger PHP, skal du ikke bruge den gamle
mysql_
klasse. Brug i stedetPDO
ellerMySQLi_
. Info... -
Det store ved databaser er dataintegritet, validering og rensning . Brugere vil ønske at lægge alle slags sjuskede, beskidte data ind i dine tabeller. Er det MO eller Missouri? Kvinde, K, kvinde, pige eller ja? Er lønnen 15,00 i timen, 50k årligt eller 3.000 en lønseddel? Er det 31/12/2013, 31/12/2013, 31/12/13, 31/12 2013 eller 31. december 2000 og tretten?
-
Beslut om du vil tillade
NULL
eller ikke. Det gør tingene mere komplicerede på grund af triple state logic, og du bliver nødt til at tjekke for det senere. Nogle mennesker beslutter at bruge en tom streng i stedet for. NULL er mere en tilstand end en faktisk værdi, og det betyder udefineret eller ukendt - værdien kan være hvad som helst. Jeg bruger null fordi en tom streng nogle gange er en gyldig værdi for et felt. For eksempel indstilling afMiddle_Initial
at være lig med en tom streng kan betyde, at personen ikke har en midterste initial, eller det kan betyde, at du bare ikke ved, hvad det er. For mig er disse ting anderledes. For andre mennesker er forskellen ligegyldig. Overvej bare tal... er 0 det samme som ukendt? -
Hvis ikke andet, så vær bare konsekvent.