NEJVÝHODNĚJŠÍ AKCE ROKU: 90 % extra kreditů ZDARMA s promokódem STROMECEK90. Zjisti více:
NOVINKA: Staň se datovým analytikem od 0 Kč a získej jistotu práce, lepší plat a nové kariérní možnosti. Více informací:

Lekce 6 - MS-SQL krok za krokem: Výběr dat (vyhledávání)

V předešlém cvičení, Řešené úlohy k 1.-5. lekci MS-SQL, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

Dnes se v MS-SQL tutoriálu zaměříme na tu nejhezčí část a tou je výběr dat. Jedná se o dotazování na data, jestli chcete, tak vyhledávání v tabulce.

Výběr dat je klíčovou funkcí databází, umožňuje nám totiž pomocí relativně jednoduchých dotazů dělat i složité výběry dat. Od prostého výběru uživatele podle jeho Id (například pro zobrazení detailů v aplikaci) můžeme vyhledávat uživatele splňující určité vlastnosti, výsledky řadit dle různých kritérií nebo dokonce do dotazu zapojit více tabulek, různé funkce a skládat dotazy do sebe (o tom až v dalších lekcích).

Testovací data

Vrátíme se opět k naší jednoduché databázi s tabulkou Uzivatele. Před zkoušením dotazů je vždy dobré mít k dispozici nějaká testovací data, abychom měli s čím pracovat a neměli tam jen čtyři uživatele. Pojďme si tedy do naší tabulky Uzivatele vložit nějaké záznamy. Něco jsem pro nás připravil.

Tabulku si nejprve vyprázdníme, abychom měli stejná data a stejné výsledky. Otevřeme si proto okno pro vykonání T-SQL skriptu – v okně SQL Server Object Explorer klikneme na databázi pravým tlačítkem a vybereme New Query...:

New Query… - MS-SQL databáze krok za krokem

Následně na naší tabulce Uzivatele spustíme příkaz TRUNCATE TABLE:

TRUNCATE TABLE [Uzivatele];

A nakonec spustíme následující příkaz pro vložení nových záznamů:

INSERT INTO [Uzivatele] (
    [Jmeno],
    [Prijmeni],
    [DatumNarozeni],
    [PocetClanku]
)
VALUES
('Jan',  'Novák',  '1984-11-03', 17),
('Tomáš', 'Marný', '1942-10-17', 12),
('Josef', 'Nový', '1958-7-10', 5),
('Alfons', 'Svoboda', '1935-5-15', 6),
('Ludmila', 'Dvořáková', '1967-4-17', 2),
('Petr', 'Černý', '1995-2-20', 1),
('Vladimír', 'Pokorný', '1984-4-18', 1),
('Ondřej', 'Bohatý', '1973-5-14', 3),
('Vítězslav', 'Churý', '1969-6-2', 7),
('Pavel', 'Procházka', '1962-7-3', 8),
('Matěj', 'Horák', '1974-9-10', 0),
('Jana', 'Veselá', '1976-10-2', 1),
('Miroslav', 'Kučera', '1948-11-3', 1),
('František', 'Veselý', '1947-5-9', 1),
('Michal', 'Krejčí', '1956-3-7', 0),
('Lenka', 'Němcová', '1954-2-11', 5),
('Věra', 'Marková', '1978-1-21', 3),
('Eva', 'Kučerová', '1949-7-26', 12),
('Lucie', 'Novotná', '1973-7-28', 4),
('Jaroslav', 'Novotný', '1980-8-11', 8),
('Petr', 'Dvořák', '1982-9-30', 18),
('Jiří', 'Veselý', '1961-1-15', 2),
('Martina', 'Krejčí', '1950-8-29', 4),
('Marie', 'Černá', '1974-2-26', 5),
('Věra', 'Svobodová', '1983-3-2', 2),
('Pavel', 'Dušín', '1991-5-1', 9),
('Otakar', 'Kovář', '1992-12-17', 9),
('Kateřina', 'Koubová', '1956-11-15', 4),
('Václav', 'Blažek', '1953-10-20', 6),
('Jan', 'Spáčil', '1967-5-6', 3),
('Zdeněk', 'Malačka', '1946-3-10', 6);

