sql >> Database >  >> RDS >> Mysql

Door MySQL opgeslagen procedure opgestelde instructie (dynamische SQL) geparametriseerd

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;



  1. 10 tijdbesparende tips voor MS Access-gebruikers

  2. php 5.x 7.x, ssl pdo-fout:Peer-certificaat CN=`someName' kwam niet overeen met verwacht CN='someIP'

  3. Hoe voeg ik een primaire sleutel auto_increment toe aan de SQL Server-database?

  4. Hoe bouw ik een cross-databasequery in PHP?