Meddelande

Minska
No announcement yet.

Primärnyckel i relationstabell?

Minska
X
  • Filter
  • Klockan
  • Show
Clear All
new posts

  • Primärnyckel i relationstabell?

    Hallå,

    Måste man ha en primärnyckel i en relationstabell?

    Jag har en tabell som länkar ihop två andra tabeller. Poster raderas, uppdateras och läggs till där hela tiden och varje gång autoökas det med ett nytt id. Kan jag skippa det fältet helt eller finns det något syfte med att ha det? Jag kan inte komma på vad jag skulle använda fältet till. Om jag behöver fältet gissar jag att det bör vara en bigint (20) eller liknande för att rymma efter ett par års användande.

    Tack!
    bassebhu - din kompis bland kompisar

    Om du mot förmodan inte är nöjd med kompositionen av ovanstående inlägg,
    eller att det helt enkelt inte nådde upp till dina förväntningtar - var god:

    Rapportera till bassebhu

  • #2
    Nej, du behöver inte ha en primärnyckel. Åtminstone inte i MySQL. Däremot rekommenderar jag dig starkt att ha det om det inte finns något annat i tabellen som ovillkorligen är unikt för varje rad, t ex personnummer, organisationsnummer eller VAT-nummer. Om det finns något annat som är unikt kan du lika väl använda det som primärnyckel, så gör jag själv ofta.
    Avundas aldrig någon det sken av lycka han har för du känner inte hans hemliga sorger.

    Kommentera


    • #3
      Är inte PK viktigt för att snabba upp CRUD-operationer? Om du sätter en PK så indexeras väl det, och "DELETE FROM tbl WHERE id = 1" kan köras istället för en "dyrare" op, typ "DELETE FROM tbl WHERE object_id = 1 AND foreign_id = 2"?
      Johan Norberg, webbutvecklare.

      @GitHub

      Läs min blogg

      Kommentera


      • #4
        casca skrev: Visa inlägg
        Är inte PK viktigt för att snabba upp CRUD-operationer? Om du sätter en PK så indexeras väl det, och "DELETE FROM tbl WHERE id = 1" kan köras istället för en "dyrare" op, typ "DELETE FROM tbl WHERE object_id = 1 AND foreign_id = 2"?
        Jo, primärnyckel är som sagt alltid att föredra. De är som du säger indexerade och snabbar upp processen att hitta specifika rader.
        Avundas aldrig någon det sken av lycka han har för du känner inte hans hemliga sorger.

        Kommentera


        • #5
          bassebhu skrev: Visa inlägg
          Hallå,

          Måste man ha en primärnyckel i en relationstabell?

          Jag har en tabell som länkar ihop två andra tabeller. Poster raderas, uppdateras och läggs till där hela tiden och varje gång autoökas det med ett nytt id. Kan jag skippa det fältet helt eller finns det något syfte med att ha det? Jag kan inte komma på vad jag skulle använda fältet till. Om jag behöver fältet gissar jag att det bör vara en bigint (20) eller liknande för att rymma efter ett par års användande.

          Tack!
          Om tabellen saknar Primärnyckel lagras den som en heap. Det är inget man vill ha stora mängder data lagrat i, och leder ofelbart till fullständig skanning av hela tabellen varje gång du behöver hitta ett värde.

          Primärnyckeln gör att det finns ett index och att data lagras strukturerat.

          En primärnyckel utgörs av en eller flera kolumner som [tillsammans] gör varje rad unik. Om du har en relationstabell mellan två andra tabeller, så bör primärnycklarna från de två tabeller du kopplar samman tillsammans bli en naturlig primärnyckel för din kopplingstabell.

          Exempel:
          Bil (Regnr, Märke, Modell, Konstruktionsår)
          Person (Personnummer, Namn, Adress, Ålder...)

          NuvarandeBilÄgare (Regnr, Personnummer, Inköpsår, Pris...)

          En viss person (Kalle) kan äga 0, 1 eller flera bilar.
          En viss bil (ABC 123) kan ha 1 eller flera ägare.

          Men om ABC 123 finns ihop med Kalle i tabellen så kan det bara finnas en sådan rad, så dessa två kolumner kan användas som primärnyckel tillsammans.

          Men om det är bättre eller sämre än att ha en inkrementell automatisk nyckel:
          NuvarandeBilÄgare (ÄgarID, Regnr, Personnummer, Inköpsår, Pris...) beror på vad du använder tabellen till, hur mycket data du har i den, om det är viktigare att insättningar går fort än att sökningar gör det eller tvärtom, mm.

          Om primärnyckeln är klustrad, så är tabellen sparad i samma ordning som de ingående kolumnerna är ordnade. Så om du har ett ÄgarID så hamnar nya rader alltid sist, medan om din primärnyckel är (Regnr, personnummer) så hamnar ny info i bokstavsordning på 1) Regnr 2) Personnummer, vilket gör insättningar långsammare men kan göra sökningar snabbare om man oftast söker på RegNr eller kombinationen Regnr, personnummer (i det här exemplet).

          Kommentera


          • #6
            Nu vet jag inte specifikt vad det är du arbetat med, men jag gjorde nyligen en lösning som går runt det du beskriver som ett problem.

            Jag hade också två tabeller...

            Jag använder bilarna som exempel: Principen är samma eller liknande:

            [Bilar]l (ID, Regnr, Märke, Modell, Konstruktionsår)
            [Person] (ID, Personnummer, Namn, Adress, Ålder... , ägerBilarID)

            [Person]
            ....
            ägerBilarID = sträng = "1,45,56"

            Denna variant vet jag inte hur väl den fungerar i större sammanhang, men i mindre sammanhang fungerar det. (Har gjort hittills i alla fall!)

            Du slipper en tredje tabell som håller koll på de två andra, vem som äger olika bilar.

            Jag är svag för ID nummer, måste medges! Primärt för man vet vad man har, så att säga...! Jag vet inte om denna varianten skulle passa för dig! Det vet du! :-)

            Kommentera


            • #7
              angelica skrev: Visa inlägg
              Nu vet jag inte specifikt vad det är du arbetat med, men jag gjorde nyligen en lösning som går runt det du beskriver som ett problem.

              Jag hade också två tabeller...

              Jag använder bilarna som exempel: Principen är samma eller liknande:

              [Bilar]l (ID, Regnr, Märke, Modell, Konstruktionsår)
              [Person] (ID, Personnummer, Namn, Adress, Ålder... , ägerBilarID)

              [Person]
              ....
              ägerBilarID = sträng = "1,45,56"

              Denna variant vet jag inte hur väl den fungerar i större sammanhang, men i mindre sammanhang fungerar det. (Har gjort hittills i alla fall!)

              Du slipper en tredje tabell som håller koll på de två andra, vem som äger olika bilar.

              Jag är svag för ID nummer, måste medges! Primärt för man vet vad man har, så att säga...! Jag vet inte om denna varianten skulle passa för dig! Det vet du! :-)
              Jag har ibland lagrat "mindre värden" i typ en komma-separerad sträng, men jag skulle nog akta mig för att göra en sån lösning med ID-fält. Om du sätter upp foreign keys korrekt (ON DELETE CASCADE) så kan du automatiskt få databasen att plocka bort nycklar i t.ex. en relationstabell (den tredje tabellen som håller koll) eftersom du har definierat att de hör samman.

              Utan foreign key constraints riskerar du att ha redundanta rader i relationstabellen, men genom att sätta ihop de som en sträng blir det ännu svårare att garantera integriteten. Säg att du tar bort bil ID 1, och den ägs av person ID 99, så den har ägerBilarID = '3,4,5,1,12,13'. Du behöver då laborera med strängar (läsa in, söka efter index, slice, spara) varje gång du kör en DELETE-operation! Dyr operation!
              Johan Norberg, webbutvecklare.

              @GitHub

              Läs min blogg

              Kommentera


              • #8
                Du behöver då laborera med strängar (läsa in, söka efter index, slice, spara) varje gång du kör en DELETE-operation! Dyr operation!
                Jo, jag är fullt medveten om det! Det man vinner med "mindre tabeller" får man betala med mer och slirigare kod.

                Jag ville bara presentera modellen. I ett projekt kan modellen fungera. Det får man avgöra från fall till fall.

                En fördel är att man kan hålla sig till TVÅ tabeller. Om sen den fördelen är värd att ta tillvara får man beakta på eget håll.

                Precis som du skriver, det finns en lång rad nackdelar!
                Men jag tror inte det var nackdelar vi skulle fokusera på och fördjupa oss i!?

                Kommentera


                • #9
                  angelica skrev: Visa inlägg
                  Jo, jag är fullt medveten om det! Det man vinner med "mindre tabeller" får man betala med mer och slirigare kod.

                  Jag ville bara presentera modellen. I ett projekt kan modellen fungera. Det får man avgöra från fall till fall.

                  En fördel är att man kan hålla sig till TVÅ tabeller. Om sen den fördelen är värd att ta tillvara får man beakta på eget håll.

                  Precis som du skriver, det finns en lång rad nackdelar!
                  Men jag tror inte det var nackdelar vi skulle fokusera på och fördjupa oss i!?
                  angelica! Det var inte menat som kritik. Jag tyckte bara att det var kul att vi för en gångs skull fick igång en intressant diskussion på webForum, så det var mina tankar kring de olika lösningarna, för de som följer tråden och kanske är osäker på vilken väg de ska ta i sin egen applikation. Som alltid finns ju fördelar och nackdelar med alla lösningar och man får själv göra en avvägning.
                  Johan Norberg, webbutvecklare.

                  @GitHub

                  Läs min blogg

                  Kommentera


                  • #10
                    angelica skrev: Visa inlägg
                    Nu vet jag inte specifikt vad det är du arbetat med, men jag gjorde nyligen en lösning som går runt det du beskriver som ett problem.

                    Jag hade också två tabeller...

                    Jag använder bilarna som exempel: Principen är samma eller liknande:

                    [Bilar]l (ID, Regnr, Märke, Modell, Konstruktionsår)
                    [Person] (ID, Personnummer, Namn, Adress, Ålder... , ägerBilarID)

                    [Person]
                    ....
                    ägerBilarID = sträng = "1,45,56"

                    Denna variant vet jag inte hur väl den fungerar i större sammanhang, men i mindre sammanhang fungerar det. (Har gjort hittills i alla fall!)

                    Du slipper en tredje tabell som håller koll på de två andra, vem som äger olika bilar.

                    Jag är svag för ID nummer, måste medges! Primärt för man vet vad man har, så att säga...! Jag vet inte om denna varianten skulle passa för dig! Det vet du! :-)
                    Den där lösningen är faktiskt riktigt dålig och den borde du vänja dig av med.
                    Även om du tycker den funkat för dig.
                    Writing programs that get things done is good. You’ll never make it as a C# programmer if your programs don’t actually do something — unless, of
                    course, you’re a consultant.

                    Kommentera


                    • #11
                      Att lagra nyckelvärden i en sträng istället för som en tredje kopplingstabell har bara en (möjlig) fördel: Det är enkelt att hålla reda på för den person som designar och kanske speciellt om den personen inte är så van vid databaser.

                      Antalet nackdelar däremot är hur många som helst. Förutom det som nämns ovan, ger det även följande:
                      * Man har inte en relationsdatabas. (Det kan leda till långt mer trassel än du anar! )
                      * Det är verkligen inte bra för prestanda!
                      * Om man alls har behov av att hålla reda på hur två tabeller hör ihop är det troligt att de behöver JOINas ibland. Låt oss säga att du vill veta allt om de av Bo Eks bilar som är av märke Volvo:

                      sql:

                      -- 1) I en relationsdatabas ser JOINen ut så här:
                      SELECT B.*
                      FROM
                      Person P
                      INNER JOIN NuvarandeBilÄgare O ON
                      P.Personnummer = O.Personnummer
                      INNER JOIN Bil B ON
                      O.Regnr = B.Regnr
                      WHERE
                      P.Namn = 'Bo Ek' AND
                      B.Märke = 'Volvo'

                      -- 2) I din stränglösning får du något i stil med
                      SELECT
                      B.*
                      FROM
                      Bil B
                      INNER JOIN Person P ON
                      P.ÄgerBilarID LIKE '%,' + B.ID + ',%' OR -- en siffra inne i strängen
                      P.ÄgerBilarID LIKE B.ID + ',%' OR -- första siffran
                      P.ÄgerBilarID LIKE '%,' + B.ID -- sista siffran
                      WHERE
                      P.Namn = 'Bo Ek' AND
                      B.Märke = 'Volvo'

                      1) Är en snabb sökning, vilken databasen är byggd för att hantera och optimera.

                      2) Är inte bara långsam, tvingar dig till strängkonkatinering för varje rad och LIKE-sökning på det, till råga på allt måste du göra tre olika jämförelser för att kunna hitta alla siffror i strängen PER RAD i tabellen för att avgöra om den innehåller intressant data, och sen är den allt annat en felsäker!
                      Tänk om bil nr 12 är en Volvo och din ÄgerBilarID-sträng råkar se ut så här: '3,91,5,18, 12,13,7' Nu missas bil 12 helt, eftersom ett mellanslag smugit sig in i strängen och då matchas den inte ovan.

                      En databasdesign som inte klarar JOINer på ett bra sätt är aldrig bra, oavsett hur små tabellerna är!

                      Kommentera


                      • #12
                        Kul och intressant diskussion! Men idag när datavolym inte är några problem borde även en TS dvs Datum och tid vara aktuellt som ett värde för bilägandet!.
                        På det viset kan man följa ägarförloppet!
                        Livet är kort och Nu!
                        Läs mera!
                        !?

                        Kommentera


                        • #13
                          Lasp skrev: Visa inlägg
                          Kul och intressant diskussion! Men idag när datavolym inte är några problem borde även en TS dvs Datum och tid vara aktuellt som ett värde för bilägandet!.
                          På det viset kan man följa ägarförloppet!
                          Ja, naturligtvis, men jag ville bara ha ett snabbt och enkelt exempel utan att behöva förklara tankar med själva modellen.

                          Kommentera

                          Working...
                          X