多次在预准备语句中调用存储过程

时间:2011-01-24 02:05:45

标签: php mysql pdo

我正在使用PHP来处理我从Web服务获取的一些XML并将结果插入到数据库中。我已经创建了一个存储过程来插入记录,我正在使用PDO来准备一个我想要多次执行的语句,如下所示:

$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, :Result)');
$st->bindParam(':Name', $Name, PDO::PARAM_STR);
$st->bindParam(':Id', $Id, PDO::PARAM_INT);
$st->bindParam(':Priority', $Priority, PDO::PARAM_STR);
$st->bindParam(':Territory', $Territory, PDO::PARAM_STR);
$st->bindParam(':DateCreated', $dateFormat, PDO::PARAM_STR);    
$st->bindParam(':Result', $result, PDO::PARAM_STR);
foreach ($this->xml->AccountsDataSet->MainRecord as $Account) {
                  $Name = (string) $Account->AcctDesc;
                  $Id = (int) $Account->AcctID;
                  if ($num = (int)$Account->CDF309607) {
                      $Priority = self::$priorityFields[$num];                    
                  } else {
                      $Priority = '';
                  }
                  if (! $Territory = (string) $Account->AcctState) {
                      $Territory = '';
                  }
                  $date = new DateTime($Account->AcctCreationDate, new DateTimeZone('UTC'));
                  $dateFormat = $date->format('Y-m-d H:i:s');
                  $st->execute();
                  echo $result . '<br />';
              }

在此示例中,“:Result”将是过程的输出值。但我根本无法完成这项工作。如果我在过程代码和PHP中省略了out put参数,则会插入一行,但循环中的后续调用将失败。为了完成这项工作,我必须每次在循环中准备语句,然后再将参数绑定到语句。我仍然无法使用过程中的输出参数来完成此工作,并且必须在过程中选择一个值以获取要处理的PHP的某些返回值。

有谁知道我在哪里出错?理想情况下,我想准备一次语句然后遍历结果,每次都用新数据执行它。是否有任何技巧可以让我完成所有这些工作?我正在使用Apache 2.2.17,PHP 5.3.5和MySQL 5.5.8在Windows 7上进行开发。

修改 好吧,在循环中多次执行语句的答案似乎是在每次调用PDOStatement :: execute()之后调用PDOStatement :: closeCursor()方法。仍然不知道如何获得返回PHP的输出参数的值。

修改 这是程序的代码:

CREATE
PROCEDURE foo.AddClient(IN ClientName VARCHAR(255), IN Client_Id INT UNSIGNED, IN Priority VARCHAR(255), IN Territory VARCHAR(100), IN DateCreated DATETIME, OUT Result VARCHAR(100))
  COMMENT 'Procedure to add a new client to the database'
BEGIN
  #Declare variables.
  DECLARE Priority_Id, Territory_Id  TINYINT UNSIGNED DEFAULT NULL;
  # Check if a Priority is defined. If so get the id, if not add it and get the id
  IF LENGTH(Priority) > 0 THEN
    SELECT
      PriorityId
    INTO
      Priority_Id
    FROM
      client_priority
    WHERE
      Name = Priority;
    IF Priority_Id IS NULL THEN
      INSERT INTO client_priority (Name) VALUES (Priority);
      SET Priority_Id = LAST_INSERT_ID();
    END IF;
  END IF;
  #Check if a Territory is defined. If so get the id, if not add it and get the id.
  IF LENGTH(Territory) > 0 THEN
    SELECT
      TerritoryId
    INTO
      Territory_Id
    FROM
      territories
    WHERE
      Name = Territory;
    IF Territory_Id IS NULL THEN
      INSERT INTO territories (Name) VALUES (Territory);
      SET Territory_Id = LAST_INSERT_ID();
    END IF;
  END IF;
  #Add the details of the client.
  BEGIN
    DECLARE EXIT HANDLER FOR SQLSTATE '23000'
    SET Result = 'Client already exists'; # Error handler in case client with the same name already exists.  
    INSERT INTO clients
      (ClientId, Name, PriorityId, TerritoryId, DateCreatedSalesNet) VALUES (Client_Id, ClientName, Priority_Id, Territory_Id, DateCreated);
    SET Result = 'Client Inserted';
  END;
END

3 个答案:

答案 0 :(得分:1)

尝试在输出参数中添加字符串长度:

$st->bindParam(':Result', $result, PDO::PARAM_STR, 4000);

答案 1 :(得分:1)

尝试添加PDO :: PARAM_INPUT_OUTPUT:

 $st->bindParam(':Result', $result, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);

答案 2 :(得分:1)

事实上你无法访问这样的结果,请看这些帖子:

因此,您需要将结果存储到MySQL var中,然后您可以显示它,如下所示:

<?php
// change 
$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, :Result)');
// to
$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, @result)');

// remove this line
$st->bindParam(':Result', $result, PDO::PARAM_STR);

// change
$st->execute();
echo $result . '<br />';
// to 
$st->execute();
echo $this->db->query('SELECT @result')->fetchColumn() . '<br />';