V databázi máme 31 uživatelů. To by mělo stačit k tomu, abychom si na nich vyzkoušeli základy dotazování.

Dotazování

Dotaz na záznamy, tedy jejich vyhledání/výběr, jsme již vlastně viděli, když jsme záznamy poprvé přidávali. Pro rekapitulaci zobrazíme všechny záznamy kliknutím pravým tlačítkem na tabulku v SQL Server Object Explorer a vybráním View Data:

View Data - MS-SQL databáze krok za krokem

Návrhář Visual Studia byl pro nás zpočátku takovou berličkou, ale nyní pro nás již přestává být zajímavý. Narážíme totiž na jeho hranice, jediné, co zde můžeme nastavit, je počet řádků. Do políčka Max Rows zadejme například hodnotu 10 a potvrďme:

Max Rows - MS-SQL databáze krok za krokem

Na databázi se zavolá dotaz, který vybere pouze 10 prvních položek. To se hodí pokud je databáze rozsáhlá, aby se neposílalo úplně všechno. Pokud chceme opravdu všechna data (a nevíme kolik jich je), tak z nabídky zvolíme speciální hodnotu All.

Visual Studio nezobrazuje ve výsledcích veškerou diakritiku, což je normální a nemá to na data žádný vliv.

Příkaz SELECT

Na pozadí Visual Studio posílá do databáze samozřejmě T-SQL dotaz, který může vypadat následovně:

SELECT TOP 10 * FROM [Uzivatele];

Dotaz je asi docela srozumitelný. Používáme zde příkaz SELECT, který slouží k výběru záznamů z tabulky. TOP 10 říká, že chceme 10 řádků od vrchu (prvních 10) a ta hvězdička označuje, že chceme vybrat všechny sloupce. Dotaz tedy česky zní: "Vyber prvních 10 řádků a všechny sloupce z tabulky Uzivatele".

Pokud si daný dotaz zavoláme na naší databázi, uvidíme stejnou tabulku jako při použití funkce View Data a Max Rows:

Id Jmeno Prijmeni DatumNarozeni PocetClanku
1 Jan Novák 1984-11-03 17
2 Tomáš Marný 1942-10-17 12
3 Josef Nový 1958-07-10 5
4 Alfons Svoboda 1935-05-15 6
5 Ludmila Dvoráková 1967-04-17 2
6 Petr Cerný 1995-02-20 1
7 Vladimír Pokorný 1984-04-18 1
8 Ondrej Bohatý 1973-05-14 3
9 Vítezslav Churý 1969-06-02 7
10 Pavel Procházka 1962-07-03 8

Klauzule WHERE

Dost často potřebujeme získat data na základě určitých kritérií. Například budeme hledat pouze Jany. K tomuto účelu se používá klauzule WHERE, kde se udávají podmínky. Jednoduché podmínky zadáváme ve formátu sloupec operátor hodnota. Mezi základní operátory patří:

  • = – je rovno,
  • > – je větší,
  • < – je menší,
  • >= – je větší nebo rovno,
  • <= – je menší nebo rovno,
  • != – není rovno.

Složitější operátory si ukážeme dále v této lekci. Dotaz pro vyhledání všech Janů by tedy vypadal následovně:

SELECT * FROM [Uzivatele] WHERE [Jmeno] = 'Jan';

Vypustili jsme TOP 10, abychom dostali všechny Jany.

Specifikace sloupců

Tabulky mají většinou mnoho sloupců a většinou nás zajímají jen nějaké. Abychom databázi nezatěžovali přenášením zbytečných dat zpět do naší aplikace, budeme se snažit vždy specifikovat jen ty sloupce, které chceme. Dejme tomu, že budeme chtít jen příjmení lidí, kteří se jmenují Jan, a ještě počet jejich článků. Dotaz upravíme:

