Koncepter
Du har misforstået nogle grundlæggende begreber, og vanskelighederne skyldes det. Vi er nødt til at tage fat på begreberne først, ikke problemet, som du opfatter det, og følgelig vil dit problem forsvinde.
automatisk forøgede id'er, som selvfølgelig er primære nøgler.
Nej de er ikke. Det er en almindelig misforståelse. Og problemer vil med garanti opstå.
Et ID
felt kan ikke være en primær nøgle i engelsk eller teknisk eller relationel betydning.
-
Selvfølgelig kan du erklære hvilken som helst i SQL felt til at være en
PRIMÆR NØGLE
, men det forvandler den ikke på magisk vis til en primær nøgle i engelsk, teknisk eller relationel betydning. Du kan navngive en chihuahua "Rottweiller", men det forvandler den ikke til en Rottweiller, den forbliver en chihuahua. Som ethvert sprog udfører SQL blot de kommandoer, du giver det, det forstår ikkePRIMARY KEY
for at betyde noget Relationelt, slår det bare et unikt indeks på kolonnen (eller feltet). -
Problemet er, at du har erklæret
ID
at være enPRIMÆR NØGLE
, du tror af det som en primær nøgle, og du kan forvente at den har nogle af kvaliteterne af en Primær Nøgle. Bortset fra det unikke ved ID'et værdi , giver det ingen fordel. Det har ingen af egenskaberne som en Primær Nøgle, eller nogen form for Relationel Nøgle for den sags skyld. Det er ikke en nøgle i engelsk, teknisk eller relationel betydning. Ved at erklære en ikke-nøgle for at være en nøgle, vil du kun forvirre dig selv, og du vil først finde ud af, at der er noget frygteligt galt, når brugeren klager over dubletter i tabellen.
Relationstabeller skal have række unikhed
En PRIMÆR NØGLE
på et ID
feltet giver ikke række unikhed. Derfor er det ikke en relationstabel, der indeholder rækker, og hvis den ikke er det, så er det en fil, der indeholder poster. Den har ikke den integritet eller kraft (på dette stadium vil du kun være opmærksom på join-kraft) eller hastighed, som en tabel i en relationsdatabase har.
Udfør denne kode (MS SQL 2008) og bevis det for dig selv. Vær venlig ikke blot at læse dette og forstå det, og fortsæt derefter med at læse resten af dette svar, denne kode skal udføres før du læser videre . Det har helbredende værdi.
CREATE TABLE dumb_file ( id INT IKKE NULL IDENTITET PRIMÆR NØGLE, navn_første CHAR(30) IKKE NULL, navn_sidste CHAR(30) IKKE NULL ) INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- lykkes INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- lykkes, men ikke tilsigtet INSERT dumb_file VALUES ( "Mickey", "Mouse") -- lykkes, men ikke beregnet SELECT * FROM dumb_file
Bemærk, at du har dublerede rækker . Relationstabeller skal have unikke rækker . Yderligere bevis på, at du ikke har en relationel tabel, eller nogen af kvaliteterne ved en.
Bemærk, at i din rapport er det eneste, der er unikt, ID
felt, som ingen bruger bekymrer sig om, ingen bruger ser, fordi det ikke er data, er det noget ekstra sludder, som en eller anden meget dum "lærer" har bedt dig om at lægge i hver fil. Du har rekord unikhed, men ikke række unikhed.
Med hensyn til data (de reelle data minus de uvedkommende tilføjelser), dataene name_last
og name_first
kan eksistere uden ID
Mark. En person har fornavn og efternavn uden at et ID er stemplet i panden.
Den anden ting, du bruger, der forvirrer dig, er AUTOINCREMENT.
Hvis du implementerer et registreringssystem uden relationel kapacitet, er det sikkert nyttigt, du behøver ikke at kode stigningen, når du indsætter poster. Men hvis du implementerer en relationel database, tjener den slet ikke noget formål, fordi du aldrig vil bruge den. Der er mange funktioner i SQL, som de fleste aldrig bruger.
Korrigerende handling
Så hvordan opgraderer, hæver du den dumb_file, der er fuld af duplikerede rækker, til en relationstabel, for at få nogle af kvaliteterne og fordelene ved en relationstabel? Der er tre trin til dette.
-
Du skal forstå Keys
- Og siden vi er gået fra ISAM-filer fra 1970'erne til Relationel Model , skal du forstå Relationelle nøgler . Det vil sige, hvis du ønsker at opnå fordelene (integritet, kraft, hastighed) ved en relationel database.
Dr. E F Cood, i hans RM , erklærede, at:
en nøgle består af dataene
og
rækkerne i en tabel skal være unikke
Din "nøgle" består ikke af dataene. Det er en ekstra, ikke-dataparasit, forårsaget af, at du er inficeret med din "lærers" sygdom. Erkend det som sådan, og tillad dig selv den fulde mentale kapacitet, som Gud gav dig (bemærk, at jeg ikke beder dig om at tænke i isolerede eller fragmenterede eller abstrakte termer, alle elementerne i en database skal integreres med hinanden). Lav en rigtig nøgle ud fra dataene og kun fra data. I dette tilfælde er der kun én mulig nøgle:
(navn_efternavn, navn_først).
-
Prøv denne kode , erklærer en unik begrænsning på dataene:
CREATE TABLE dumb_table ( id INT IKKE NULL IDENTITET PRIMÆR NØGLE, name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT UK UNIQUE ( name_last, name_first ) ) INSERT dumb_table VALUES ( "mickey" "Mouse") -- lykkes INSERT dumb_table VALUES ( "Mickey", "Mouse") -- mislykkes, som tilsigtet INSERT dumb_table VALUES ( "Minnie", "Mouse") -- lykkes SELECT * FROM dumb_table
Nu har vi række unikke . Det er den sekvens, der sker for de fleste mennesker:de opretter en fil, der tillader duper; de aner ikke, hvorfor duper dukker op i rullemenuerne; brugeren skriger; de justerer filen og tilføjer et indeks for at forhindre duper; de går til næste fejlrettelse. (De kan gøre det korrekt eller ej, det er en anden historie.)
-
Det andet niveau. For tænkende mennesker, der tænker ud over fix-its. Da vi nu har række unikke, hvad i himlens navn er formålet med
ID
felt, hvorfor har vi det overhovedet ??? Åh, fordi chihuahuaen hedder Rotty, og vi er bange for at røre ved den.Erklæringen om, at det er en
PRIMÆR NØGLE
er falsk, men den forbliver og forårsager forvirring og falske forventninger. Den eneste ægte nøgle, der findes, er(navn_efter, navn_næve),
og det er en alternativ nøgle på dette tidspunkt.Derfor
ID
felt er totalt overflødigt; og det samme er indekset, der understøtter det; og det samme er den dummeAUTOINCREMENT
; og det samme er den falske erklæring om, at det er enPRIMÆR NØGLE
; og eventuelle forventninger, du måtte have til det, er falske.Fjern derfor det overflødige
ID
Mark. Prøv denne kode :CREATE TABLE honest_table ( name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT PK PRIMARY KEY ( name_last, name_first ) INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- lykkes INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- mislykkes som tilsigtet INSERT honest_table VALUES ( "Minnie", "Mouse") -- lykkes SELECT * FROM honest_table
Fungerer fint, fungerer efter hensigten, uden de uvedkommende felter og indekser.
Husk dette, og gør det rigtigt, hver eneste gang.
Falske lærere
I disse endetider vil vi som anbefalet have mange af dem. Bemærk godt, de "lærere", der udbreder ID
kolonner, i kraft af de detaljerede beviser i dette indlæg, forstår simpelthen ikke Relationel Model eller relationelle databaser. Især dem, der skriver bøger om det.
Som det fremgår, sidder de fast i ISAM-teknologien før 1970. Det er alt, de forstår, og det er alt, hvad de kan lære. De bruger en SQL-databasecontainer for at lette adgangen, gendannelse, sikkerhedskopiering osv., men indholdet er rent Record Filing System uden relationel integritet, kraft eller hastighed. AFAIC, det er et alvorligt bedrageri.
Ud over ID
felter, er der selvfølgelig adskillige elementer, der er centrale Relationelle-eller-ej-begreber, som samlet set får mig til at drage en så alvorlig konklusion. Disse andre elementer er uden for rammerne af dette indlæg.
Et bestemt par idioter er i øjeblikket i gang med et angreb på First Normal Form. De hører hjemme i asylet.
Svar
Nu til resten af dit spørgsmål.
Er der en måde, hvorpå jeg kan oprette en relationstabel uden at miste funktioner til automatisk stigning?
Det er en selvmodsigende sætning. Jeg stoler på, at du vil forstå ud fra min forklaring, Relationstabeller har intet behov for AUTOINCREMENT
"funktioner"; hvis filen har AUTOINCREMENT
, det er ikke en relationstabel.
AUTOINCREMENT
er kun god til én ting:hvis, og kun hvis, du vil oprette et Excel-regneark i SQL-databasecontaineren, fyldt med felter med navnet A,
B,
og C,
på tværs af toppen, og optag tal nede i venstre side. I databasetermer er det resultatet af en SELECT, en fladtrykt visning af dataene, altså ikke kilden af data, som er organiseret (normaliseret).
En anden mulig (men ikke foretrukken) løsning kan være, at der er en anden primær nøgle i den første tabel, som er brugernavnet på brugeren, selvfølgelig ikke med en auto-increment-sætning. Er det uundgåeligt?
I teknisk arbejde er vi ligeglade med præferencer, for det er subjektivt, og det ændrer sig hele tiden. Vi bekymrer os om teknisk korrekthed, fordi det er objektivt, og det ændrer sig ikke.
Ja, det er uundgåeligt. For det er bare et spørgsmål om tid; antal fejl; antal "kan ikke gøres"; antal brugerskrig, indtil du står over for fakta, overvinder dine falske erklæringer og indser, at:
-
den eneste måde at sikre, at brugeren rækker er unikke, at brugernavne er unikke, er at erklære en
UNIQUE
begrænsning på det -
og slippe af med
bruger_id
ellerid
i brugerfilen -
som promoverer
brugernavn
tilPRIMÆR NØGLE
Ja, fordi hele dit problem med den tredje tabel, ikke tilfældigt, er så elimineret.
Den tredje tabel er en Associativ tabel . Den eneste nødvendige nøgle (primær nøgle) er en sammensætning af de to overordnede primærnøgler. Det sikrer entydigt rækkerne , som er identificeret med deres nøgler, ikke ved deres ID'er.
Jeg advarer dig om det, fordi de samme "lærere", som lærte dig fejlen ved at implementere ID
felter, lærer fejlen ved implementering af ID
felter i den associative tabel, hvor den ligesom med en almindelig tabel er overflødig, ikke tjener noget formål, introducerer dubletter og skaber forvirring. Og det er dobbelt overflødigt, fordi de to nøgler, der giver, allerede er der og stirrer os i ansigtet.
Da de ikke forstår RM , eller Relationelle termer, kalder de associative tabeller "link" eller "kort" tabeller. Hvis de har et ID
felt, er de i virkeligheden filer.
Opslagstabeller
ID
felter er især dum ting at gøre til opslags- eller referencetabeller. De fleste af dem har genkendelige koder, der er ingen grund til at opregne listen over koder i dem, fordi koderne er (skal være) unikke.
Derudover er det en god ting at have koderne i de underordnede tabeller som FK'er:koden er meget mere meningsfuld, og den sparer ofte en unødvendig joinforbindelse:
VÆLG ... FRA child_table -- ikke opslagstabellen WHERE gender_code ="M" -- FK i barnet, PK i opslag
i stedet for:
VÆLG ... FRA child_table WHERE gender_id =6 -- meningsløst for vedligeholderen
eller værre:
VÆLG ... FRA child_table C -- at du forsøger at bestemme JOIN lookup_table L ON C.gender_id =L.gender_id WHERE L.gender_code ="M" -- meningsfuld, kendt
Bemærk, at dette er noget, man ikke kan undgå:du har brug for unikhed på opslagskoden og unikhed på beskrivelsen. Det er den eneste metode til at forhindre dubletter i hver af de to kolonner:
OPRET TABEL køn ( gender_code CHAR(2) NOT NULL, name CHAR(30) NOT NULL CONSTRAINT PK PRIMÆR NØGLE ( gender_code ) CONSTRAINT AK UNIQUE ( navn ) )
Fuldt eksempel
Ud fra detaljerne i dit spørgsmål formoder jeg, at du har SQL-syntaks og FK-definitionsproblemer, så jeg vil give hele den løsning, du har brug for som et eksempel (da du ikke har givet fildefinitioner):
CREATE TABLE-bruger ( -- Typisk identifikationstabel user_name CHAR(16) NOT NULL, -- Short PK name_first CHAR(30) NOT NULL, -- Alt Key.1 name_last CHAR(30) NOT NULL, - - Alt Key.2 fødselsdato DATO IKKE NULL -- Alt Key.3 BEGRÆNSNING PK -- unikt brugernavn PRIMÆR NØGLE ( brugernavn ) CONSTRAINT AK -- unik personidentifikation PRIMÆR NØGLE ( navn_efternavn, navn_først, fødselsdato ) ) OPRET BORD sport ( -- Typisk Opslagstabel sport_code CHAR(4) NOT NULL, -- PK Kort kodenavn CHAR(30) NOT NULL -- AK CONSTRAINT PK PRIMARY KEY ( sport_code ) CONSTRAINT AK PRIMARY KEY ( navn ) ) OPRET TABEL bruger_sport ( -- Typisk associativ tabel brugernavn CHAR(16) NOT NULL, -- PK.1, FK sport_code CHAR(4) NOT NULL, -- PK.2, FK start_ dato DATO IKKE NULL BEGRÆNSNING PK PRIMÆR NØGLE ( bruger_navn, sport_kode ) BEGRÆNSNING user_plays_sport_fk UDENLANDSKE NØGLE ( brugernavn ) REFERENCER bruger ( brugernavn ) KONSTRAINT sport_occupies_bruger_fk UDENLANDSKE NØGLE ( sport_kode ) REFERENCER sport (sportskode) (sportskode)
Der er den PRIMÆR NØGLE
erklæringen er ærlig, den er en primær nøgle; intet ID;
ingen AUTOINCREMENT;
ingen ekstra indekser; ingen duplikerede rækker; ingen fejlagtige forventninger; ingen følgeproblemer.
Datamodel
Her er datamodellen, der passer til definitionerne.
-
Hvis du ikke er vant til notationen, skal du være opmærksom på, at hvert lille flueben, hak og mærke, de ubrudte vs stiplede linjer, de firkantede vs runde hjørner, betyder noget meget specifikt. Se IDEF1X-notation .
-
Et billede siger mere end tusind ord; i dette tilfælde er et standard-klagebillede mere værd end det; en dårlig er ikke papiret værd, den er tegnet på.
-
Tjek venligst verbets sætninger omhyggeligt, de består af et sæt prædikater. Resten af prædikaterne kan bestemmes direkte fra modellen. Hvis dette ikke er klart, så spørg venligst.