Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL Съхранена процедура Подготвен оператор (Динамичен SQL) Параметризиран

EXECUTE операторът трябва да получи фиксиран списък от аргументи, така че ще трябва да подготвите и изпълнете израза в IF/THEN/ELSE блокирай.

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;

Не знам никакъв начин да разреша това в ограничения обхват на езика на съхранената процедура MySQL. За мен това е още една добра причина да не използвам динамичен SQL в запомнените процедури.

За вашите коментари:

Разбирам... можете да използвате CASE изявление вместо IF/THEN/ELSE , но всъщност имате 2 =128 потенциални различни случая за низове на заявки, защото предполагам, че всеки от тези 7 модула може да бъде търсен или не.

Алтернатива, която би ви позволила да използвате параметри на заявката, е да забравите за използването на UNION и вместо това напишете процедурата по такъв начин, че да изпълнява до 7 отделни SELECT заявки и ги връща като множество набори от резултати . Това е нещо, което запомнените процедури са предназначени да правят. Но трябва да напишете код във вашия PHP слой, за да извлечете всеки набор от резултати на свой ред. Тоест, преминете през наборите от резултати и в този цикъл преминете през редовете на текущия набор от резултати. Вижте пример на PDO::nextRowset() или mysqli::next_result() .

Не, не сте в безопасност, ако направите това! Използване на параметър на заявка в PHP за предаване на низ към CALL WEBSITE_mainSearch(?) е безполезен за защита срещу SQL инжектиране, ако след това свържете тази стойност на параметъра в друг низ вътре в процедурата и извършите динамичен SQL разбор и изпълнение. Използването на параметри на заявката не прави стойностите на параметрите „безопасни“, те просто отделят тези стойности от фазата на SQL анализ.

Вие сте по-безопасни, ако използвате вградената функция на MySQL QUOTE() при конкатениране на низовете. QUOTE() прави екраниране на специални знаци, точно като mysql_real_escape_string() . Освен че е малко по-различен, защото също така произвежда единични кавички, ограничаващи низа, като PDO::quote() прави.

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

Актуализация:още една алтернатива:използвайте UNION за добавяне на още подзаявки и поддържане на броя на модулите. След това използвайте CASE за изпълнение на подготвената заявка с различен брой параметри въз основа на натрупания брой.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вмъкване на данни в MySQL база данни

  2. MySQL - преброяване на общия брой редове в php

  3. ГРЕШКА 2003 (HY000):Не мога да се свържа с MySQL сървър на локален хост (10061)

  4. pandasql няма да импортира:ImportError:не може да импортира име към_sql

  5. произволни 2 записа според позиция и ред по позиция