SELECT [Prijmeni], [PocetClanku] FROM [Uzivatele] WHERE [Jmeno] = 'Jan';

Místo hvězdičky * za klíčovým slovem SELECT jsme vyjmenovali požadované sloupce Prijmeni a PocetClanku. Výčet sloupců, které má dotaz vrátit, nemá nic společného s dalšími sloupci, které v dotazu používáme. Můžeme tedy vyhledávat podle deseti sloupců, ale vrátit jen jeden.

Výsledek:

Prijmeni PocetClanku
Novák 17
Spáčil 3

Opravdu nebuďme líní a pokud nepotřebujeme téměř všechny sloupce, vyjmenujme v příkazu SELECT ty, jejichž hodnoty vás v tu chvíli zajímají. Vždy se snažme podmínku omezit co nejvíce již na úrovni databáze, ne že si vytaháme celou tabulku do aplikace a tam si ji vyfiltrujeme. Řekněme, že by vaše aplikace poté nebyla úplně rychlá :)

Bez klauzule WHERE

Stejně jako tomu bylo u DELETE nebo UPDATE, i zde bude fungovat pouze dotaz:

SELECT * FROM [Uzivatele];

Tehdy budou vybráni úplně všichni uživatelé z tabulky.

Složitější podmínky

Teď vyberme všechny uživatele, narozené od roku 1960 a s počtem článků vyšším než 5:

SELECT * FROM [Uzivatele] WHERE [DatumNarozeni] >= '1960-1-1' AND [PocetClanku] > 5;

Výsledek:

Id Jmeno Prijmeni DatumNarozeni PocetClanku
1 Jan Novák 1984-11-03 17
9 Vítezslav Churý 1969-06-02 7
10 Pavel Procházka 1962-07-03 8
20 Jaroslav Novotný 1980-08-11 8
21 Petr Dvořák 1982-09-30 18
26 Pavel Dušín 1991-05-01 9
27 Otakar Kovář 1992-12-17 9

Všimněme si v dotazu logického operátoru AND ("a zároveň"). To určuje, že podmínky musí být splněny obě. Pokud bychom chtěli, aby se do výsledku zařadilo vše, co splňuje alespoň jednu podmínku, místo operátoru AND bychom použili logický operátor OR ("nebo"):

SELECT * FROM [Uzivatele] WHERE [DatumNarozeni] >= '1960-1-1' OR [PocetClanku] > 5;

Dotaz by poté česky zněl: "Vyber všechny sloupce uživatelů, kteří se narodili od roku 1960 nebo napsali více než 5 článků".

Priorita logických operátorů

Zkusme vybrat všechny uživatele narozené od roku 1970, kteří napsali 2 nebo 8 článků. S dosavadními znalostmi bychom dotaz napsali třeba takto:

SELECT *
FROM [Uzivatele]
WHERE [DatumNarozeni] >= '1970-1-1' AND [PocetClanku] = 2 OR [PocetClanku] = 8;

Dotaz však nevrací požadované výsledky:

Id Jmeno Prijmeni DatumNarozeni PocetClanku
10 Pavel Procházka 1962-07-03 8
20 Jaroslav Novotný 1980-08-11 8
25 Vera Svobodová 1983-03-02 2

Pavel Procházka se totiž narodil před rokem 1970 a neměl by se tak ve výsledku vyskytovat. Problém nám zde činí to, že operátor AND má při vyhodnocování podmínky vyšší prioritu než operátor OR. Ve skutečnosti tedy vybíráme uživatele, kteří splňují aspoň jednu z následujících podmínek:

  • "narodili se od roku 1970 a napsali 2 články",
  • "napsali 8 článků".

Aby dotaz vracel správné výsledky musíme využít závorky () pro změnu priority vyhodnocování logických operátorů:

SELECT *
FROM [Uzivatele]
WHERE [DatumNarozeni] >= '1970-1-1' AND ([PocetClanku] = 2 OR [PocetClanku] = 8);

