Вызов хранимой процедуры в цикле foreach - выполняется только первый - PullRequest
1 голос
/ 26 ноября 2010

Это действительно производная от моего предыдущего вопроса сегодня .

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

CREATE PROCEDURE PROC_1(
  IN param1 VARCHAR(255),
  IN param2 VARCHAR(255))
BEGIN
  DECLARE ok INT;
  DECLARE success, failure VARCHAR(255);

  /* several SELECT, IF ... THEN, INSERT and UPDATE operations which then SET ok var to 0 or 1 */
  IF ok = 1 THEN
    SET success = 'Everything went well';
    SELECT success;
    LEAVE;
  ELSE
    SET failure = 'Problem description';
    SELECT failure;
    LEAVE;    
  END IF;
END

Я сделал это так (короткая версия):

$calls = array(
    "CALL PROC_1('param1', 'param2')",
    "CALL PROC_1('param3', 'param4')",
    "CALL PROC_1('param5', 'param6')",
);

// assuming I'm already connected to DB with $link
foreach ($calls as $i => $call)
{
    echo $i . ': ';
    $result = mysql_query($call);
    $ok = ($result === FALSE) ? FALSE : TRUE;
    var_dump($ok);

    if ($result !== FALSE)
        mysql_free_result($result);
}

Первая итерация работает, как и ожидалось, но что-нибудь после возвращает FALSE.
Почему это?

Попробовал mysqli на всякий случай, но получил точно такой же вывод:

0: bool(true)
1: bool(false)
2: bool(false)

Что интересно, я проверил журналы MySQL (для ведения журнала всех запросов) и только первый запрос когда-либо попадал на сервер. Следующие запросы никогда не попадают на сервер.

PS. Я использую PHP 5.3.2 и Apache 2.2.17.


UPDATE

Согласно предложению Шакти Сингха, я проверил состояние $link перед тем, как обращаться к базе данных. Я заметил, что со второй итерации произошла ошибка, поэтому вот вывод с ошибкой:

ERROR: (0) 
0: bool(true)
ERROR: (0) 

ERROR: (0) 
1: bool(false)
ERROR: (2014) Commands out of sync; you can't run this command now

ERROR: (2014) Commands out of sync; you can't run this command now
2: bool(false)
ERROR: (2014) Commands out of sync; you can't run this command now

Кроме того, это появляется в журнале ошибок MySQL:

101126 15:46:28 [Warning] Aborted connection 129 to db: 'db1' user: 'root' host: 'localhost' (Got an error reading communication packets)

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

В php, когда мы вызываем хранимую процедуру в цикле, она просто выполняется один раз.Это происходит, когда хранимая процедура возвращает какой-либо набор результатов.Я столкнулся с той же проблемой.У меня была хранимая процедура для обновления записей таблицы.

DELIMITER $$

DROP PROCEDURE IF EXISTS `espritkm`.`update_notification`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `update_notification`(item_id_val VARCHAR(11),item_source_val VARCHAR(50),item_type_id_val INT(50),item_type_val VARCHAR(50),created_at_val BIGINT(11),pivot_user_id_val VARCHAR(256),pivot_item_type_val VARCHAR(64),pivot_owner_type_val VARCHAR(64),pivot_owner_id_val INT(11),user_id_val VARCHAR(64),  OUT row_effect VARCHAR(11))
Begin
  Declare item_count INT(10);
   SET @SQL1 = CONCAT('select count(*) into @item_count from item_notifications where item_id = ''', item_id_val, '''');                                                                                    PREPARE S1 FROM @SQL1;                                                                                EXECUTE S1;                                                                                    DEALLOCATE PREPARE S1;     
    IF @item_count = 0 THEN
       SET @SQL2 = CONCAT('INSERT INTO item_notifications (item_id,item_source,item_type_id,item_type,created_at,pivot_user_id,pivot_item_type,pivot_owner_type,pivot_owner_id,user_id) value(''',item_id_val,''',''',item_source_val,''',''',item_type_id_val,''',''',item_type_val,''',''',created_at_val,''',''',pivot_user_id_val,''',''',pivot_item_type_val,''',''',pivot_owner_type_val,''',''',pivot_owner_id_val,''',''',user_id_val,''')');    
 PREPARE S2 FROM @SQL2;                                                                                  EXECUTE S2;                                                                                     DEALLOCATE PREPARE S2;      
      SET row_effect= "Insert";    
    ELSE             
        SET row_effect= "Update";    

    SET @SQL3 = CONCAT('UPDATE item_notifications SET viewer_id = ''',user_id_val,''' WHERE item_id = ''' ,item_id_val,'''') ;     
       PREPARE S3 FROM @SQL3;                                                                                 EXECUTE S3;                                                                                    DEALLOCATE PREPARE S3;      

    END IF;
    SELECT row_effect;
END$$

DELIMITER ;

И это должно было быть выполнено для 1000+ строк, но выполнено только для одной записи.

В случаекогда ваш SP вернет какой-либо набор данных.Просто удалите переменную OUT или любой оператор select (только для ссылки на результат), и он будет работать нормально.

1 голос
/ 26 ноября 2010

Хранимая процедура может возвращать более одного набора результатов, и она всегда будет возвращать один дополнительный набор результатов, который не содержит никаких данных, но содержит общую информацию об ошибке / предупреждении о вызове процедуры в дополнение к любым явно возвращенным наборам результатов.

источник - http://forums.mysql.com/read.php?52,228296,228347#msg-228347

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