Obsahuje tabulka daný text?
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
?>
Diskuse
Dan Péder:
MySQL nemá operátor exists?
25.12.2006 18:27:10
Onecar:
To je opravdu dobré, jsem rád, že znám nejrychlejší metodu :-).
26.12.2006 11:32:00
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...
26.12.2006 22:05:06
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.
27.12.2006 10:57:32
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
27.12.2006 01:15:00
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.
27.12.2006 09:48:35
Pavel:
Davat $_GET[search] i do takoveto ukazky, ktera vubec pro svoji funkci nepotrebuje predstirat predani pomoci metody GET, to je proste uchylnost.
3.1.2007 22:34:16
Nejčastěji vyhledáváme přece to, co dostaneme od uživatele.
4.1.2007 11:09:43
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.
27.12.2006 19:13:35
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ě.
3.1.2007 22:43:47
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.
12.1.2007 19:41:13
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...
27.12.2006 20:07:19
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
17.5.2012 12:57:12
Jan:
Vyřešeno omlouvám se za spam.
17.5.2012 13:37:19