【问题标题】:MySQL stored procedure no insert ID returned?MySQL存储过程没有返回插入ID?
【发布时间】:2018-06-23 03:55:38
【问题描述】:

我有一个非常简单的查询,不知道我在这里做错了什么。

我的数据库调用没有收到我期望的insert id

表格:

存储过程:

CREATE DEFINER=`root`@`localhost` PROCEDURE `addCustomerProduct`(IN in_customerID INT, in_productID INT)
BEGIN
    INSERT INTO order_customer_product (customerID, productID, retailAmountAtPurchase, faceValue)
    SELECT
        in_customerID,
        in_productID,
        p.retail,
        p.faceValue
    FROM
        products as p
    WHERE 
        p.productID = in_productID;
END

PHP:

   public function addProduct($data, $userID)
    {
        // Do we already have a pending order for this user?
        $orderID = $this->doesOrderExist($userID);

        // We had no order, lets create one
        if (!$orderID) {
            $orderID = $this->createOrder($userID);
        }

        /**
         * Insert the customer product.
         * This relates a denomination to a customer.
         */
        $customerProductID = $this->addCustomerProduct($data);

        // Add this customer product to the order
        $this->addProductToOrder(array("customerProductID" => $customerProductID, "orderID" => $orderID));

        // Return
        return $customerProductID;
    }

    /**
     * Description: Add a customer product / reward
     * Page: client/add_reward
     */
    public function addCustomerProduct($data){
        $procedure = "CALL addCustomerProduct(?,?)";
        $result = $this->db->query($procedure, $data);
        return $this->db->insert_id();
    }

问题所在的行是:$customerProductID = $this->addCustomerProduct($data);

正在向表中插入一条新记录,并且该表具有PK/AI。数据正常,但 0 返回为 $customerProductID

从 select 语句中插入可能不会返回 insert ID 吗?

更新@Ravi-

更新 2:

我创建了一个单独的方法并对正在发送的查询和数据进行硬编码。

添加记录正常,AI 上升,0 返回为last id

public function test(){
    $procedure = "CALL addCustomerProduct(?,?)";
    $result = $this->db->query($procedure, array("customerID" => 1, "productID" => 20));
    echo $this->db->insert_id();
}

还重新启动了 MySQL 服务器以确保那里没有发生任何异常情况。

另外,更新了 SP 以在不使用选择的情况下将随机数据插入表中。

CREATE DEFINER=`root`@`localhost` PROCEDURE `addCustomerProduct`(IN in_customerID INT, in_productID INT)
BEGIN
    INSERT INTO order_customer_product (customerID, productID, retailAmountAtPurchase, faceValue)
    VALUES(8,2,'4.55',25);
END

更新 3:

在插入之后,我将打印出运行的最后一个查询以及结果。您会注意到有 1 个受影响的行(正在插入)但 insert_id 仍然为 0。

CALL addCustomerProduct('8','33')

CI_DB_mysqli_result Object
(
    [conn_id] => mysqli Object
        (
            [affected_rows] => 1
            [client_info] => mysqlnd 5.0.12-dev - 20150407 - $Id: b396954eeb2d1d9ed7902b8bae237b287f21ad9e $
            [client_version] => 50012
            [connect_errno] => 0
            [connect_error] => 
            [errno] => 0
            [error] => 
            [error_list] => Array
                (
                )

            [field_count] => 0
            [host_info] => Localhost via UNIX socket
            [info] => 
            [insert_id] => 0
            [server_info] => 5.6.35
            [server_version] => 50635
            [stat] => Uptime: 1637  Threads: 3  Questions: 508  Slow queries: 0  Opens: 113  Flush tables: 1  Open tables: 106  Queries per second avg: 0.310
            [sqlstate] => 00000
            [protocol_version] => 10
            [thread_id] => 25
            [warning_count] => 0
        )

    [result_id] => 1
    [result_array] => Array
        (
        )

    [result_object] => Array
        (
        )

    [custom_result_object] => Array
        (
        )

    [current_row] => 0
    [num_rows] => 
    [row_data] => 
)

更新 4:

从我做的一些研究来看,除非你使用$this->db->insert()之类的mysqli方法,否则它不会向你提供最后一个插入id。

我将尝试找出 Ravi 的建议,但似乎代码点火器不允许显示的示例。至少我现在知道,除非您使用“insert”方法而不是存储过程,否则我并没有发疯,它只是不正常的行为。

