sql >> Databáze >  >> RDS >> Mysql

SQL:Vytvoření relační tabulky se 2 různými auto_increment

Koncepty

Neporozuměli jste některým základním pojmům az toho plynou potíže. Nejprve se musíme zabývat koncepty, nikoli problémem, jak jej vnímáte vy, a následně váš problém zmizí.

automaticky inkrementovaná ID, což jsou samozřejmě primární klíče.

Ne nejsou. To je běžná mylná představa. A problémy se zaručeně vyskytnou.

ID pole nemůže být primární klíč v anglickém, technickém nebo relačním smyslu.

  • Jistě, v SQL můžete deklarovat jakýkoli jako PRIMARY KEY , ale to jej magicky nepřemění na primární klíč v anglickém, technickém nebo relačním smyslu. Čivavu můžete pojmenovat „Rottweiller“, ale tím se nemění na rotvajlera, zůstává čivavou. Jako každý jazyk SQL jednoduše provádí příkazy, které mu zadáte, nerozumí PRIMARY KEY aby to znamenalo něco relačního, prostě to udeří do sloupce (nebo pole) jedinečný index.

  • Problém je v tom, že jste deklarovali ID být PRIMARY KEY , myslíte jako primární klíč a můžete očekávat že má některé vlastnosti primárního klíče. Kromě jedinečnosti hodnoty ID , nepřináší žádnou výhodu. Nemá žádnou z kvalit primárního klíče nebo jakéhokoli relačního klíče. Není to klíč v anglickém, technickém nebo relačním smyslu. Prohlášením neklíče za klíč se pouze zmate a že je něco strašně špatně, zjistíte, až když si uživatel bude stěžovat na duplicity v tabulce.

Relační tabulky musí mít řádek jedinečnost

PRIMARY KEY na ID pole neposkytuje řádek jedinečnost. Není to tedy relační tabulka obsahující řádky, a pokud tomu tak není, pak je to soubor obsahující záznamy. Nemá žádnou integritu ani sílu (v této fázi si budete vědomi pouze síly spojení) nebo rychlost, kterou má tabulka v relační databázi.

Spusťte tento kód (MS SQL 2008) a dokažte to sami. Prosím, nečtěte toto a pochopte to, a pak pokračujte ve čtení zbytku této odpovědi, tento kód je nutné provést před dalším čtením . Má léčivou hodnotu.

    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

Všimněte si, že máte duplicitní řádky . Relační tabulky musí mít jedinečné řádky . Další důkaz toho, že nemáte relační tabulku ani žádnou z jejích vlastností.

Všimněte si, že jediná věc, která je v přehledu jedinečná, je ID pole, které žádného uživatele nezajímá, žádný uživatel nevidí, protože to nejsou data, je to nějaký další nesmysl, který vám nějaký velmi hloupý "učitel" řekl, abyste dali do každého souboru. Máte záznam jedinečnost, ale ne řádek jedinečnost.

Pokud jde o data (skutečná data minus nadbytečné přírůstky), data name_last a name_first může existovat bez ID pole. Osoba má křestní jméno a příjmení, aniž by na jejím čele bylo vyraženo ID.

Druhá věc, kterou používáte a která vás mate, je AUTOINCREMENT. Pokud implementujete systém evidence záznamů bez schopnosti Relational, jistě je užitečné, nemusíte při vkládání záznamů kódovat přírůstek. Ale pokud implementujete relační databázi, neslouží vůbec žádnému účelu, protože ji nikdy nepoužijete. V SQL je mnoho funkcí, které většina lidí nikdy nepoužívá.

Nápravné opatření

