MySQL Regulární výrazy (Regexp)
⚡ Chytré shrnutí
MySQL Regulární výrazy (REGEXP) porovnávají hodnoty sloupců s flexibilními vzory, které zástupné znaky nemohou vyjádřit. Zde je vysvětlena syntaxe REGEXP, synonymum RLIKE, všechny podporované metaznaky, opravené příklady dotazů v databázi myflixdb a funkce regulárních výrazů přidané v MySQL 8.0.
Jaké jsou MySQL regulární výrazy?
MySQL regulární výrazy vám pomohou vyhledat data, která odpovídají složitým kritériím. Regulární výraz je vzor, který popisuje tvar hledané hodnoty, nikoli samotnou hodnotu.
Pokud jste již s MySQL zástupné znakyMožná se ptáte, proč se regulární výrazy vyplatí učit, když LIKE dává podobné výsledky. Odpovědí je expresivní síla: zástupné znaky nabízejí pouze dva symboly, zatímco regulární výrazy popisují rozsahy znaků, alternativy, opakování a pozice slov v jednom vzoru.
Po stanovení účelu se v následující části seznámíme s syntaxí, kterou budete používat v každém dotazu REGEXP.
Základní syntaxe REGEXP
Základní syntaxe regulárního výrazu je následující.
SELECT * FROM table_name WHERE fieldname REGEXP 'pattern';
ZDE:
- „Příkaz SELECT“ je standard příkaz SELECT.
- "KDE název pole" je název sloupce, na kterém se provádí regulární výraz.
- "Vzor REGEXP" — REGEXP je operátor regulárního výrazu a „pattern“ představuje vzor, který má být nalezen. RLIKE je synonymum pro REGEXP a vrací stejné výsledky. Abyste se vyhnuli záměně s operátorem LIKE, je lepší použít REGEXP.
Podívejme se nyní na praktický příklad.
SELECT * FROM `movies` WHERE `title` REGEXP 'code';
Výše uvedený dotaz vyhledává všechny názvy filmů, které obsahují slovo „code“. Nezáleží na tom, zda se slovo „code“ objevuje na začátku, uprostřed nebo na konci názvu. Pokud název obsahuje daný vzor, je vrácen řádek.
Porovnání začátku hodnoty se seznamem znaků
Předpokládejme, že chceme filmy, jejichž názvy začínají písmeny a, b, c nebo d, za nimiž následuje libovolný počet dalších znaků. Tohoto výsledku dosáhneme kombinací seznamu znaků s metaznakem stříška.
SELECT * FROM `movies` WHERE `title` REGEXP '^[abcd]';
Spuštění výše uvedeného skriptu v MySQL Workbench s databází myflixdb nám dává následující výsledky.
| movie_id | titul | ředitel | rok_vydáno | category_id |
|---|---|---|---|---|
| 4 | Code Jméno Černá | Edgar Jimz | 2010 | NULL |
| 5 | Tatínkovy holčičky | NULL | 2007 | 8 |
| 6 | andělé a démoni | NULL | 2007 | 6 |
| 7 | Davinci Code | NULL | 2007 | 6 |
Ve vzoru '^[abcd]' vyžaduje stříška (^) shodu na začátku hodnoty a seznam znaků [abcd] akceptuje pouze názvy, jejichž první písmeno je a, b, c nebo d. Porovnání při výchozím řazení nerozlišuje velká a malá písmena, a proto „Code Vrátí se „jméno Black“.
Vyloučení znaků se seznamem negovaných znaků
Nyní upravme skript a negatujme seznam znaků, abychom zjistili, které řádky se vrátí.
SELECT * FROM `movies` WHERE `title` REGEXP '^[^abcd]';
Spuštění výše uvedeného skriptu v MySQL Workbench s databází myflixdb nám dává následující výsledky.
| movie_id | titul | ředitel | rok_vydáno | category_id |
|---|---|---|---|---|
| 1 | Piráti z Karibiku 4 | Rob Marshall | 2011 | 1 |
| 2 | Zapomínání na Sarah Marshal | Nicholas Stoller | 2008 | 2 |
| 3 | X-Men | 2008 | ||
| 9 | Honey mooneRS | John Schultz | 2005 | 8 |
| 16 | 67% vinen | 2012 | ||
| 17 | Diktátor | Chalie Chaplie | 1920 | 7 |
| 18 | ukázkový film | Anonymní | 8 | |
| 19 | film 3 | John Brown | 1920 | 8 |
Uvnitř seznamu znaků se význam stříšky změní: '^[^abcd]' stále ukotví shodu na začátku, zatímco [^abcd] nyní vylučuje všechny názvy, které začínají jedním z uzavřených znaků.
Tyto dva příklady používají pouze kotvy a seznamy znaků. Následující část se zabývá celou sadou metaznaků.
Metaznaky regulárních výrazů
Výše uvedené příklady ukazují nejjednodušší formu regulárního výrazu. Metaznaky umožňují doladit vyhledávání podle vzoru: vyjadřují opakování, alternativy, rozsahy a pozice. V tabulce níže jsou uvedeny všechny metaznaky podporované regulárním výrazem. MySQL Operátor REGEXP s opraveným příkladem pro každý z nich.
| Char | Description | Příklad | |
|---|---|---|---|
| * | Jedno hvězdička (*) shoduje se s nulou (0) nebo více instancemi jediná postava která tomu předchází. | SELECT * Z filmů WHERE název REGEXP 'da*'; odpovídá písmenu „d“ následovanému nulou nebo více znaky „a“, takže Da Vinci Code a Daddy's Little Girls se kvalifikují. Použijte 'da+', když musí být skutečně přítomno písmeno „a“. | |
| + | Jedno více (+) odpovídá jednomu nebo více výskytům znaku, který mu předchází. | SELECT * FROM `filmy` WHERE `title` REGEXP 'mon+'; zobrazí všechny filmy obsahující slovo „mon“ následované jedním nebo více znaky „n“. Například Andělé a démoni. | |
| ? | Jedno otazník (?) odpovídá nule (0) nebo jednomu výskytu znaku, který mu předchází. | SELECT * FROM `categories` WHERE `category_name` REGEXP 'com?'; shoduje se s „co“ a volitelným „m“. Například komedie a romantická komedie. | |
| . | Jedno tečka (.) odpovídá libovolnému jednotlivému znaku kromě nového řádku. | SELECT * FROM movies WHERE `year_released` REGEXP '200.'; uvádí všechny filmy vydané v daném roce začínající písmenem „200“ následovaným libovolným jednotlivým znakem. Například 2005, 2007, 2008. | |
| [abc] | Jedno seznam znaků [abc] odpovídá kterémukoli z uzavřených znaků. | SELECT * FROM `filmy` WHERE `title` REGEXP '[vwxyz]'; uvádí všechny filmy obsahující libovolnou postavu z „vwxyz“. Například X-Men a Da Vinci Code. | |
| [^abc] | Jedno negovaný seznam [^abc] odpovídá libovolnému znaku kromě těch, které jsou v něm uvedeny. | SELECT * FROM `filmy` WHERE `title` REGEXP '^[^vwxyz]'; uvádí všechny filmy, jejichž název nezačíná znakem ve slově „vwxyz“. | |
| [AZ] | Jedno rozsah [AZ] odpovídá libovolnému velkému písmenu. | SELECT * FROM `členové` WHERE `poštovní_adresa` REGEXP '[AZ]'; zobrazí všechny členy, jejichž poštovní adresa obsahuje písmeno mezi A a Z. Například Janet Jones s číslem členství 1. | |
| [az] | Jedno rozsah [az] odpovídá libovolnému malému písmenu. | SELECT * FROM `členové` WHERE `poštovní_adresa` REGEXP '[az]'; vrátí všechny členy, jejichž poštovní adresa obsahuje písmeno mezi a a z. Všimněte si, že výchozí řazení nerozlišuje velká a malá písmena, takže tento rozsah odpovídá i velkým písmenům. | |
| [0-9] | Jedno rozsah [0-9] odpovídá jakékoli číslici od 0 do 9. | SELECT * FROM `členové` WHERE `kontaktní_číslo` REGEXP '[0-9]'; zobrazí všechny členy, jejichž kontaktní číslo obsahuje alespoň jednu číslici. Například Robert Phil. | |
| ^ | Jedno stříška (^) ukotví shodu na začátek hodnoty. | SELECT * FROM `filmy` WHERE `title` REGEXP '^[cd]'; zobrazí všechny filmy, jejichž název začíná na „c“ nebo „d“. Například Code Jméno Black, Daddy's Little Girls a Da Vinci Code. | |
| $ | Jedno znak dolaru ($) ukotví shodu na konci hodnoty. | SELECT * FROM `filmy` WHERE `titul` REGEXP 'kód$'; uvádí všechny filmy, jejichž název končí na „code“. Například Da Vinci Code. | |
| | | Jedno svislý pruh (|) izoluje alternativy. | SELECT * FROM `filmy` WHERE `title` REGEXP '^[cd]|^[u]'; zobrazí všechny filmy, jejichž název začíná písmenem „c“, „d“ nebo „u“. Například Code Jméno Black, Da Vinci Codea Podsvětí – AwakenIng. | |
| \b | Jedno hranice slova (\b) odpovídá začátku nebo konci slova. Nahrazuje starší značky [[:<:]] a [[:>:]], které MySQL 8.0 odstraněno. | SELECT * FROM `filmy` WHERE `titul` REGEXP '\\bpro'; uvádí všechny filmy se slovem začínajícím na „pro“. Například Zapomeňme na Sarah Marshalovou. Na MySQL 5.7 ekvivalentní vzor je '[[:<:]]pro'. | |
| [[:třída:]] | Jedno třída postavy odpovídá pojmenované skupině znaků: [[:alpha:]] pro písmena, [[:space:]] pro mezery, [[:punct:]] pro interpunkci a [[:upper:]] pro velká písmena. Všimněte si zdvojnásobit hranaté závorky. | SELECT * FROM `filmy` WHERE `titul` REGEXP '^[[:alpha:][:space:]]+$'; uvádí všechny filmy, jejichž název obsahuje pouze písmena a mezery. Například Zapomeňme na Sarah Marshalovou, zatímco Piráti z Karibiku 4 je vynechán kvůli číslici. | |
Zpětné lomítko (\) je řídicí znak. Protože MySQL Nejprve analyzuje řetězec a poté vzor, doslovné zpětné lomítko musí být uvnitř vzoru REGEXP zapsáno jako dvojité zpětné lomítko (\\).
⚠️ Upozornění na verzi: MySQL Verze 8.0.4 nahradila starý engine regulárních výrazů knihovnou ICU. Značky slov [[:<:]] a [[:>:]] byly v této verzi odstraněny, takže vzory zkopírované ze staršího materiálu selhávají s chybou „syntaxe error“ na MySQL 8.0. Použijte místo toho \b.
Nyní, když jsou definovány všechny metaznaky, vyvstává oprávněná otázka: kdy by měl REGEXP nahradit jednodušší operátor LIKE?
REGEXP vs. LIKE: který z nich byste měli použít?
Oba operátory filtrují řádky podle vzoru, ale řeší různé problémy. LIKE rozumí pouze dvěma symbolům, zatímco REGEXP rozumí celé sadě metaznaků uvedené výše. Tato schopnost má svou cenu, takže volba je spíše kompromisem než preferencí.
| Kritérium | LIKE | REGELEXP |
|---|---|---|
| Symboly vzorů | pouze % a _ | Anchors, rozsahy, alternace, kvantifikátory, třídy znaků |
| Typické použití | Vyhledávání předpon, přípon a „obsahuje“ | Validace, více alternativ, porovnávání s ohledem na polohu |
| Využití indexu | Možné, pokud vzor nezačíná znakem %. | Nikdy nepoužívá index |
| Návratová hodnota | PRAVDA nebo NEPRAVDA | 1 nebo 0 a NULL, pokud je kterýkoli z operandů NULL |
Pro přímočaré porovnávání zvolte LIKE, protože se dobře čte a stále může používat index. REGEXP zvolte, pokud jeden vzor musí vyjadřovat několik pravidel najednou, například „začíná na c nebo d a končí číslicí“. U velkých tabulek nejprve zúžte řádky pomocí indexované podmínky a poté na tuto menší množinu použijte REGEXP.
MySQL Funkce regulárních výrazů 8.0
Operátor REGEXP odpovídá pouze na jednu otázku: odpovídá hodnota vzoru? MySQL Verze 8.0 přidala čtyři funkce, které jdou ještě dále a umožňují vám lokalizovat, např.tract a přepište odpovídající text. Každý z nich přijímá volitelný argument match_type, kde 'c' vynutí porovnání s rozlišováním velkých a malých písmen a 'i' vynutí porovnání bez rozlišování velkých a malých písmen.
- REGEXP_LIKE(výraz, vzor) Vrací 1, pokud hodnota odpovídá vzoru. Jedná se o funkční formu operátoru REGEXP a argument match_type explicitně rozlišuje velká a malá písmena.
- REGEXP_INSTR(výraz, vzor) vrací pozici prvního znaku shody nebo 0, pokud vzor není nalezen.
- REGEXP_SUBSTR(výraz, vzor) vrací samotný odpovídající podřetězec, což je užitečné pro vytažení roku, kódu nebo čísla z delší textové hodnoty.
- REGEXP_REPLACE(výraz, vzor, nahrazení) vrací hodnotu s každou nahrazenou shodou, takže může vyčistit data uvnitř SQL aktualizační dotaz.
SELECT title, REGEXP_SUBSTR(title, '[0-9]+') AS number_in_title FROM `movies` WHERE REGEXP_LIKE(title, '[0-9]');
Výše uvedený dotaz vrací všechny názvy filmů, které obsahují číslici, spolu s těmito číslicemi samotnými. MySQL 5.7 tyto funkce nejsou k dispozici, takže operátor REGEXP zůstává jedinou možností.

