Использование пользовательской переменной MySQL в хранимой процедуре для предложения «in» - PullRequest
4 голосов
/ 21 октября 2009

При отправке строки разделенных запятыми идентификаторов, как varchar, в хранимую процедуру MySQL, я не могу использовать эту строку как часть предложения IN с возвращенными правильными результатами. Строка усекается до десятичной точки, и используется только первое значение.

Я думал, что смогу обойти это, подготовив и затем выполнив инструкцию, но это все равно вернуло только совпадение для первого значения.

Примеры кода могут сделать вещи немного понятнее. Я хочу преобразовать следующее в хранимую процедуру (с динамическим предложением in):

select id, name from cities where id in (1,2,3);

Это моя хранимая процедура с использованием подготовленного оператора:

DROP PROCEDURE IF EXISTS `cities_select_by_ids` $$
CREATE PROCEDURE `cities_select_by_ids`(
    in _cityIds varchar(1000)
)
BEGIN
SET  @cityIds = _cityIds;

PREPARE stmt FROM '
    select
      id,
      name
    from cities
    where id in (?);
';

EXECUTE stmt USING @cityIds;
DEALLOCATE PREPARE stmt;

END $$
DELIMITER ;

При вызове хранимой процедуры я получаю совпадение только для города '1':

call cities_select_by_ids_prepare('1, 2, 3');

Вот скрипт создания и вставки для таблицы и данных:

CREATE TABLE cities (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
);
insert into cities (name) values ('London'), ('Manchester'), ('Bristol'), ('Birmingham'), ('Brighton');

Ответы [ 3 ]

4 голосов
/ 18 февраля 2010

Попробуй это.

DROP PROCEDURE IF EXISTS `cities_select_by_ids_2`;

CREATE PROCEDURE `cities_select_by_ids_2`(
    in cityIDs varchar(1000)
)

BEGIN

#- ix - index into the list of city IDs
# cid - city ID
SET @ix := 1;
SET @cid := substring_index(cityIDs, ',', @ix);

LOOP_1: 
WHILE (@cid is not null) DO
    SELECT id,  name 
    FROM cities
        WHERE id in (@cid) ;

     #-- substring_index returns complete cityIDs string when index is > number of elements
     IF (length(substring_index(cityIDs, ',', @ix)) >= length(cityIDs)) THEN
          LEAVE LOOP_1;
     END IF;

     SET @ix := @ix + 1;
     SET @cid = substring_index(substring_index(cityIDs, ',', @ix), ',', -1);

END WHILE;
END 

#----
call cities_select_by_ids_2('1, 2');
3 голосов
/ 17 июля 2012

Еще одна альтернатива.

Запрос ниже работает только для поддерживаемых операторов PREPARED внутри хранимых процедур.MySQL 5.0 я думаю.Что гораздо лучше, чем использовать "find_in_set".Используйте двойные кавычки "" для строки.

/* Check your mysql version */

BEGIN
SET @sql_text:=concat(
   'SELECT 
      id,
      name
    FROM db.table
    WHERE 
      id IN 
      (',

      /* BEGIN Parameter */
      '91,57',
      /* END Parameter */

      ') ORDER BY id ASC');

PREPARE stmt from @sql_text;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END
2 голосов
/ 21 октября 2009

из-за того, как работает параметризация, это невозможно.

ближайший вы можете получить это:

where find_in_set(id, ?)

, но это не будет масштабироваться, так как не может использовать индекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...