Jak tedy upgradujete, povýšíte tento dumb_file, který je plný duplicitních řádků, na relační tabulku, abyste získali některé z kvalit a výhod relační tabulky? K tomu existují tři kroky.

  1. Musíte rozumět Keys

    • A protože jsme pokročili od souborů ISAM ze 70. let 20. století, k relačnímu modelu , musíte porozumět Relačním klíčům . To znamená, pokud chcete získat výhody (integrita, výkon, rychlost) relační databáze.

    Dr E F Cood ve svém RM , prohlásil, že:

    klíč se skládá z dat

    a

    Řádky v tabulce musí být jedinečné

    Váš „klíč“ není složen z dat. Je to nějaký další parazit, který není datový, způsobený tím, že jste se nakazili nemocí svého "učitele". Uvědomte si to jako takové a dovolte si plnou mentální kapacitu, kterou vám Bůh dal (všimněte si, že vás nežádám, abyste přemýšleli izolovaně, fragmentovaně nebo abstraktně, všechny prvky v databázi musí být vzájemně integrovány). Vytvořte skutečný klíč z dat a pouze z dat. V tomto případě existuje pouze jeden možný klíč:(name_last, name_first).

  2. Vyzkoušejte tento kód , prohlásit jedinečné omezení dat:

         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
    

    Nyní máme jedinečnost řádku . To je sekvence, která se stane většině lidí:vytvoří soubor, který umožňuje podvody; nemají ponětí, proč se v rozbalovacích seznamech objevují podvodníci; uživatel křičí; vyladí soubor a přidají index, aby se zabránilo podvodům; přejdou na další opravu chyby. (Mohou to udělat správně nebo ne, to je jiný příběh.)

  3. Druhá úroveň. Pro myslící lidi, kteří přemýšlejí nad rámec oprav. Protože nyní máme jedinečnost řádku, to, co ve jménu nebes je účelem ID pole, proč ho vůbec máme??? Ach, protože čivava se jmenuje Rotty a my se jí bojíme dotknout.

    Prohlášení, že se jedná o PRIMARY KEY je nepravdivé, ale zůstává, což způsobuje zmatek a falešná očekávání. Jediný pravý klíč, který existuje, je (name_last, name_fist), a je to Alternativní klíč v tomto bodě.

    Proto ID pole je zcela nadbytečné; a stejně tak index, který to podporuje; a stejně tak stupidní AUTOINCREMENT; a stejně tak nepravdivé prohlášení, že se jedná o PRIMARY KEY; a všechna očekávání, která od toho můžete mít, jsou falešná.

    Odstraňte proto nadbytečné ID pole. Vyzkoušejte tento kód :

        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
    

    Funguje dobře, funguje tak, jak bylo zamýšleno, bez cizích polí a indexů.

    Pamatujte si to prosím a udělejte to pokaždé správně.

Falešní učitelé

V těchto konečných časech, jak bylo avizováno, jich budeme mít mnoho. Dobře si všimněte "učitelů", kteří šíří ID sloupce, na základě podrobných důkazů v tomto příspěvku, jednoduše nerozumí relačnímu modelu nebo relační databáze. Zejména ti, kteří o tom píší knihy.

Jak je dokázáno, uvízly v technologii ISAM před rokem 1970. To je vše, čemu rozumí, a to je vše, co mohou učit. Používají kontejner databáze SQL pro snadný přístup, obnovu, zálohování atd., ale obsah je čistý systém evidence záznamů bez relační integrity, výkonu nebo rychlosti. AFAIC, je to vážný podvod.

Kromě ID Samozřejmě existuje několik položek, které jsou klíčovými koncepty Relational-or-not, které dohromady vedou k tomu, že jsem vytvořil tak vážný závěr. Tyto další položky jsou nad rámec tohoto příspěvku.

Jedna konkrétní dvojice idiotů právě provádí útok na First Normal Form. Patří do azylového domu.

Odpověď

Nyní ke zbytku vaší otázky.

Existuje způsob, jak mohu vytvořit relační tabulku bez ztráty funkcí automatického přírůstku?

To je sebeprotichůdná věta. Věřím, že z mého vysvětlení pochopíte, že relační tabulky nepotřebují pro AUTOINCREMENT "funkce"; pokud má soubor AUTOINCREMENT , není to relační tabulka.

AUTOINCREMENT je dobré pouze pro jednu věc:pokud a pouze tehdy, chcete-li vytvořit excelovou tabulku v kontejneru databáze SQL, doplněnou o pole s názvem A, B, a C, přes horní část a zaznamenejte čísla dolů na levé straně. Z hlediska databáze je to výsledek SELECT, zploštělý pohled na data, což není zdroj dat, která jsou organizována (normalizována).

