De EXECUTE
statement moet een vaste lijst met argumenten krijgen, dus je moet en . voorbereiden voer de instructie uit in een IF/THEN/ELSE
blok.
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;
Ik weet geen enkele manier om dit op te lossen in de beperkte reikwijdte van de MySQL-opgeslagen proceduretaal. Voor mij is het nog een goede reden om geen dynamische SQL te gebruiken in opgeslagen procedures.
Over uw opmerkingen:
Ik begrijp het... je zou een CASE
verklaring
in plaats van een IF/THEN/ELSE
, maar je hebt eigenlijk 2 =128 mogelijke verschillende gevallen voor queryreeksen, omdat ik aanneem dat elk van die 7 modules kan worden doorzocht of niet.
Een alternatief waarmee u queryparameters kunt gebruiken, is het gebruik van UNION
. te vergeten , en schrijf in plaats daarvan de procedure op zo'n manier dat er maximaal 7 afzonderlijke SELECT
query's en retourneert ze allemaal als meerdere resultatensets . Daar zijn opgeslagen procedures voor bedoeld. Maar u moet code in uw PHP-laag schrijven om elke resultaatset om de beurt op te halen. Dat wil zeggen, lus over de resultaatsets, en binnen die lus, lus over de rijen van de huidige resultaatset. Zie voorbeeld op PDO::nextRowset()
of mysqli::next_result()
.
Nee, je bent niet veilig als je dat doet! Een queryparameter in PHP gebruiken om een string door te geven aan de CALL WEBSITE_mainSearch(?)
is nutteloos voor bescherming tegen SQL-injectie, als u die parameterwaarde vervolgens samenvoegt in een andere tekenreeks binnen de procedure en een dynamische SQL-parse-and-execute uitvoert. Het gebruik van queryparameters maakt parameterwaarden niet "veilig", ze scheiden die waarden alleen van de SQL-parseerfase.
Je bent veiliger als je de ingebouwde functie van MySQL gebruikt QUOTE()
bij het aaneenschakelen van de snaren. QUOTE()
doet escapen van speciale tekens, net als mysql_real_escape_string()
. Behalve dat het iets anders is, omdat het ook de enkele aanhalingstekens produceert die de tekenreeks afbakenen, zoals BOB::quote()
doet.
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),')') ;
Update:nog een alternatief:gebruik UNION
om meer subquery's toe te voegen en het aantal modules bij te houden. Gebruik dan een CASE
om de voorbereide query uit te voeren met een ander aantal parameters op basis van de geaccumuleerde telling.
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;