Mysql
 sql >> Database >  >> RDS >> Mysql

Istruzione MySQL Stored Procedure preparata (SQL dinamico) parametrizzata

Il EXECUTE all'istruzione deve essere fornito un elenco fisso di argomenti, quindi dovrai preparare e eseguire l'istruzione in un IF/THEN/ELSE blocco.

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;

Non conosco alcun modo per risolverlo nell'ambito limitato del linguaggio delle procedure memorizzate MySQL. Per me, è un altro buon motivo per non utilizzare SQL dinamico nelle procedure memorizzate.

Re i tuoi commenti:

Capisco... potresti usare un CASE dichiarazione invece di un IF/THEN/ELSE , ma in realtà hai 2 =128 potenziali casi diversi per le stringhe di query, perché presumo che uno di questi 7 moduli possa essere cercato o meno.

Un'alternativa che ti consentirebbe di utilizzare i parametri di query è dimenticare di utilizzare UNION , e invece scrivi la procedura in modo tale che esegua fino a 7 SELECT separati interroga e li restituisce tutti come set di risultati multipli . Questo è qualcosa che le stored procedure sono destinate a fare. Ma devi scrivere codice nel tuo livello PHP per recuperare ogni set di risultati a turno. Cioè, scorrere i set di risultati e, all'interno di quel ciclo, scorrere le righe del set di risultati corrente. Vedi esempio in PDO::nextRowset() o mysqli::next_result() .

No, non sei al sicuro se lo fai! Utilizzo di un parametro di query in PHP per passare una stringa a CALL WEBSITE_mainSearch(?) è inutile per la protezione contro l'iniezione SQL, se quindi si concatena il valore del parametro in un'altra stringa all'interno della procedura e si esegue un'analisi ed esecuzione SQL dinamica. L'utilizzo dei parametri di query non rende i valori dei parametri "sicuri", ma semplicemente separano tali valori dalla fase di analisi SQL.

Sei più sicuro se utilizzi la funzione integrata di MySQL CITAZIONE() quando si concatenano le stringhe. QUOTE() fa l'escape dei caratteri speciali, proprio come mysql_real_escape_string() . Solo che è leggermente diverso, perché produce anche le virgolette singole che delimitano la stringa, come DOP::quote() fa.

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),')') ;

Aggiornamento:un'altra alternativa:usa UNION per aggiungere più sottoquery e tenere il conteggio dei moduli. Quindi usa un CASE per eseguire la query preparata con un numero diverso di parametri in base al conteggio accumulato.

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;