Dina fel orsakas på grund av felaktig syntax för främmande nyckel.
Men Jag tycker att du ska använda ID-fält istället för att göra strängsammansatta primärnycklar . Det finns några problem med din metod...
-
Det kommer att göra det svårare för DB att sammanfoga tabeller jämfört med att använda ett heltalsfält (ID) för att ansluta (svårare ==längre bearbetningstid).
-
Det är giltigt att ha flera personer med samma namn, även med en mellaninitial.
-
Vad händer om du måste ändra någons namn? Antingen för att det lagrades fel eller att de gifte sig eller så... Det betyder att du inte bara behöver uppdatera din
employee
tabellen, menworks
tabellen och alla andra tabeller som du har använt namnet som en främmande nyckel.
Ta en titt på detta:http://sqlfiddle.com/#! 2/2dc8c/3/0
Jag har lagt till ett tabell-ID till varje tabell . Det är en unsigned int
, vilket betyder att det inte kan vara negativt (eftersom det inte skulle vara så meningsfullt). Det är också auto_increment
, vilket innebär att varje gång du lägger till en rad i tabellen kommer detta ID att genereras automatiskt och gå upp 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 skulle lägga till saker till den här tabellen så här:
insert into Employee (Employee_ID, LastName, FirstName, MidInitial)
values (null, 'Smith', 'John', 'K');
null
kommer att bli det automatiskt genererade ID:t. Det kommer att vara unikt för varje rad.
Dessutom en unik begränsning innebär att kombinationen av dessa fält måste vara unik i tabellen. Men med ett tillräckligt stort företag slår jag vad om att två personer kommer att ha samma namn. I det verkliga livet skulle jag föreslå att du tar bort denna unika begränsning.
Jag gjorde liknande ändringar i företagstabellen...
create table company(
company_ID int unsigned auto_increment primary key,
company_name varchar(20),
city varchar(10),
unique (company_name)
);
Saker kan läggas till som:
insert into company values (null, 'Taco Bell', 'Paris');
Så... för works
.... istället för att lagra det fullständiga namnet på varje person och det fullständiga företagsnamnet om och om igen i denna tabell, nu behöver vi bara lagra ID:s.
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 lägga till saker i works
så här:
insert into Works values (null, 1, 1, '10.00');
Eftersom John Smith var vår första anställd skulle hans Employee_ID vara 1. För att verifiera det, försök bara select * from Employee where FirstName='John' and LastName='Smith'
. Taco Bell skulle också få company_id =1. Genom att infoga dessa värden i works
, det betyder att John nu jobbar på Taco Bell.
Jag skulle också föreslå att du lägger till fält som start_date
och end_date
och job_title
till ditt arbetsbord. Och du skulle vilja ta särskild hänsyn till alla unika begränsningar för det här bordet också. Människor kan arbeta för samma företag mer än en gång. De kan också ha olika jobb.
När du vill få ut din data igen använder du en fråga som denna:
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
vilket bara är ett fint sätt att säga detta:
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
Några anteckningar om databassaker...
-
Välj en namnkonvention och håll dig till den! Om du vill använda
CamelCase
, använd den överallt. Omyou_want_to_use
understryker i dina namn, använd dem överallt. Det finns massor av namnkonventioner att välja mellan:prefix attribut (kolumner/fält) med tabellnamnet, med vanliga förkortningar (eller inte), där versaler används (eller inte)... detta beror mest på personliga preferenser men det finns finns artiklar där ute om för- och nackdelar med att använda vissa. Sista anmärkningen, _bara för att du kan använda mellanslag i ett namn,__ betyder det inte att du borde.`Almost all`
databaser låter[you use spaces]
i namn om du vill men det kan orsaka många problem senare. -
Tabellnamn ska inte vara plural. Detta är ett sällskapsdjur för mig och här är anledningen:Vi vet att ett bord kommer att hålla många rekord... många personer/personer, många anställda, flera företag, flera poster av vilken typ eller typ som helst. Varje rad beskriver bara en av dessa saker. Ibland är det helt enkelt inte ens vettigt att ha namnet i plural. Andra gånger är det tveksamt - som att
works
tabell. Om du ibland gör det plural, och ibland gör det singular, kan det bli förvirrande senare. Genom att bara göra det hela singulär är det fortfarande helt vettigt, och du växlar inte fram och tillbaka eller behöver slå upp det exakta namnet när du skriver frågor. -
Datatyper är viktiga och försök att vara konsekvent över tabellerna för liknande fält (som alla
id
s samma typ; gör alla booleska fält till alla bitar eller heltal eller vad som helst, bara gör dem lika). Det finns olika storlekar av heltalstyper du kan välja mellan. Tänk på storlek, prestanda och vad som är lämpligt för dina behov. Bestäm om du verkligen behöver en nvarchar eller om en varchar är okej.- Datum ska aldrig lagras som en sträng. Använd lämplig datatyp för datum, datum och tid, tid eller tidsstämpel . Detta kommer att hjälpa dig så mycket senare när du behöver hämta det, jämföra det eller använda det i beräkningar. Ett annat viktigt beslut är hur du valde att hantera tidszoner . Jag gillar att lagra allt i UTC och hantera alla tidszonförskjutningar på fronten, när informationen presenteras för användaren. Detta håller allt konsekvent och jag behöver inte oroa mig för om raden infogades kl. 18.00 baserat på min användares datortid, användarens webbläsartid, min databas tid eller serverns tid.
- Datum ska aldrig lagras som en sträng. Använd lämplig datatyp för datum, datum och tid, tid eller tidsstämpel . Detta kommer att hjälpa dig så mycket senare när du behöver hämta det, jämföra det eller använda det i beräkningar. Ett annat viktigt beslut är hur du valde att hantera tidszoner . Jag gillar att lagra allt i UTC och hantera alla tidszonförskjutningar på fronten, när informationen presenteras för användaren. Detta håller allt konsekvent och jag behöver inte oroa mig för om raden infogades kl. 18.00 baserat på min användares datortid, användarens webbläsartid, min databas tid eller serverns tid.
-
Inkludera ett
ID
fält som är unikt för raden i varje tabell. Det enklaste sättet att göra detta är att använda enauto_increment
(mysql) elleridentity(1,1)
(sql server) så att databasen håller reda på det åt dig. Dessa värden kan återställas eller återställas om du behöver det. -
Lär dig att använda normalisering .
-
Lär dig vilka transaktioner gör och varför de är viktiga... även om du inte använder dem.
-
Lär dig mer om olika typer av kopplingar . Detta är en av de bästa förklaringarna Jag har någonsin sett. Det viktigaste att vara uppmärksam på är om sammanfogningen ska vara en yttre eller inre sammanfogning.
-
Läs mer om SQL-injektion och ännu viktigare, hur för att förhindra det (den länken är för PHP).
-
Om du använder PHP, använd inte den gamla
mysql_
klass. Använd iställetPDO
ellerMySQLi_
. Info... -
Det stora med databaser är dataintegritet, validering och sanering . Användare kommer att vilja lägga alla typer av slarviga, smutsiga data i dina tabeller. Är det MO eller Missouri? Kvinna, K, kvinna, tjej eller ja? Är lönen 15,00 i timmen, 50k årligen eller 3 000 en lönecheck? Är det 2013-12-31, 2013-12-31, 31-12-13, 31 december 2013 eller trettiofyst två tusen och tretton december?
-
Bestämma om du vill tillåta
NULL
eller inte. Det gör saker och ting mer komplicerade på grund av triple state logic och du kommer att behöva leta efter det senare. Vissa människor bestämmer sig för att bara använda en tom sträng istället. NULL är mer ett tillstånd än ett verkligt värde och det betyder odefinierat eller okänt - värdet kan vara vad som helst. Jag använder null eftersom en tom sträng ibland är ett giltigt värde för ett fält. Till exempel, ställa inMiddle_Initial
att vara lika med en tom sträng kan betyda att personen inte har en mellaninitial eller så kan det betyda att du helt enkelt inte vet vad det är. För mig är dessa saker annorlunda. För andra människor spelar skillnaden ingen roll. Tänk bara på siffror... är 0 detsamma som okänt? -
Om inget annat, var bara konsekvent.