EXECUTE
příkaz musí mít pevný seznam argumentů, takže si budete muset připravit a proveďte příkaz v IF/THEN/ELSE
blokovat.
IF articlesModule = 1 THEN
SET @query = ... UNION ...
PREPARE stmt FROM @query;
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
ELSE
SET @query = ...; /* no UNION */
PREPARE stmt FROM @query;
EXECUTE stmt USING @searchWordIn, @searchWordIn;
END IF;
Neznám žádný způsob, jak to vyřešit v omezeném rozsahu jazyka uložených procedur MySQL. Pro mě je to další dobrý důvod, proč nepoužívat dynamické SQL v uložených procedurách.
K vašim komentářům:
Chápu... můžete použít CASE prohlášení
místo IF/THEN/ELSE
, ale ve skutečnosti máte 2 =128 potenciálních různých případů pro řetězce dotazů, protože předpokládám, že kterýkoli z těchto 7 modulů lze prohledat nebo ne.
Alternativou, která by vám umožnila používat parametry dotazu, je zapomenout na použití UNION
a místo toho zapište proceduru tak, aby spustila až 7 samostatných SELECT
dotazy a vrátí je všechny jako více sad výsledků . To je něco, co mají uložené procedury dělat. Ale musíte napsat kód ve vaší vrstvě PHP, abyste postupně získali každou sadu výsledků. To znamená, že smyčka přes výsledné sady a v rámci této smyčky smyčka přes řádky aktuální sady výsledků. Viz příklad na PDO::nextRowset()
nebo mysqli::next_result()
.
Ne, pokud to uděláte, nejste v bezpečí! Použití parametru dotazu v PHP k předání řetězce do CALL WEBSITE_mainSearch(?)
je k ochraně před vložením SQL k ničemu, pokud pak zřetězíte hodnotu parametru do jiného řetězce uvnitř procedury a provedete dynamickou analýzu a provedení SQL. Použití parametrů dotazu nečiní hodnoty parametrů "bezpečnými", pouze oddělují tyto hodnoty od fáze analýzy SQL.
Jste ve větším bezpečí, pokud používáte vestavěnou funkci MySQL CITACE()
při zřetězení strun. QUOTE()
dělá escapování speciálních znaků, stejně jako mysql_real_escape_string()
. Až na to, že je to trochu jiné, protože také vytváří jednoduché uvozovky vymezující řetězec, jako je PDO::quote()
ano.
SET @query = CONCAT(@query, 'SELECT blockName AS itemName, blockPath AS seoName,
blockID AS itemID, MATCH(blockName, blockBody) AGAINST (',
QUOTE(searchWordIn), ') AS relevance, \'block\' AS itemType
FROM content_blocks WHERE MATCH(blockName, blockBody) AGAINST (',
QUOTE(searchWordIn),')') ;
Aktualizace:ještě jedna alternativa:použijte UNION
přidat další poddotazy a udržet počet modulů. Poté použijte CASE
pro provedení připraveného dotazu s jiným počtem parametrů na základě akumulovaného počtu.
SET @n = 0;
IF articlesModule = 1 THEN
SET @query = ... UNION ...
SET @n = @n+1;
END IF;
IF newsModule = 1 THEN
SET @query = ... UNION ...
SET @n = @n+1;
END IF;
... and similar for the other 5 modules ...
PREPARE stmt FROM @query;
CASE @n
WHEN 1:
EXECUTE stmt USING @searchWordIn, @searchWordIn;
WHEN 2:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 3:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
WHEN 4:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 5:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
WHEN 6:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn;
WHEN 7:
EXECUTE stmt USING @searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn, @searchWordIn, @searchWordIn,
@searchWordIn, @searchWordIn;
END;