sql >> Databasteknik >  >> RDS >> Mysql

SQL:Skapar en relationstabell med 2 olika auto_increment

Koncept

Du har missuppfattat vissa grundläggande begrepp, och svårigheterna blir resultatet av det. Vi måste ta itu med begreppen först, inte problemet som du uppfattar det, och följaktligen kommer ditt problem att försvinna.

automatiskt inkrementerade ID, som naturligtvis är primärnycklar.

Nej det är de inte. Det är en vanlig missuppfattning. Och problem kommer garanterat att uppstå.

Ett ID fältet kan inte vara en primär nyckel i engelska eller tekniska eller relationella betydelser.

  • Visst, i SQL kan du deklarera alla fältet ska vara en PRIMARY KEY , men det förvandlar den inte på magiskt sätt till en primärnyckel i engelska, tekniska eller relationella bemärkelser. Du kan döpa en chihuahua till "Rottweiller", men det förvandlar den inte till en rottweiller, den förblir en chihuahua. Som alla språk, kör SQL helt enkelt kommandona som du ger det, det förstår inte PRIMARY KEY för att betyda något Relationellt, slår det bara ett unikt index på kolumnen (eller fältet).

  • Problemet är att du har deklarerat ID vara en PRIMARY KEY , du tänker av den som en primärnyckel, och du kan förvänta dig att den har några av egenskaperna hos en Primärnyckel. Förutom det unika med ID-värdet värde , det ger ingen fördel. Den har ingen av egenskaperna hos en primärnyckel, eller någon form av relationsnyckel för den delen. Det är inte en nyckel i engelska, tekniska eller relationella betydelser. Genom att förklara att en icke-nyckel är en nyckel, kommer du bara att förvirra dig själv, och du kommer att upptäcka att det är något fruktansvärt fel först när användaren klagar på dubbletter i tabellen.

Relationstabeller måste ha rad unika

En PRIMARY KEY på ett ID fältet innehåller inte rad unikhet. Därför är det inte en relationstabell som innehåller rader, och om det inte är det är det en fil som innehåller poster. Den har inte någon av den integritet eller kraft (i detta skede kommer du bara att vara medveten om join-power) eller hastighet som en tabell i en relationsdatabas har.

Kör denna kod (MS SQL 2008) och bevisa det för dig själv. Vänligen läs inte bara detta och förstå det, och fortsätt sedan med att läsa resten av det här svaret, den här koden måste köras innan du läser vidare . Det har botande värde.

    CREATE TABLE dumb_file (
        id         INT      NOT NULL  IDENTITY  PRIMARY KEY,
        name_first CHAR(30) NOT NULL,
        name_last  CHAR(30) NOT NULL
        )

    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds
    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds, but not intended
    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds, but not intended

    SELECT * FROM dumb_file

Lägg märke till att du har dubbletter av rader . Relationstabeller måste ha unika rader . Ytterligare bevis på att du inte har en relationstabell, eller någon av egenskaperna hos en.

Lägg märke till att i din rapport är det enda som är unikt ID fältet, som ingen användare bryr sig om, ingen användare ser, eftersom det inte är data, det är något extra nonsens som någon väldigt dum "lärare" sa åt dig att lägga i varje fil. Du har rekord unikhet men inte rad unikhet.

När det gäller data (den verkliga datan minus de främmande tilläggen), data name_last och name_first kan existera utan ID fält. En person har ett för- och efternamn utan att legitimation är stämplad i pannan.

Det andra du använder som förvirrar dig är AUTOINCREMENT. Om du implementerar ett registerarkiveringssystem utan relationskapacitet är det säkert till hjälp, du behöver inte koda inkrementet när du infogar poster. Men om du implementerar en relationsdatabas tjänar den inget syfte alls, eftersom du aldrig kommer att använda den. Det finns många funktioner i SQL som de flesta aldrig använder.

Korrigerande åtgärd

