Poddotazy (SQL Server)

  • 18. 2. 2018
  • 21 minut ke čtení
    • W
    • M
    • T
    • M
    • j
    • +3

Platí pro: SQL Server (všechny podporované verze) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Parallel Data Warehouse

Poddotaz je dotaz, který je vnořen do SELECT, INSERT, UPDATE nebo DELETE nebo v jiném poddotazu. Poddotaz lze použít kdekoli, kde je povolen výraz. V tomto příkladu se poddotaz používá jako výraz sloupce s názvem MaxUnitPrice v příkazu SELECT.

Subquery Fundamentals

Poddotaz je také nazývá se vnitřní dotaz nebo vnitřní výběr, zatímco příkaz obsahující poddotaz se také nazývá vnější dotaz nebo vnější výběr.

Mnoho příkazů Transact-SQL, které obsahují poddotazy, lze alternativně formulovat jako spojení. Další otázky lze položit pouze u poddotazů. V Transact-SQL obvykle neexistuje žádný rozdíl ve výkonu mezi příkazem, který obsahuje poddotaz, a sémanticky ekvivalentní verzí, která ho neobsahuje. V některých případech, kdy je nutné zkontrolovat existenci, však spojení přináší lepší výkon. Jinak musí být vnořený dotaz zpracován pro každý výsledek vnějšího dotazu, aby byla zajištěna eliminace duplikátů. V takových případech by přístup spojením přinesl lepší výsledky. Následuje příklad ukazující jak poddotaz SELECT, tak i spojení SELECT, které vrací stejnou sadu výsledků:

Poddotaz vnořený do vnějšího příkazu SELECT má následující komponenty:

  • Běžný SELECT dotaz včetně běžných komponent seznamu select.
  • Pravidelná klauzule FROM obsahující jeden nebo více názvů tabulek nebo zobrazení.
  • Volitelná WHERE klauzule.
  • volitelná GROUP BY klauzule.
  • volitelná HAVING klauzule.

Dotaz SELECT poddotazu je vždy uzavřen v závorkách. Nemůže obsahovat klauzuli COMPUTE nebo FOR BROWSE a klauzuli ORDER BY může obsahovat pouze tehdy, když je také uvedena klauzule TOP.

Poddotaz lze vnořit do klauzule WHERE nebo HAVING vnější SELECT, INSERT, UPDATE nebo DELETE nebo uvnitř jiného poddotazu. Je možné až 32 úrovní vnoření, i když se limit liší v závislosti na dostupné paměti a složitosti dalších výrazů v dotazu. Jednotlivé dotazy nemusí podporovat vnoření až do 32 úrovní. Poddotaz se může objevit kdekoli, kde lze použít výraz, pokud vrací jednu hodnotu.

Pokud se tabulka zobrazí pouze v poddotazu a ne ve vnějším dotazu, nelze sloupce z této tabulky zahrnout do výstup (seznam pro výběr vnějšího dotazu).

Příkazy, které obsahují poddotaz, mají obvykle jeden z těchto formátů:

  • WHERE výraz IN (poddotaz)
  • WHERE expression comparison_operator (subquery)
  • WHERE EXISTS (subquery)

V některých příkazech Transact-SQL lze poddotaz vyhodnotit, jako by to byl nezávislý dotaz. Koncepčně jsou výsledky poddotazů nahrazeny do vnějšího dotazu (i když to nemusí být nutně způsob, jakým SQL Server ve skutečnosti zpracovává příkazy Transact-SQL s poddotazy).

Existují tři základní typy poddotazů. Ti, kteří:

  • pracují na seznamech zavedených pomocí IN, nebo těch, které srovnávací operátor upravil pomocí ANY nebo ALL.
  • Jsou zavedeny s nemodifikovaným srovnávacím operátorem a musí vrátit jedinou hodnotu.
  • Jsou zavedeny testy existence s EXISTS.

Pravidla poddotazů

