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

发布于 2024-10-14 01:12:06 字数 3439 浏览 2 评论 0原文

我正在使用 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 中省略输出参数,则会插入一行,但循环中的后续调用会失败。为了完成这项工作,我必须在循环中每次都准备新鲜的语句,然后再次将参数绑定到该语句。我仍然无法使用过程中的输出参数来完成这项工作,并且必须在过程中选择一个值才能将一些返回值传递给 PHP 进行处理。

有谁知道我哪里出了问题?理想情况下,我想准备一次语句,然后循环遍历结果,每次都使用新数据执行它。为了让这一切顺利进行,我是否缺少任何技巧?我正在 Windows 7 上使用 Apache 2.2.17、PHP 5.3.5 和 MySQL 5.5.8 进行开发。

编辑: 那么,在循环中多次执行该语句的答案似乎是每次调用 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

I'm using PHP to process some XML that I'm getting from a web service and to insert the results into a database. I've created a stored procedure to insert the records and I'm using PDO to prepare a statement that I'd then like to execute multiple times, something like this:

$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 />';
              }

In this example ':Result' would be a output value from the procedure. I cannot make this work at all though. If I omit the out put parameter both in the procedure code and PHP then one row gets inserted but subsequent calls in the loop fail. To make this work I have to prepare the statement fresh each time in the loop, then binding the parameters to the statement again. I still cannot make this work with an output parameter in the procedure and have to Select a value in the procedure to get some return value to PHP to process.

Does anyone know where I'm going wrong with this? Ideally I'd like to prepare the statement once and then loop through the results, executing it each time with fresh data. Are there any tricks that I'm missing to make all of this work? I'm developing on Windows 7 with Apache 2.2.17, PHP 5.3.5 and MySQL 5.5.8.

EDIT:
Well, the answer to executing the statement multiple times in the loop seems to be to call the PDOStatement::closeCursor() method each time after calling PDOStatement::execute(). Still no idea on how to get the value of an output parameter returned to PHP though.

EDIT
Here's the code for the procedure:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蝶…霜飞 2024-10-21 01:12:06

事实上,您无法像这样访问结果,请参阅这些帖子:

所以你需要将结果存储到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 />';

The fact is you can't access you result like this, see these posts :

So you will need to store the result into a MySQL var, then you can display it, like this :

<?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 />';
滥情空心 2024-10-21 01:12:06

尝试将字符串长度添加到输出参数:

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

Try adding a string length to the output parameter:

$st->bindParam(':Result', $result, PDO::PARAM_STR, 4000);
久隐师 2024-10-21 01:12:06

尝试添加 PDO::PARAM_INPUT_OUTPUT:

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

Try to add PDO::PARAM_INPUT_OUTPUT:

 $st->bindParam(':Result', $result, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文