I have a very simple query, not sure what I am doing wrong here.
My DB call is not receiving an insert id
as I would expect it to.
Table:
Stored Procedure:
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();
}
The line with the issue is: $customerProductID = $this->addCustomerProduct($data);
.
A new record is being inserted into the table and the table has a PK/AI
. Data goes in fine but 0
is returned as the $customerProductID
.
Will an insert from select statement not return an insert ID
perhaps?
Update For @Ravi-
Update 2:
I created a separate method and hard coded the query and data being sent.
It adds the records fine, AI goes up, 0
is returned as the last id
.
public function test(){
$procedure = "CALL addCustomerProduct(?,?)";
$result = $this->db->query($procedure, array("customerID" => 1, "productID" => 20));
echo $this->db->insert_id();
}
Also restarted the MySQL server to make sure there wasn't anything weird going on there.
Also, updated the SP to just insert random data into the table without using a select.
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
Update 3:
Right after the insert, I am printing out the last query that was ran as well as the result. You will notice that there is 1 affected row (the insert is happening) but the insert_id
is still 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] =>
)
Update 4:
From some of the research I have done, unless you use the mysqli method such as $this->db->insert()
, it won't provide a last insert id back to you.
I am going to try and figure out Ravi's suggestion but it seems that code igniter doesn't allow the example that was shown. At least I know now that I am not crazy and its just not normal behavior unless you use the ``insert` method vs a stored procedure.
If you are AUTO_INCREMENT with column, then you can use last_insert_id() method. This method gets the ID of the last inserted record in MySQL. Insert some records in the table using insert command.
If you insert multiple rows into the table using a single INSERT statement, the LAST_INSERT_ID() function returns the first automatically generated value only. If the insertion fails, the result returned by the LAST_INSERT_ID() remain unchanged. The LAST_INSERT_ID() function works based on client-independent principle.
MySQL INSERT statement is used to insert record(s) or row(s) into a table. The insertion of records or rows in the table can be done in two ways, insert a single row at a time, and insert multiple rows at a time.
Description ¶Returns the ID generated by an INSERT or UPDATE query on a table with a column having the AUTO_INCREMENT attribute. In the case of a multiple-row INSERT statement, it returns the first automatically generated value that was successfully inserted.
This answer may explain why your existing code doesn't work. To quote:
CodeIgniter's
insert_id()
will only return an ID of aninsert()
. Unless you are executing something like$this->db->insert('table', $data);
before calling the function it will not be able to return an ID.
MySQL's LAST_INSERT_ID();
should help you here (assuming you have permission to alter the stored procedure definition). Change it to:
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
Then use something like the following to get the output parameter value:
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;
}
If the above doesn't work, try adding a $this->db->trans_start();
and $this->db->trans_complete();
before and after the stored procedure call to ensure the transaction is committed.
Ideally, following line should work
$this->db->insert_id;
But, I'm not sure why is not working, so I would suggest a workaround as following, recompile your procedure with additional parameter out_lastId
, which will return last inserted id
CREATE DEFINER=`root`@`localhost` PROCEDURE `addCustomerProduct`(IN in_customerID INT, in_productID INT, OUT out_lastId INT)
And, after insert set the value with last inserted id.
SET out_lastId = LAST_INSERT_ID();
==Updated==
$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();
Why
insert_id()
will only workes with Query Builder and Queries only. SP's are used to call with $this->db->query()
but it won't retuns data insert_id()
.
How
Before the End of SP add SELECT MAX(id) FROM order_customer_product;
. So this will return the last ID to your code.
Suggestion
As I see there is an Insert query to DB. If I use similar case will use normal Query Builder or/and will warp it with Codeigniter Transactions(My answer on another question).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With