Na poddotaz se vztahují následující omezení:

  • Seznam výběru poddotazu zavedeného operátorem porovnání může obsahovat pouze jeden výraz nebo název sloupce (kromě toho, že EXISTS a IN fungují na SELECT * nebo seznam).
  • Pokud klauzule WHERE vnějšího dotazu obsahuje název sloupce, je musí být kompatibilní se sloupcem v seznamu výběru poddotazů.
  • Ve vybraném seznamu poddotazů nelze použít datové typy ntext, text a obrázky.
  • Protože musí vracet jednu hodnotu, poddotazy zavedené nemodifikovaným srovnávacím operátorem (jedním nenásledované klíčovým slovem ANY nebo ALL) nemůže obsahovat klauzule GROUP BY a HAVING.
  • nelze použít u poddotazů, které zahrnují GROUP BY.
  • COMPUTE a INTO nelze specifikovat.
  • ORDER BY lze zadat pouze v případě, že je zadána také TOP.
  • Pohled vytvořený pomocí poddotazu nelze aktualizovat.
  • Seznam výběrů poddotazů zavedených pomocí EXISTS podle konvence má hvězdičku ( *) místo názvu jednoho sloupce. Pravidla pro poddotaz zavedený pomocí EXISTS jsou stejná jako pravidla pro standardní výběrový seznam, protože poddotaz zavedený pomocí EXISTS vytváří existenci otestovat a místo dat vrátit TRUE nebo FALSE.

Kvalifikace názvů sloupců v poddotazech

V následujícím příkladu je sloupec BusinessEntityID ve WHERE klauzule vnějšího dotazu je implicitně kvalifikována názvem tabulky v klauzuli vnějšího dotazu FROM (Sales.Store). Odkaz na CustomerID ve vybraném seznamu poddotazu je kvalifikován klauzulí FROM, tj. Tabulkou Sales.Customer.

Obecným pravidlem je, že názvy sloupců v příkazu jsou implicitně kvalifikovány tabulkou, na kterou odkazuje klauzule FROM na stejné úrovni. Pokud sloupec v tabulce uvedené v klauzuli FROM poddotazu neexistuje, je implicitně kvalifikován tabulkou, na kterou odkazuje FROM klauzule vnějšího dotazu.

Takto vypadá dotaz se zadanými implicitními předpoklady:

Nikdy se nemýlí explicitně uvést název tabulky a vždy je možné přepsat implicitní předpoklady týkající se názvů tabulek s výslovnou kvalifikací.

Důležité

Pokud je na sloupec odkazován v poddotazu, neexistuje v tabulce, na kterou odkazuje klauzule poddotazu „s FROM, ale existuje v tabulce, na kterou odkazuje vnější dotaz“ s FROM klauzule, dotaz se provede bez chyby. SQL Server implicitně kvalifikuje sloupec v poddotazu s názvem tabulky ve vnějším dotazu.

Více úrovní vnoření

Poddotaz může sám obsahovat jeden nebo více poddotazů. Ve výpisu lze vnořit libovolný počet poddotazů.

Následující dotaz vyhledá jména zaměstnanců, kteří jsou zároveň prodejci.

Zde je sada výsledků.

Nejvnitřnější dotaz vrací ID prodejců. Dotaz na další vyšší úrovni je vyhodnocen pomocí těchto ID prodejních osob a vrací kontaktní ID čísla zaměstnanců. Konečně vnější dotaz používá ID kontaktů k vyhledání jmen zaměstnanců.

Tento dotaz můžete také vyjádřit jako spojení:

Mnoho dotazů lze vyhodnotit jednorázovým provedením poddotazu a dosazením výsledné hodnoty nebo hodnot do klauzule WHERE vnějšího dotazu. V dotazech, které obsahují korelovaný poddotaz (také známý jako opakující se poddotaz), poddotaz závisí na vnějším dotazu na jeho hodnoty. To znamená, že poddotaz je prováděn opakovaně, jednou pro každý řádek, který může být vybrán vnějším dotazem. Tento dotaz načte jednu instanci každého křestního jména a příjmení každého zaměstnance, pro které je bonus v tabulce SalesPerson 5000 a pro který identifikační čísla zaměstnanců se v tabulkách Zaměstnanec a Prodejce shodují.

Zde je sada výsledků.

Předchozí poddotaz v tomto příkazu nelze vyhodnotit nezávisle na vnějším dotazu. Potřebuje hodnotu pro Employee.BusinessEntityID, ale tato hodnota se mění, když SQL Server zkoumá různé řádky v Employee.
Přesně takhle dotaz je vyhodnocen: SQL Server považuje každý řádek tabulky zaměstnanců za zahrnutí do výsledků nahrazením hodnoty v každém řádku do vnitřního dotazu. Například pokud SQL Server nejprve prozkoumá řádek pro Syed Abbas, proměnná Employee.BusinessEntityID má hodnotu 285, kterou nahrazuje SQL Server utes do vnitřního dotazu.

Výsledek je 0 (Syed Abbas nedostal bonus, protože je nikoli prodejce), takže vnější dotaz bude vyhodnocen jako:

Protože je to nepravda, řádek pro Syed Abbas není zahrnut ve výsledcích.

Write a Comment

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *