Vnitřní spojení vyžaduje, aby každý řádek ve dvou spojených tabulkách měl shodné hodnoty sloupců a je běžně používanou operací spojení v aplikacích, ale neměl by být považován za nejlepší volbu ve všech situacích. Vnitřní spojení vytvoří novou tabulku výsledků kombinací hodnot sloupců dvou tabulek (A a B) na základě predikátu spojení. Dotaz porovnává každý řádek A s každým řádkem B, aby našel všechny páry řádků, které splňují predikát spojení. Když je spojovací predikát uspokojen porovnáním hodnot, které nemají hodnotu NULL, hodnoty sloupců pro každou shodnou dvojici řádků A a B se spojí do řádku výsledku.
Výsledek spojení lze definovat jako výsledek prvního převzetí kartézského součinu (nebo křížového spojení) všech řádků v tabulkách (kombinace každého řádku v tabulce A s každým řádkem v tabulce B) a následného vrácení všech řádků, které splňují predikát spojení. Skutečné implementace SQL obvykle používají jiné přístupy, například hašovací spojení nebo řazení-sloučení spojení, protože výpočet kartézského produktu je pomalejší a pro jeho uložení by často bylo zapotřebí neúměrně velké množství paměti.
SQL specifikuje dva různé syntaktické způsoby, jak vyjádřit spojení: „explicitní zápis spojení“ a „implicitní zápis spojení“. „Implicitní spojovací notace“ již není považována za osvědčený postup, přestože ji databázové systémy stále podporují.
„Explicitní spojovací notace“ používá klíčové slovo JOIN
, volitelně předchází klíčové slovo INNER
k určení tabulky, ke které se chcete připojit, a klíčové slovo ON
k zadání predikátů pro připojení, jako v následující příklad:
SELECT employee.LastName, employee.DepartmentID, department.DepartmentName FROM employee INNER JOIN department ONemployee.DepartmentID = department.DepartmentID;
Employee.LastName | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
Robinson | 34 | administrativní |
Jones | 33 | inženýrství |
Smith | 34 | administrativní |
Heisenberg | 33 | Inženýrství |
Rafferty | 31 | Prodej |
„Implicitní zápis spojení“ jednoduše uvádí t Tabulky pro připojení v klauzuli FROM
příkazu SELECT
oddělením čárkami. Určuje tedy křížové spojení a klauzule WHERE
může použít další predikáty filtru (které fungují srovnatelně s predikáty spojení v explicitní notaci).
Následující příklad je ekvivalentní předchozímu, ale tentokrát s použitím implicitní spojovací notace:
SELECT employee.LastName, employee.DepartmentID, department.DepartmentName FROM employee, departmentWHERE employee.DepartmentID = department.DepartmentID;
Dotazy uvedené v příkladech výše se připojí k tabulkám Zaměstnanec a Oddělení pomocí sloupce Oddělení ID obou tabulek. Pokud se DepartmentID těchto tabulek shoduje (tj. Predikát spojení je splněn), bude dotaz kombinovat sloupce LastName, DepartmentID a DepartmentName ze dvou tabulek do řádku výsledků. Pokud se ID oddělení neshoduje, nevygeneruje se žádný řádek s výsledky.
Výsledek provedení výše uvedeného dotazu tedy bude:
Employee.LastName | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
Robinson | 34 | administrativní |
Jones | 33 | Inženýrství |
Smith | 34 | Administrativní |
Heisenberg | 33 | Inženýrství |
Rafferty | 31 | Prodej |
Zaměstnanec „Williams“ a oddělení „Marketing“ se ve výsledcích provedení dotazu neobjeví. Ani jeden z nich nemá žádné odpovídající řádky v jiné příslušné tabulce: „Williams“ nemá žádné přidružené oddělení a žádný zaměstnanec nemá ID oddělení 35 („Marketing“). V závislosti na požadovaných výsledcích může být toto chování jemnou chybou, které lze zabránit nahrazením vnitřního spojení vnějším spojením.
Vnitřní spojení a NULL valuesEdit
Programátoři by měli zvláštní opatrnost při spojování tabulek ve sloupcích, které mohou obsahovat hodnoty NULL, protože NULL nikdy nebude odpovídat žádné jiné hodnotě (ani samotné NULL), pokud podmínka spojení výslovně nepoužívá predikát kombinace, který nejprve zkontroluje, zda jsou sloupce spojení NOT NULL
před použitím zbývajících predikátových podmínek. Vnitřní spojení lze bezpečně použít pouze v databázi, která vynucuje referenční integritu, nebo kde je zaručeno, že sloupce spojení nebudou NULL. Mnoho relačních databází zpracovávajících transakce spoléhá na standardy aktualizace dat Atomicity, Consistency, Isolation, Durability (ACID), aby byla zajištěna integrita dat, takže vnitřní spojení je vhodná volba. Transakční databáze však obvykle také mají žádoucí sloupce spojení, které mohou mít hodnotu NULL.Mnoho reportovacích relačních databází a datových skladů používá velkoobjemové dávkové aktualizace Extract, Transform, Load (ETL), které ztěžují nebo znemožňují vynucení referenční integrity, což má za následek potenciálně NULL spojení sloupců, které autor dotazu SQL nemůže upravit, a které způsobují vynechání vnitřních spojení data bez indikace chyby. Volba použití vnitřního spojení závisí na návrhu databáze a charakteristikách dat. Levé vnější spojení lze obvykle nahradit vnitřním spojením, když sloupce spojení v jedné tabulce mohou obsahovat hodnoty NULL.
Jakýkoli datový sloupec, který může být NULL (prázdný), by nikdy neměl být použit jako odkaz v vnitřní spojení, pokud není zamýšleným výsledkem vyloučení řádků s hodnotou NULL. Pokud mají být úmyslně odstraněny sloupce spojení NULL ze sady výsledků, může být vnitřní spojení rychlejší než vnější spojení, protože spojení tabulky a filtrování se provádí v jediném kroku. Naopak vnitřní spojení může mít za následek katastroficky pomalý výkon nebo dokonce selhání serveru, když se použije v dotazu na velký objem v kombinaci s databázovými funkcemi v klauzuli SQL Where. Funkce v klauzuli SQL Where může vést k tomu, že databáze ignoruje relativně kompaktní indexy tabulek. Databáze může číst a vnitřní spojení s vybranými sloupci z obou tabulek před snížením počtu řádků pomocí filtru, který závisí na vypočítané hodnotě, což vede k relativně enormnímu množství neefektivního zpracování.
Když je výsledková sada je produkováno spojením několika tabulek, včetně hlavních tabulek používaných k vyhledání úplných textových popisů číselných identifikačních kódů (vyhledávací tabulka), hodnota NULL v kterémkoli z cizích klíčů může mít za následek vyloučení celého řádku ze sady výsledků, bez indikace chyby. Složitý dotaz SQL, který zahrnuje jedno nebo více vnitřních spojení a několik vnějších spojení, má stejné riziko pro hodnoty NULL ve sloupcích odkazů na vnitřní spojení.
Závazek k kódu SQL obsahujícímu vnitřní spojení předpokládá, že sloupce spojení NULL nebudou budou zavedeny budoucími změnami, včetně aktualizací dodavatelů, změn designu a hromadného zpracování mimo pravidla pro ověřování dat aplikace, jako jsou převody dat, migrace, hromadné importy a slučování.
Vnitřní spojení lze dále klasifikovat jako equi-joins, jako přirozené spojení nebo jako cross-joins.
Equi-joinEdit
Equi-join je specifický typ spojení založeného na komparátoru, který používá pouze srovnání rovnosti v join-predicate. Použití jiných srovnávacích operátorů (například <
) diskvalifikuje join jako equi-join. Výše uvedený dotaz již poskytl příklad equi-join:
SELECT *FROM employee JOIN department ON employee.DepartmentID = department.DepartmentID;
Můžeme napsat equi-join, jak je uvedeno níže,
SELECT *FROM employee, departmentWHERE employee.DepartmentID = department.DepartmentID;
Pokud spol lumns in an equi-join have the same name, SQL-92 provides an optional shorthand notation for expressing equi-joins, by by the USING
construct:
SELECT *FROM employee INNER JOIN department USING (DepartmentID);
Konstrukce USING
je však více než pouhý syntaktický cukr, protože výsledná sada se od výsledku liší sada verze s výslovným predikátem. Konkrétně všechny sloupce uvedené v USING
seznamu se zobrazí pouze jednou s nekvalifikovaným názvem, nikoli jednou pro každou tabulku ve spojení. Ve výše uvedeném případě bude existovat jeden DepartmentID
sloupec a žádný employee.DepartmentID
nebo department.DepartmentID
.
Klauzule USING
není podporována MS SQL Serverem a Sybase.
Natural joinEdit
The natural join je speciální případ equi-join. Přirozené spojení (⋈) je binární operátor, který je zapsán jako (R ⋈ S), kde R a S jsou vztahy. Výsledkem přirozeného spojení je sada všech kombinací n-tic v R a S, které jsou stejné na jejich společných názvech atributů.Zvažte například tabulky Zaměstnanec a oddělení a jejich přirozené spojení:
|
|
|
To lze také použít k definování složení vztahů. Například složení Employee and Dept is their join as shown above, projected on all but the common attribute DeptName. V teorii kategorií je spojení přesně produktem vlákna.
Přirozené spojení je pravděpodobně jedním z nejdůležitějších operátorů, protože je relačním protějškem logického AND. Všimněte si, že pokud se stejná proměnná objeví v každém ze dvou predikátů, které jsou spojeny AND, pak tato proměnná znamená stejnou věc a obě podoby musí být vždy nahrazeny stejnou hodnotou. Přirozené spojení zejména umožňuje kombinaci vztahů, které jsou přidruženy cizím klíčem. Například ve výše uvedeném příkladu cizí klíč pravděpodobně drží od Employee.DeptName k Dept.DeptName a poté přirozené spojení Employee a Dept kombinuje všechny zaměstnance s jejich odděleními. Funguje to, protože cizí klíč drží mezi atributy se stejným názvem. Pokud tomu tak není, například v cizím klíči z Dept.manager do Employee.Name, je třeba tyto sloupce před přejímáním přirozeného spojení přejmenovat. Takové spojení se někdy označuje také jako rovnocenné spojení.
Více formálně je sémantika přirozeného spojení definována takto:
R ⋈ S = {t ∪ s ∣ t ∈ R ∧ s ∈ S ∧ F un (t ∪ s)} {\ displaystyle R \ motýlek S = \ left \ {t \ cup s \ mid t \ in R \ \ land \ s \ in S \ \ land \ {\ mathit {Fun}} (t \ cup s) \ right \}},
kde Fun je predikát, který platí pro relaci r právě tehdy, když r je funkce. Obvykle se vyžaduje, aby R a S musely mít alespoň jeden společný atribut, ale pokud je toto omezení vynecháno a R a S nemají žádné společné atributy, pak se přirozené spojení stane přesně kartézským součinem.
The přirozené spojení lze simulovat pomocí Coddových primitiv následovně. Nechť c1,…, cm jsou názvy atributů společné pro R a S, r1,…, rn jsou názvy atributů jedinečné pro R a nechme s1,…, sk být atributy jedinečné pro S. Dále předpokládejme, že názvy atributů x1,…, xm nejsou ani v R, ani v S. V prvním kroku lze nyní přejmenovat názvy běžných atributů v S:
T = ρ x 1 / c 1,…, xm / cm (S) = ρ x 1 / c 1 (ρ x 2 / c 2 (… ρ xm / cm (S) …)) {\ displaystyle T = \ rho _ {x_ {1} / c_ {1}, \ ldots, x_ {m} / c_ {m}} (S) = \ rho _ {x_ {1} / c_ {1}} (\ rho _ {x_ {2} / c_ {2 }} (\ ldots \ rho _ {x_ {m} / c_ {m}} (S) \ ldots))}
Pak vezmeme kartézský součin a vybereme n-tice, které se mají spojit:
U = π r 1,…, rn, c 1,…, cm, s 1,…, sk (P) {\ displaystyle U = \ pi _ {r_ {1}, \ ldots, r_ {n}, c_ {1}, \ ldots, c_ {m}, s_ {1}, \ ldots, s_ {k}} (P)}
Přirozené spojení je typ ekv join, kde predikát join vzniká implicitně porovnáním všech sloupců v obou tabulkách, které mají v spojených tabulkách stejné názvy sloupců. Výsledná připojená tabulka obsahuje pouze jeden sloupec pro každou dvojici stejně pojmenovaných sloupců. V případě, že nebudou nalezeny žádné sloupce se stejnými názvy, bude výsledkem křížové spojení.
Většina odborníků souhlasí s tím, že PŘÍRODNÍ PŘIPOJENÍ jsou nebezpečná, a proto důrazně nedoporučují jejich použití. Nebezpečí pochází z neúmyslného přidání nového sloupce, který je pojmenován stejně jako jiný sloupec v druhé tabulce. Existující přirozené spojení by pak mohlo „přirozeně“ použít nový sloupec pro srovnání a porovnávat / porovnávat pomocí jiných kritérií (z jiných sloupců) než dříve. Existující dotaz by tedy mohl přinést různé výsledky, přestože data v tabulkách nebyla změněna, ale pouze rozšířena.Použití názvů sloupců k automatickému určování odkazů na tabulky není volbou ve velkých databázích se stovkami nebo tisíci tabulek, kde by to na konvence pojmenování znamenalo nerealistické omezení. Databáze reálného světa jsou běžně navrženy s údaji o cizím klíči, která není důsledně naplněna (jsou povoleny hodnoty NULL), kvůli obchodním pravidlům a kontextu. Je běžnou praxí upravit názvy sloupců podobných dat v různých tabulkách a tento nedostatek rigidní konzistence odsouvá přirozená spojení k teoretickému konceptu pro diskusi.
Výše uvedený ukázkový dotaz pro vnitřní spojení lze vyjádřit jako přirozený připojte se následujícím způsobem:
SELECT *FROM employee NATURAL JOIN department;
Stejně jako u explicitní klauzule USING
, v připojené tabulce se vyskytuje pouze jeden sloupec DepartmentID bez kvalifikace:
DepartmentID | Employee.LastName | Department.DepartmentName |
---|---|---|
34 | Smith | administrativní pracovník |
33 | Jones | inženýrství |
34 | Robinson | administrativní |
33 | Heisenberg | inženýrství |
31 | Rafferty | Prodej |
PostgreSQL, MySQL a Oracle su podporovat přirozené spojení; Microsoft T-SQL a IBM DB2 nikoli. Sloupce použité ve spojení jsou implicitní, takže kód spojení neukazuje, které sloupce se očekávají, a změna názvů sloupců může změnit výsledky. Ve standardu SQL: 2011 jsou přirozená spojení součástí volitelného balíčku F401 „Rozšířená připojená tabulka“.
V mnoha databázových prostředích jsou názvy sloupců řízeny externím dodavatelem, nikoli vývojářem dotazů. Přirozené spojení předpokládá stabilitu a konzistenci v názvech sloupců, které se mohou měnit během upgradů verzí nařízených dodavatelem.