【问题讨论】:

  • 您期望的插入 ID 是什么?
  • @Ravi - 从addCustomerProduct() 过程创建的AI,位于页面顶部。
  • 不应该是$this->db->insert_id; 而不是$this->db->insert_id();
  • @RamRaider - 不要相信,这是一个框架(CodeIgniter),这是一个内置的方法。在我的代码中的其他任何地方都可以使用:.
  • 打开“通用日志”以查看确切发出的命令。它不会包含insert_id(),但它可能包含 Codeigniter 正在插入的一些语句。

标签: php mysql codeigniter


【解决方案1】:

理想情况下,以下行应该可以工作

$this->db->insert_id;

但是,我不确定为什么不起作用,所以我建议以下解决方法,使用附加参数 out_lastId 重新编译您的过程,这将返回最后插入的 id

CREATE DEFINER=`root`@`localhost` PROCEDURE `addCustomerProduct`(IN in_customerID INT, in_productID INT, OUT out_lastId INT)

并且,在插入之后,使用最后插入的 id 设置值。

 SET out_lastId = LAST_INSERT_ID();

==更新==

$this->db->multi_query( "CALL addCustomerProduct($data, @id);SELECT @id as id" );
$db->next_result();            // flush the null RS from the call
$rs=$this->db->store_result();       // get the RS containing the id
echo $rs->fetch_object()->id, "\n";
$rs->free();

【讨论】:

  • $data 是一个包含我要发送的两个变量的数组。
  • 这会引发一个错误,因为我告诉 SP 将有 2 个参数进入,但在 SP 中定义了 3 个。
  • @SBB 当然,你需要添加 3 个参数,我想,你会从那里小心的。我也应该更新 php 代码吗?
  • 好吧,我添加了$procedure = "CALL addCustomerProduct(?,?, ?)";,但我不确定如何从那里获得价值。
  • @SBB 好久没写php了,不过我会试试的。
【解决方案2】:

This answer 可以解释为什么您现有的代码不起作用。引用:

CodeIgniter 的insert_id() 只会返回insert() 的ID。 除非您在调用函数之前执行了类似$this->db->insert('table', $data); 的操作,否则它将无法返回 ID。

MySQL 的LAST_INSERT_ID(); 应该可以帮助您(假设您有权更改存储过程定义)。改成:

CREATE DEFINER=`root`@`localhost` PROCEDURE `addCustomerProduct`(
    IN in_customerID INT, in_productID INT, OUT out_customerProductID INT)
BEGIN
    INSERT INTO order_customer_product (
        customerID, productID, retailAmountAtPurchase, faceValue)
    VALUES(8,2,'4.55',25);

    SELECT LAST_INSERT_ID() INTO out_customerProductID;
END

然后使用类似下面的东西来获取输出参数值:

public function addCustomerProduct($data) {
    $procedure = "CALL addCustomerProduct("
                   . $this->db->escape($data["customerID"]).", "
                   . $this->db->escape($data["productID"]).", "
                   . "@customerProductID);"
    $this->db->query($procedure);
    $query = $this->db->query("SELECT @customerProductID AS customerProductID");
    if($query->num_rows() > 0)
      return $query->result()->customerProductID;
    else
      return NULL;
}

如果上述方法不起作用,请尝试在存储过程调用前后添加$this->db->trans_start();$this->db->trans_complete();,以确保事务已提交。

【讨论】:

  • 我终于开始尝试这个,当我像上面那样设置我的 SP 和代码时,我得到了两个错误之一。首先,如果我只提供 2 ?,? 当它期望 3 时(一个用于 out),它会抛出一个错误,说明它们的参数数量不正确。如果我将第三个? 添加到呼叫中,我会收到You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?,?,?)' at line 1。在有交易和没有交易的情况下都试过了。
  • 好的,我对 Codeigniter 不是很熟悉(这就是我写“类似...”的原因)但现在已经根据this answer 修改了上面的代码。
【解决方案3】:

为什么

insert_id() 仅适用于 Query BuilderQueriesSP 用于调用$this->db->query(),但不会返回数据insert_id()


如何

在 SP 的末尾添加 SELECT MAX(id) FROM order_customer_product;。所以这会将最后一个 ID 返回到您的代码。


建议

正如我所见,有一个对 DB 的插入查询。如果我使用类似的情况,将使用普通的 Query Builder 或/并使用 Codeigniter Transactions(My answer on another question) 扭曲它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 2011-05-05
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多