sql >> Database teknologi >  >> RDS >> Mysql

Mysql og FK's problem

Fremmednøglekolonnen(-erne) skal referere til kolonne(r), der omfatter et præfiks længst til venstre for den primære nøgle eller en unik nøgle i den overordnede tabel.

Med andre ord virker følgende eksempler i InnoDB:

CREATE TABLE Foo ( a INT, b INT, c INT, PRIMARY KEY (a,b,c) );
CREATE TABLE Bar ( x INT, y INT );

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(b,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,b); -- RIGHT

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(b); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(a); -- RIGHT

Du fik en fejl, fordi du forsøger at gøre det, der svarer til (x) referencer Foo(b).
Din kolonne codmenuitem er den anden af ​​tre kolonner i den primære nøgle for overordnet.

Det ville fungere, hvis smenuitememp.codemenuitem skulle henvise til smenuitem.codmodulo , fordi den kolonne er kolonnen længst til venstre i den overordnede tabels primære nøgle.

Til dit opfølgende spørgsmål:

Husk den måde, fremmednøgler fungerer på. Hver gang du indsætter eller opdaterer en række i den underordnede tabel, skal den slå en række op i den overordnede tabel for at bekræfte, at værdien findes i den refererede kolonne. Hvis kolonnen ikke er indekseret, skal den lave en tabelscanning for at opnå dette opslag, og det ville være meget dyrt, forudsat at din overordnede tabel vokser.

Hvis du prøver at slå en række op baseret på den midterste kolonne i et indeks med flere kolonner, hjælper indekset dig ikke. Analogt er det som at søge i en telefonbog for alle personer med et bestemt mellemnavn.

Standard ANSI SQL kræver, at den refererede kolonne er en del af en PRIMÆR NØGLE eller UNIK NØGLE, og det kræver, at de fremmede nøglekolonner matcher alle kolonnerne af en primær eller unik begrænsning i den overordnede.

Men InnoDB er mere eftergivende. Det kræver stadig, at den refererede kolonne i den overordnede tabel indekseres, så opslaget kan være effektivt, og at de refererede kolonner er længst til venstre i indekset. Men et ikke-unik indeks er okay; det er tilladt for en fremmednøgle at referere til den.

Dette kan føre til mærkelige tilfælde som en underordnet række, der refererer til mere end én række i forælderen, men det forventes, at du vil håndtere sådanne uregelmæssigheder.

Jeg føler behov for at understrege det sidste punkt. Du vil få unormale data, hvis du definerer fremmednøgler til ikke-entydigt indekserede kolonner i det overordnede. Dette vil sandsynligvis få dine forespørgsler til at rapportere rækker flere gange, når du tilmelder dig. Du bør ikke bruge denne adfærd fra InnoDB; du bør kun definere fremmednøgler til overordnede kolonner, der er unikke.




  1. Sådan får du rollens kommentar fra PostgreSQL-databasen

  2. mysqli_num_rows virker ikke korrekt

  3. Kodning af parameter-værdi for SELECT i PHP-MySQL

  4. serverens tidszoneværdi 'CDT' er ikke genkendt eller repræsenterer mere end én tidszone