WYKONAJ
oświadczenie musi mieć ustaloną listę argumentów, więc będziesz musiał przygotować i wykonaj instrukcję w IF/THEN/ELSE
blokować.
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;
Nie znam żadnego sposobu rozwiązania tego w ograniczonym zakresie języka procedur składowanych MySQL. Dla mnie to kolejny dobry powód, aby nie używać dynamicznego SQL w procedurach składowanych.
Odpowiedz na swoje komentarze:
Rozumiem... możesz użyć CASE oświadczenie
zamiast IF/THEN/ELSE
, ale w rzeczywistości masz 2 =128 potencjalnych różnych przypadków dla ciągów zapytań, ponieważ zakładam, że którykolwiek z tych 7 modułów może być przeszukiwany lub nie.
Alternatywą, która pozwoliłaby na użycie parametrów zapytania, jest zapomnienie o używaniu UNION
, a zamiast tego napisz procedurę w taki sposób, aby uruchamiała do 7 oddzielnych SELECT
zapytania i zwraca je wszystkie jako wiele zestawów wyników . To jest coś, do czego mają służyć procedury składowane. Ale musisz napisać kod w swojej warstwie PHP, aby po kolei pobrać każdy zestaw wyników. Oznacza to, że pętla nad zestawami wyników i w tej pętli pętla nad wierszami bieżącego zestawu wyników. Zobacz przykład na PDO::nextRowset()
lub mysqli::next_result()
.
Nie, nie jesteś bezpieczny, jeśli to zrobisz! Użycie parametru zapytania w PHP do przekazania ciągu do CALL WEBSITE_mainSearch(?)
jest bezużyteczny do ochrony przed wstrzyknięciem SQL, jeśli następnie połączysz tę wartość parametru z innym łańcuchem wewnątrz procedury i wykonasz dynamiczną analizę i wykonanie SQL. Użycie parametrów zapytania nie powoduje, że wartości parametrów są „bezpieczne”, po prostu oddzielają te wartości od fazy analizy SQL.
Jesteś bezpieczniejszy, jeśli używasz wbudowanej funkcji MySQL WYCENA()
podczas łączenia ciągów. WYCENA()
wykonuje ucieczki znaków specjalnych, tak jak mysql_real_escape_string()
. Z wyjątkiem tego, że jest nieco inny, ponieważ tworzy również pojedyncze cudzysłowy oddzielające ciąg, takie jak PDO::cytat()
tak.
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),')') ;
Aktualizacja:jeszcze jedna alternatywa:użyj UNION
aby dodać więcej podzapytań i zachować liczbę modułów. Następnie użyj CASE
aby wykonać przygotowane zapytanie z inną liczbą parametrów w oparciu o skumulowaną liczbę.
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;