Výsledek:

Id Jmeno Prijmeni DatumNarozeni PocetClanku
20 Jaroslav Novotný 1980-08-11 8
25 Věra Svobodová 1983-03-02 2

Operátory

V SQL máme i další operátory, řekněme si o LIKE, IN a BETWEEN.

LIKE

LIKE umožňuje vyhledávat textové hodnoty jen podle části textu. Funguje podobně, jako operátor = (rovná se), navíc ale můžeme používat dva zástupné znaky:

  • % (procento) označuje libovolný počet libovolných znaků.
  • _ (podtržítko) označuje jeden libovolný znak.

Pojďme si vyzkoušet několik dotazů s operátorem LIKE. Najděme příjmení lidí začínající na "S":

SELECT [Prijmeni] FROM [Uzivatele] WHERE [Prijmeni] LIKE 's%';

Text zadáme jako vždy v apostrofech, pouze na některá místa můžeme vložit speciální znaky. Na velikosti písmen nezáleží (hledání je tedy case-insensitive). Výsledek dotazu bude následující:

Prijmeni
Svoboda
Svobodová
Spáčil

Nyní zkusme najít pětipísmenná příjmení, která mají jako druhý znak "O". Je obecně doporučováno odstraňovat v hodnotách předávaných operátoru LIKE bílé znaky. Toho docílíte funkcemi LTRIM() a RTRIM(), které odstraňují bílé znaky zleva a zprava:

SELECT [Prijmeni] FROM [Uzivatele] WHERE RTRIM([Prijmeni]) LIKE '_o___';

Výsledek:

Prijmeni
Novák
Horák
Kovář

Asi již tušíte, jak LIKE funguje. Použití lze vymyslet mnoho, většinou se používá s procenty na obou stranách pro fulltextové vyhledávání (například slova v textu článku).

IN

IN umožňuje vyhledávat pomocí výčtu prvků. Udělejme si tedy výčet jmen a vyhledejme uživatele s těmito jmény:

SELECT [Jmeno], [Prijmeni] FROM [Uzivatele] WHERE [Jmeno] IN ('Petr', 'Jan', 'Kateřina');

Výsledek:

Jmeno Prijmeni
Jan Novák
Petr Černý
Petr Dvořák
Kateřina Koubová
Jan Spáčil

Operátor IN se používá ještě u tzv. poddotazů, ale na ty máme ještě dost času :)

BETWEEN

Poslední operátor, který si dnes vysvětlíme, je BETWEEN (tedy "mezi"). Není ničím jiným, než zkráceným zápisem podmínky >= AND <=. Již víme, že i datumy můžeme běžně porovnávat. Najděme si uživatele, kteří se narodili mezi lety 1980 a 1990:

SELECT [Jmeno], [Prijmeni], [DatumNarozeni] FROM [Uzivatele] WHERE [DatumNarozeni] BETWEEN '1980-1-1' AND '1990-1-1';

Mezi dvě mezní hodnoty píšeme klíčové slovo AND.

Výsledek:

Jmeno Prijmeni DatumNarozeni
Jan Novák 1984-11-03
Vladimír Pokorný 1984-04-18
Jaroslav Novotný 1980-08-11
Petr Dvořák 1982-09-30
Věra Svobodová 1983-03-02

Dotaz bychom mohli vylepšit porovnáváním jen roku z daného data pomocí funkce YEAR():

SELECT [Jmeno], [Prijmeni], [DatumNarozeni] FROM [Uzivatele] WHERE YEAR([DatumNarozeni]) BETWEEN 1980 AND 1990;

To je pro dnešek vše. U výběru dat zůstaneme ještě několik dílů.

V následujícím cvičení, Řešené úlohy k 6. lekci MS-SQL, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Řešené úlohy k 1.-5. lekci MS-SQL
Všechny články v sekci
MS-SQL databáze krok za krokem
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 6. lekci MS-SQL
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
461 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity