我正在努力在另一个存储过程中调用存储过程。就像现在一样,存储过程永远不会将SELECT语句返回到PHP中的mysqli调用(但它在MySQL工作台中工作正常)。
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `new_bid`(IN bid_in decimal(6,2),
IN ticker_in varchar(5),
IN share_amount_in BIGINT)
BEGIN
DECLARE company_id_var INT;
DECLARE highest_bid BIT;
DECLARE generated_bid_id BIGINT;
SET company_id_var = (SELECT ID
FROM Companies
WHERE Ticker = ticker_in);
-- Put the bid into the Bids table.
INSERT INTO Bids(company_id,bid,share_amount)
VALUES (company_id_var,bid_in,share_amount_in);
SET generated_bid_id = LAST_INSERT_ID();
CALL check_available_shares(bid_in,share_amount_in,generated_bid_id,@shares_left);
-- Check if the bid is higher than the current highest bid.
-- If so update the CurrentState table to have the new value.
UPDATE CurrentState SET buyer = bid_in
WHERE ID = company_id_var
AND buyer < bid_in;
IF (ROW_COUNT() = 1)
THEN
SELECT 1 AS highest_bid, @shares_left AS shares_left, CS.buyer, CS.seller, CS.last_price, CO.name, CO.ticker
FROM CurrentState CS, Companies CO
WHERE CS.id = CO.id
AND CO.ticker = ticker_in;
ELSE
SELECT 0 AS highest_bid, @shares_left AS shares_left, CS.buyer, CS.seller, CS.last_price, CO.name, CO.ticker
FROM CurrentState CS, Companies CO
WHERE CS.id = CO.id
AND CO.ticker = ticker_in;
END IF;
END
如果我删除&#34; CALL&#34;函数从这个存储过程返回底部的一个SELECT语句,但如果我保持&#34; CALL&#34;功能它不会返回任何东西。 我尝试过exec和execute但是当我尝试在MySQL工作台中保存程序时,这只会给我语法错误。此问题与https://stackoverflow.com/questions/23193085/mysqli-does-not-return-any-results-but-stored-procedure-does有关。 但似乎这个问题可能与mysqli如何处理存储过程的执行有关,因为当我在mySQL工作台中手动调用存储过程时它工作正常(?)
答案 0 :(得分:0)
在我的头撞墙后几个小时,我找到了一个解决方案。由于此存储过程调用另一个使用游标的存储过程,因此我必须使用$mysqli->multi_query()
函数。以下是我如何运作:
new_bid存储过程:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `new_bid`(IN bid_in decimal(6,2),
IN ticker_in varchar(5),
IN share_amount_in BIGINT)
BEGIN
-- Store the company ID into a variable as this value will used more than once.
DECLARE company_id_var INT;
DECLARE ParamtoPass INT;
DECLARE highest_bid BIT;
DECLARE generated_bid_id BIGINT;
SET company_id_var = (SELECT ID
FROM Companies
WHERE Ticker = ticker_in);
-- Put the bid into the Bids table.
INSERT INTO Bids(company_id,bid,share_amount)
VALUES (company_id_var,bid_in,share_amount_in);
SET generated_bid_id = LAST_INSERT_ID();
-- EXECUTE check_available_shares bid_in, @share_amount_in,@generated_bid_id,@shares_left;
CALL check_available_shares (bid_in,@share_amount_in,generated_bid_id,@shares_left);
-- Check if the bid is higher than the current highest bid.
-- If so update the CurrentState table to have the new value.
UPDATE CurrentState SET buyer = bid_in
WHERE ID = company_id_var
AND buyer < bid_in;
IF (ROW_COUNT() = 1)
THEN
SELECT 1 AS highest_bid, @shares_left AS shares_left, CS.buyer, CS.seller, CS.last_price, CO.name, CO.ticker
FROM CurrentState CS, Companies CO
WHERE CS.id = CO.id
AND CO.ticker = ticker_in;
ELSE
SELECT 0 AS highest_bid, @shares_left AS shares_left, CS.buyer, CS.seller, CS.last_price, CO.name, CO.ticker
FROM CurrentState CS, Companies CO
WHERE CS.id = CO.id
AND CO.ticker = ticker_in;
END IF;
END
check_available_shares程序:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `check_available_shares`(IN bid_in decimal(6,2),
IN share_amount_in int,
IN bid_id bigint,
OUT shares_left BIT)
BEGIN
DECLARE num_shares INT;
DECLARE selling_id INT;
DECLARE selling_price DECIMAL(6,2);
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR SELECT share_amount,sell_price,ID
FROM ShareSell
WHERE sell_price <= bid_in
ORDER BY sell_price ASC, sell_timestamp ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur; /* open cursor */
read_loop: LOOP
FETCH NEXT FROM cur
INTO num_shares, selling_price, selling_id;
IF (done) THEN
LEAVE read_loop;
END IF;
IF ((share_amount_in - num_shares) > 0) THEN
SET share_amount_in = (share_amount_in - num_shares);
DELETE FROM ShareSell
WHERE ID = selling_id;
ELSEIF((share_amount_in - num_shares) < 0) THEN
UPDATE ShareSell
SET share_amount = (share_amount - share_amount_in)
WHERE ID = selling_id;
DELETE FROM Bids
WHERE ID = bid_id;
LEAVE read_loop;
ELSE
DELETE FROM ShareSell
WHERE ID = selling_id;
DELETE FROM Bids
WHERE ID = bid_id;
END IF;
SELECT num_shares,selling_price;
END LOOP;
CLOSE cur;
IF (share_amount_in > 0) THEN
UPDATE Bids
SET share_amount = share_amount_in
WHERE ID = bid_id;
SET shares_left = 1;
ELSE
SET shares_left = 0;
END IF;
END
最后是PHP调用:
$bid = 43.10;
$ticker = "GOS";
$share_amount = 1000;
if ($mysqli->multi_query("CALL new_bid($bid,'$ticker',$share_amount)"))
{
if ($result = $mysqli->store_result())
{
while ($row = $result->fetch_assoc())
{
print_r($row);
}
$result->close();
}
}
答案 1 :(得分:0)
谢谢!这也是我的问题。我也遇到了一个完全类似的问题(见PHP mysqli is NOT trapping some errors when calling stored procedure)。您的帖子帮助我解决了我的问题!
我也有一个用PHP调用SP1的案例,后者又称为SP2,并且一切在mysql客户端中都可以正常工作,但是在被PHP调用时会中断!确实,我在SP2中也有一个结果集的SELECT。而且我的问题症状与您的症状完全相同,并且使用multi_query()
从未使我感到震惊。
我注意到您还选择了check_available_shares
中的一个“结果集*”(请参阅第SELECT num_shares,selling_price;
行)。不确定为什么有此行。如果删除该行,我怀疑您应该能够做一个query()
而不是multi_query()
。