Dalším možným (ale neupřednostňovaným) řešením může být, že v první tabulce je další primární klíč, což je uživatelské jméno uživatele, samozřejmě ne s automatickým přírůstkem. Je to nevyhnutelné?

V technické práci se nestaráme o preference, protože to je subjektivní a neustále se to mění. Záleží nám na technické správnosti, protože ta je objektivní a ta se nemění.

Ano, je to nevyhnutelné. Protože je to jen otázka času; počet chyb; počet "nemůže udělat"; počet uživatelských výkřiků, dokud nebudete čelit faktům, nepřekonáte svá nepravdivá prohlášení a neuvědomíte si, že:

  • jediný způsob, jak zajistit, aby uživatel řádkoval jsou jedinečné, že uživatelská jména jsou jedinečná, je deklarovat UNIQUE omezení

  • a zbavit se user_id nebo id v uživatelském souboru

  • který propaguje user_name na PRIMARY KEY

Ano, protože celý váš problém s třetí tabulkou, nikoli náhodou, je poté odstraněn.

Tato třetí tabulka je Asociativní tabulka . Jediný požadovaný klíč (primární klíč) je složený ze dvou nadřazených primárních klíčů. To zajišťuje jedinečnost řádků , které jsou identifikovány svými klíči, nikoli svými IDs.

Varuji vás před tím, protože stejní "učitelé", kteří vás naučili chybu při implementaci ID polí, naučte chybu implementace ID pole v asociativní tabulce, kde je stejně jako u běžné tabulky nadbytečná, neplní žádný účel, zavádí duplikáty a způsobuje zmatek. A je to dvojnásob nadbytečné, protože dva klíče, které to poskytují, už tam jsou a hledí nám do tváře.

Protože nerozumí RM , nebo relační termíny, nazývají asociativní tabulky "odkazové" nebo "mapové" tabulky. Pokud mají ID pole, jsou to ve skutečnosti soubory.

Vyhledávací tabulky

ID pole jsou zvláště hloupá věc pro vyhledávací nebo referenční tabulky. Většina z nich má rozpoznatelné kódy, není třeba v nich vyjmenovávat seznam kódů, protože kódy jsou (měly by být) jedinečné.

Navíc mít kódy v podřízených tabulkách jako FK je dobrá věc:kód je mnohem smysluplnější a často ušetří zbytečné spojení:

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

místo:

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

nebo hůř:

    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

Všimněte si, že tomu se nelze vyhnout:potřebujete jedinečnost vyhledávacího kódu a jedinečnost v popisu. To je jediný způsob, jak zabránit duplicitám v každém ze dvou sloupců:

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

        CONSTRAINT PK 
            PRIMARY KEY ( gender_code )

        CONSTRAINT AK 
            UNIQUE ( name )
        )

Úplný příklad

Z podrobností ve vaší otázce mám podezření, že máte problémy se syntaxí SQL a definicí FK, takže jako příklad uvedu celé řešení, které potřebujete (protože jste neuvedli definice souborů):

    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 )
        )

Zde je PRIMARY KEY prohlášení je čestné, je to primární klíč; žádné ID; žádné AUTOINCREMENT; žádné další indexy; žádné duplicitní řádky; žádná mylná očekávání; žádné následné problémy.

Datový model

Zde je datový model k definicím.

  • Ukázkový uživatelský sportovní datový model

  • Pokud nejste zvyklí na notaci, mějte na paměti, že každé malé zaškrtnutí, zářez a značka, plná vs přerušovaná čára, čtverec vs kulaté rohy, znamená něco velmi specifického. Viz Zápis IDEF1X .

  • Obrázek vydá za tisíc slov; v tomto případě má standardní reklamační obrázek větší hodnotu; špatný nestojí za papír, na kterém je nakreslený.

  • Pečlivě zkontrolujte slovesné fráze, které tvoří sadu predikátů. Zbytek predikátů lze určit přímo z modelu. Pokud to není jasné, zeptejte se.




  1. přesun dat z jedné tabulky do druhé, edice postgresql

  2. Přehled logické replikace v PostgreSQL

  3. Jak vygenerovat pole automatického přírůstku ve výběrovém dotazu

  4. S tímto dotazem implementujte funkci stránkování (přeskočit / vzít).