Obsahuje tabulka daný text?

Školení, která pořádám

Jaký dotaz je nejlepší položit, pokud nás zajímá, zda jakýkoliv záznam v tabulce obsahuje určitou hodnotu, a už nás nezajímá, který záznam to je ani kolik jich je? Takový dotaz můžeme použít např. tehdy, když uživatel hledá v novinkách a my mu chceme nabídnout i vyhledávání v jiných objektech. Začněme prvním, co nás napadne:

<?php
mysql_num_rows(mysql_query("SELECT * FROM tabulka WHERE obsah LIKE '%" . mysql_real_escape_string($_GET["search"]) . "%'"));
// poprvé: 1.0481 s, potřetí: 0.4241 s
?>

Tento dotaz je nešikovný v tom, že prohledává všechny řádky a vrací nám obsah všech sloupců, který vůbec nepotřebujeme. Výše uvedený kód se obvykle nahrazuje tímto:

<?php
mysql_result(mysql_query("SELECT COUNT(*) FROM tabulka WHERE obsah LIKE '%" . mysql_real_escape_string($_GET["search"]) . "%'"), 0);
// poprvé: 0.7361 s, potřetí: 0.0505 s
?>

Dotaz vrací jedinou hodnotu, pořád ale prochází všechny řádky. Nás celkový počet záznamů nezajímá, chceme vědět jen ano/ne. Vrátíme se proto pokorně k prvnímu kódu, ale počet výsledků omezíme klauzulí LIMIT a místo všech sloupců si buď můžeme vybrat nějaký krátký (obvykle id) nebo jít ještě o krok dále a nechat si vrátit pouze konstantu:

<?php
mysql_num_rows(mysql_query("SELECT 1 FROM tabulka WHERE obsah LIKE '%" . mysql_real_escape_string($_GET["search"]) . "%' LIMIT 1"));
// poprvé: 0.2756 s, potřetí: 0.0499 s
?>
Jakub Vrána, Dobře míněné rady, 25.12.2006, diskuse: 16 (nové: 0)

Diskuse

Dan Péder:

MySQL nemá operátor exists?

ikona Jakub Vrána OpenID:

Má.

Onecar:

To je opravdu dobré, jsem rád, že znám nejrychlejší metodu :-).

maros:

a co ak chcem zistit to iste, ale je aj jedno, v ktorom stlpci? napr. vyhladavanie v tabulke clankov s nadpisom, uvodom a telom clanku...

ikona Jakub Vrána OpenID:

Potom je nutné všechny sloupce v podmínce vyjmenovat a oddělit pomocí OR. Někoho by mohlo napadnout ještě něco jako CONCAT(sloupec1, sloupec2) LIKE ..., ale tam je problém s jednoznačným oddělovačem.

Jakub:

Je lepší použít?

Toto

mysql_num_rows(mysql_query("SELECT 1 FROM tabulka WHERE obsah LIKE '%$_GET[search]%' LIMIT 1"));

nebo toto?

mysql_num_rows(mysql_query("SELECT 1 FROM tabulka WHERE obsah LIKE '%".$_GET["search"]."%' LIMIT 1"));

díky

Vlasta Neubauer:

v sql dotazu ani jedno. je lepší hodnotu $_GET["search"] před použitím nějak 'ošetřit'. ale jinak je to celkem fuk. já preferuji kratší variantu.

Pavel:

Davat $_GET[search] i do takoveto ukazky, ktera vubec pro svoji funkci nepotrebuje predstirat predani pomoci metody GET, to je proste uchylnost.

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL: Reakce na: Pavel

ikona Jakub Vrána OpenID:

Nejčastěji vyhledáváme přece to, co dostaneme od uživatele.

ikona D1ce:

IMHO je lepší všude cpát jednoduché uvozovky, a spojovat:

mysql_num_rows(mysql_query('SELECT 1 FROM tabulka WHERE obsah LIKE \'%'.$_GET['search'].'%\' LIMIT 1'));

Protože řetězec v jednoduchých uvozovkách se(jak bych to řek) neanalizuje nebo neparsuje tak jako řetězec ve dvoitých na vložené proměnné, escapované sekvence apod.

ikona dgx:

Proč by to mělo být lepší? Naopak, vkládání proměnných "...$x..." je pěkná feauture. A rozhodně přispívá k čitelnosti zdrojáku. Řekl bych, že i docela  značně.

uzivatel:

No na mnohych frameworkoch sa zauzivalo pouzivanie pri uvodzovkach pouzivat {$premenna}
Pri znakoch, ktore nie su dobre vidiet to celkom pomoze. Ale ak sa v kode vyskytuje mnoho premennych blizko seba je z toho pekny bordel.

trta:

malicko mimo tema, ale nekdy se muze hodit dotaz typu

SELECT SQL_CALC_FOUND_ROWS ... LIMIT ..

a nasledne

SELECT FOUND_ROWS()

kde ten druhy dotaz vrati pocet radku vracenych v dotazu, kdyz by nebyla aplikovana klauzule LIMIT...

ikona Jakub Vrána OpenID:

Někdy se to může hodit, ale ne v tomto případě. Napsal jsem o tom samostatný článek: http://php.vrana.cz/ziskani-poctu-radek.php

Jan:

Dobrý den, mám dotaz pokud použiji toto:
mysql_num_rows(mysql_query("SELECT 1 FROM tabulka WHERE obsah LIKE '%" . mysql_real_escape_string($_GET["search"]) . "%' LIMIT 1"));

u textu, který obsahuje diakritiku my to vráti, že v dtb a není a přitom tam je. Prosím o radu co stím. Děkuji

Jan:

Vyřešeno omlouvám se za spam.
avatar © 2005-2019 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.