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ýtPRIMARY 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.
-
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).
-
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.)
-
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á oPRIMARY 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
neboid
v uživatelském souboru -
který propaguje
user_name
naPRIMARY 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.
-
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.