Så hur uppgraderar, höjer du den dumb_filen som är full av dubbletter av rader till en relationstabell, för att få några av egenskaperna och fördelarna med en relationstabell? Det finns tre steg för detta.

  1. Du måste förstå Keys

    • Och sedan vi har gått från ISAM-filer från 1970-talet till Relationsmodellen måste du förstå Relationsnycklar . Det vill säga om du vill få fördelarna (integritet, kraft, hastighet) med en relationsdatabas.

    Dr E F Cood, i hans RM , förklarade att:

    en nyckel består av data

    och

    raderna i en tabell måste vara unika

    Din "nyckel" består inte av data. Det är en ytterligare, icke-dataparasit, orsakad av att du är infekterad med din "lärares" sjukdom. Känn igen det som sådant och tillåt dig själv hela den mentala kapacitet som Gud gav dig (lägg märke till att jag inte ber dig att tänka i isolerade eller fragmenterade eller abstrakta termer, alla element i en databas måste integreras med varandra). Skapa en riktig nyckel av data, och endast från data. I det här fallet finns det bara en möjlig nyckel:(name_last, name_first).

  2. Prova den här koden , deklarera en unik begränsning av data:

         CREATE TABLE dumb_table (
            id         INT      NOT NULL  IDENTITY  PRIMARY KEY,
            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" )  -- succeeds
        INSERT dumb_table VALUES ( "Mickey", "Mouse" )  -- fails, as intended
        INSERT dumb_table VALUES ( "Minnie", "Mouse" )  -- succeeds
    
        SELECT * FROM dumb_table
    

    Nu har vi radunikthet . Det är den sekvens som händer de flesta människor:de skapar en fil som tillåter duperingar; de har ingen aning om varför duper dyker upp i rullgardinsmenyn; användaren skriker; de finjusterar filen och lägger till ett index för att förhindra duper; de går till nästa buggfix. (De kan göra det korrekt eller inte, det är en annan historia.)

  3. Den andra nivån. För tänkande människor som tänker bortom fix-its. Eftersom vi nu har unika rader, vad i himlens namn är syftet med ID fältet, varför har vi det ens ??? Åh, för att chihuahuan heter Rotty och vi är rädda för att röra vid den.

    Deklarationen att det är en PRIMARY KEY är falsk, men den förblir, vilket orsakar förvirring och falska förväntningar. Den enda äkta nyckeln som finns är (name_last, name_fist), och det är en alternativ nyckel vid det här laget.

    Därför ID fältet är helt överflödigt; och så är indexet som stöder det; och så är den dumma AUTOINCREMENT; och så är den falska deklarationen att det är en PRIMARY KEY; och alla förväntningar du kan ha på det är falska.

    Ta därför bort det överflödiga ID fält. Prova den här koden :

        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" )  -- succeeds
        INSERT honest_table VALUES ( "Mickey", "Mouse" )  -- fails, as intended
        INSERT honest_table VALUES ( "Minnie", "Mouse" )  -- succeeds
    
        SELECT * FROM honest_table
    

    Fungerar bra, fungerar som det är tänkt, utan främmande fält och index.

    Kom ihåg detta och gör det rätt, varje gång.

Falsklärare

I dessa yttersta tider kommer vi att ha många av dem. Observera väl, "lärarna" som sprider ID kolumner, på grund av de detaljerade bevisen i detta inlägg, förstår helt enkelt inte Relationsmodellen eller relationsdatabaser. Speciellt de som skriver böcker om det.

Som visats har de fastnat i ISAM-tekniken före 1970. Det är allt de förstår, och det är allt de kan lära ut. De använder en SQL-databasbehållare för att underlätta åtkomst, återställning, säkerhetskopiering, etc, men innehållet är ett rent registerarkiveringssystem utan relationsintegritet, kraft eller hastighet. AFAIC, det är ett allvarligt bedrägeri.

Förutom ID fält, naturligtvis, det finns flera saker som är viktiga Relationella-eller-ej-begrepp, som tillsammans får mig att dra en så allvarlig slutsats. Dessa andra föremål ligger utanför det här inläggets omfattning.

Ett särskilt par idioter utför för närvarande ett angrepp på First Normal Form. De hör hemma i asylet.

Svar

Nu till resten av din fråga.

Finns det något sätt jag kan skapa en relationstabell utan att förlora funktioner för automatisk ökning?

Det är en mening som motsäger sig själv. Jag litar på att du kommer att förstå av min förklaring, relationstabeller har inget behov för AUTOINCREMENT "funktioner"; om filen har AUTOINCREMENT , det är inte en relationstabell.

AUTOINCREMENT är bra för bara en sak:om, och bara om, du vill skapa ett Excel-kalkylblad i SQL-databasbehållaren, fylld med fält med namnet A, B, och C, längst upp och spela in siffror längst till vänster. I databastermer är det resultatet av en SELECT, en tillplattad vy av data, det vill säga inte källan av data, som är organiserad (normaliserad).

En annan möjlig (men inte föredragen) lösning kan vara att det finns en annan primärnyckel i den första tabellen, vilket är användarens användarnamn, inte med en automatisk inkrementsats, förstås. Är det oundvikligt?

I tekniskt arbete bryr vi oss inte om preferenser, eftersom det är subjektivt, och det förändras hela tiden. Vi bryr oss om teknisk korrekthet, eftersom det är objektivt, och det förändras inte.

Ja, det är oundvikligt. För det är bara en tidsfråga; antal buggar; antal "kan inte göra"; antal användarskrik, tills du inser fakta, övervinner dina falska deklarationer och inser att:

  • det enda sättet att säkerställa att användaren rader är unika, att användarnamn är unika, är att deklarera en UNIQUE begränsning på det

  • och bli av med user_id eller id i användarfilen

  • som främjar user_name till PRIMARY KEY

Ja, eftersom hela ditt problem med det tredje bordet, inte av en slump, då elimineras.

Den tredje tabellen är en associativ tabell . Den enda nyckel som krävs (primärnyckel) är en sammansättning av de två överordnade primärnycklarna. Det säkerställer att raderna är unika , som identifieras av deras nycklar, inte av deras IDs.

Jag varnar dig för det eftersom samma "lärare" som lärde dig felet att implementera ID fält, lär dig felet med att implementera ID fält i den associativa tabellen, där den, precis som med en vanlig tabell, är överflödig, inte tjänar något syfte, introducerar dubbletter och orsakar förvirring. Och det är dubbelt överflödigt eftersom de två nycklarna som ger redan finns där och stirrar oss i ansiktet.

Eftersom de inte förstår RM , eller Relationella termer, kallar de associativa tabeller "länk" eller "karta"-tabeller. Om de har ett ID fältet är de i själva verket filer.

Söktabeller

ID fält är särskilt dum sak att göra för uppslags- eller referenstabeller. De flesta av dem har igenkännbara koder, det finns ingen anledning att räkna upp listan med koder i dem, eftersom koderna är (ska vara) unika.

Dessutom är det bra att ha koderna i de underordnade tabellerna som FK:er:koden är mycket mer meningsfull och den sparar ofta en onödig koppling:

    SELECT ...
        FROM child_table           -- not the lookup table
        WHERE gender_code = "M"    -- FK in the child, PK in the lookup

istället för:

    SELECT ...
        FROM child_table
        WHERE gender_id = 6        -- meaningless to the maintainer

eller ännu värre:

    SELECT ...
        FROM child_table C         -- that you are trying to determine
        JOIN lookup_table L
            ON C.gender_id = L.gender_id
        WHERE L.gender_code = "M"  -- meaningful, known

Observera att detta är något man inte kan undvika:du behöver unikhet på uppslagskoden och unika på beskrivningen. Det är den enda metoden för att förhindra dubbletter i varje av de två kolumnerna:

    CREATE TABLE gender (
        gender_code  CHAR(2)  NOT NULL,
        name         CHAR(30) NOT NULL

        CONSTRAINT PK 
            PRIMARY KEY ( gender_code )

        CONSTRAINT AK 
            UNIQUE ( name )
        )

Fullständigt exempel

Från detaljerna i din fråga misstänker jag att du har SQL-syntax och FK-definitionsproblem, så jag kommer att ge hela lösningen du behöver som ett exempel (eftersom du inte har angett fildefinitioner):

    CREATE TABLE user (                 -- Typical Identifying Table
        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
        birth_date DATE     NOT NULL    -- Alt Key.3

        CONSTRAINT PK                   -- unique user_name
            PRIMARY KEY ( user_name )

        CONSTRAINT AK                   -- unique person identification
            PRIMARY KEY ( name_last, name_first, birth_date )
        )

    CREATE TABLE sport (                  -- Typical Lookup Table
        sport_code  CHAR(4)  NOT NULL,    -- PK Short code
        name        CHAR(30) NOT NULL     -- AK

        CONSTRAINT PK 
            PRIMARY KEY ( sport_code )

        CONSTRAINT AK 
            PRIMARY KEY ( name )
        )

    CREATE TABLE user_sport (           -- Typical Associative Table
        user_name  CHAR(16) NOT NULL,   -- PK.1, FK
        sport_code CHAR(4)  NOT NULL,   -- PK.2, FK
        start_date DATE     NOT NULL

        CONSTRAINT PK 
            PRIMARY KEY ( user_name, sport_code )

        CONSTRAINT user_plays_sport_fk
            FOREIGN KEY     ( user_name )
            REFERENCES user ( user_name )

        CONSTRAINT sport_occupies_user_fk
            FOREIGN KEY      ( sport_code )
            REFERENCES sport ( sport_code )
        )

Där, PRIMARY KEY deklarationen är ärlig, den är en primärnyckel; inget ID; ingen AUTOINCREMENT; inga extra index; inga dubbletter av rader; inga felaktiga förväntningar; inga följdproblem.

Datamodell

Här är datamodellen för definitionerna.

  • Exempel på användarsportdatamodell

  • Om du inte är van vid notationen, tänk på att varje liten bock, hack och markering, de heldragna vs streckade linjerna, de fyrkantiga vs runda hörnen, betyder något mycket specifikt. Se IDEF1X-notation .

  • En bild säger mer än tusen ord; i detta fall är en standard-klagomålsbild värd mer än så; en dålig är inte värd pappret den är ritad på.

  • Vänligen kontrollera verbfraserna noggrant, de består av en uppsättning predikat. Resten av predikaten kan bestämmas direkt från modellen. Fråga om detta inte är tydligt.




  1. Hur man installerar phpMyAdmin

  2. Partial Index används inte i ON CONFLICT-satsen när du utför en upsert i Postgresql

  3. MYSQLi-fel:Användaren har redan fler än "max_user_connections" aktiva anslutningar

  4. Hur man övervakar PostgreSQL 12-prestanda med OmniDB – Del 2