MySQL Stored Procedure Empty in PHP works in PHPMyAdmin - php

I have the following stored procedure. It works fine in phpMyAdmin, but when I try to run it using PHP PDO library I get no errors, just an empty array.
CREATE DEFINER=`root`#`localhost`
PROCEDURE `get_gauge_values`(IN `maxdate` TIMESTAMP,
IN `dashboard_id` INT)
begin
DECLARE finished BOOLEAN;
DECLARE line_timestamp TIMESTAMP;
DECLARE line_tagid INT;
DECLARE line_name VARCHAR(50);
DECLARE line_value VARCHAR(50);
DECLARE cid CURSOR FOR
SELECT Max(hd.timestamp),
hd.tag_id
FROM dashboard_to_dashboard_lines ddl
JOIN dashboard_lines dl
ON dl.line_id = ddl.dashboard_line_id
JOIN historical_data hd
ON hd.tag_id = dl.gauge_tag_id
WHERE hd.timestamp <= maxdate
AND ( dashboard_id = 0
OR ddl.dashboard_id = dashboard_id )
GROUP BY 2;
DECLARE CONTINUE handler
FOR NOT found
SET finished=TRUE;
SET finished=FALSE;
DROP TABLE IF EXISTS gauge_values_temp;
CREATE TABLE gauge_values_temp
(
name VARCHAR(255),
value VARCHAR(50)
);
open cid;
START_LOOP:
LOOP
FETCH cid INTO line_timestamp, line_tagid;
IF finished <> false THEN
LEAVE start_loop;
ELSE
INSERT INTO gauge_values_temp
(name,
value)
SELECT ol.name,
hd.value
FROM dashboard_lines dl
JOIN operation_lines ol
ON ol.line_id = dl.line_id
JOIN historical_data hd
ON hd.tag_id = dl.gauge_tag_id
WHERE dl.gauge_tag_id = line_tagid
AND hd.timestamp = line_timestamp;
end IF;
end LOOP;
close cid;
SELECT *
FROM gauge_values_temp;
end
The code that I use in PHP for trying to pull data back is the following:
try {
$sql = "CALL get_gauge_values('2015-12-28 09:00:00','1')";
$q = $link->query($sql);
$q->setFetchMode(PDO::FETCH_ASSOC);
} catch (PDOException $pe) {
die("Error occurred:" . $pe->getMessage());
}
while ($r = $q->fetch()) {
echo 'Row returned<br />';
}
exit;
I'm confused as to why it returns the result set in phpMyAdmin but running it with the PHP code below in a browser returns 0 rows. All I get when I print_r($q) is Array( )...

Related

Is it possible to pass multiple input values in stored procedure parameter?

I am working on a fantasy baseball optimizer and I have a stored procedure where when the user selects players it will return the best possible player, but the problem is, the sp only does it for one player at a time. I wanted to know if there was a way the sp could do it for at most nine players at one time.
Visual Reference
Here's the code for the stored procedure:
DELIMITER $$
CREATE DEFINER=`u998875936_chri`#`%` PROCEDURE `Optimizer9`(
PlayerName varchar(30),
PlayerPosition varchar(2),
PlayerSalary int,
PlayerFPPG Numeric (20,17),
CapRemaining int,
OUT ReturnPlayerName varchar(30),
OUT ReturnCap int
)
BEGIN
Declare Count int;
Declare lclSal int;
Declare lclPlayerName varchar(30);
Declare lclReturnPlayerName varchar(30);
Declare lclCap int;
Set lclPlayerName='';
Set lclReturnPlayerName='';
Set lclSal=0;
Set lclCap = CapRemaining;
Set Count=0;
create temporary Table IF NOT EXISTS TempPlayer9(
Player varchar(30),
Pos varchar(2),
Sal int,
Points Numeric (20,17)
);
Insert into TempPlayer9 (Player,Pos,Sal,Points)
SELECT Nickname
,Position
,Salary
,FPPG
FROM playerList
WHERE POSITION = PlayerPosition
and FPPG > PlayerFPPG
order by FPPG DESC;
Set Count=(Select Count(*) from TempPlayer9);
While Count > 0
DO
Set lclPlayerName=(Select Player from TempPlayer9 LIMIT 1);
Set lclSal=(Select Sal from TempPlayer9 LIMIT 1);
IF (lclsal- PlayerSalary) < lclCap
THEN
Set lclCap = lclCap - (lclSal- PlayerSalary);
Set lclReturnPlayerName = lclPlayerName;
Set Count=0;
DELETE from TempPlayer9 Where Player = lclPlayerName;
Set Count=Count-1 ;
END IF;
END WHILE;
Set ReturnPlayerName = lclReturnPlayerName;
Set ReturnCap = lclCap;
END$$
DELIMITER ;
PHP Code:
<?php
$remain=35000;
$player= $_POST['player'];
$pos= $_POST['pos'];
$sal= $_POST['sal'];
$points= $_POST['fppg'];
$cap= $remain-$sal;
$sql = $mysqli->query("call Optimizer11('$player', '$pos','$sal' , '$points', '$cap', #ReturnPlayerName, #ReturnCap)");
$results = $mysqli->query ("select #ReturnPlayerName as Player,#ReturnCap AS SalRemaining");
$rows = mysqli_fetch_array($results);
print_r($rows);
?>

Calling from PHP Stored Procedure with Cursor and Union SQL Doesn't Show All Data

I Create a stored procedure that execute perfectly in MYSQL but when I call it from PHP it only show the data that correspond to the first data of the cursor.
Here is how I call the stored procedure :
$sql = mysqli_query($db, "CALL MySP('".$ec4."')");
Here is how I retrieve the data:
while ($ligne = mysqli_fetch_array($sql))
Thank you
Stored procedure data
php calling
while ($ligne = mysqli_fetch_array($sql)) {
echo '</br>';
echo '</br>'.$ligne["Agences"].'</br>';
echo '</br>'.$ligne["date_op"].'</br>';
echo '</br>'.$ligne["arrivee"].'</br>';
}
Here is my Stored Procedure :
DELIMITER $
CREATE PROCEDURE `MySP`( date_op VARCHAR(10) )
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE ville_agence VARCHAR(50);
DECLARE cursor_i CURSOR FOR SELECT ville FROM villes;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO ville_agence;
IF done THEN
LEAVE read_loop;
END IF;
SELECT
Agences,
date_op,
(select Villes from grille a where a.Nom = b.Nom_de_Depart and a.`Type` ='A' LIMIT 1) as arrivee
FROM
grille b
where
b.`Type` = 'T'
and upper(Agences) in (ville_agence)
UNION
SELECT
Agences,
date_op,
(select Agences from grille a where a.Code = b.Code and a.`Type` = 'D' LIMIT 1) as arrivee
FROM
grille b
where b.`Type` = 'A'
and upper(Agences) in (ville_agence);
END LOOP;
CLOSE cursor_i;
END

Convert Mysql procedure into PHP code

I have a stored procedure on my Mysql DB, but i need to change it to get it done by PHP.
I've been looking around here and i know that is possible to make a SP from PHP, but it requires Mysqli (i don't have it updated, and updating it is not possible for personal reasons) or at least that was the only way i found to do it (source).
So for me that only have Mysql, it's possible to do it from php? or should i just "translate" the procedure into PHP format? I mean not making a procedure but a function instead (php function), that actually do the same with PHP code (loops, selects, calls and so) but not storing the procedure on the DB.
This is my procedure
DELIMITER //
create procedure autor_products (in id int)
begin
update authors set authors_products=
(SELECT DISTINCT count(products_id)
FROM products
INNER JOIN authors_to_manufacturers as am ON am.manufacturers_id = products.manufacturers_id
WHERE authors_id = id)
WHERE manufacturers_id = id;
end
//
DELIMITER $$
CREATE PROCEDURE authors()
BEGIN
DECLARE a INT Default 0 ;
DECLARE manu_length int;
select max(manufacturers_id) into manu_length from authors;
simple_loop: LOOP
SET a=a+1;
call autor_products(a);
IF a >= manu_length THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
END $$
DELIMITER ;
commit;
I managed to do this, which is "working" for at least one update
<?php
require('includes/configure.php'); //To get the DB name, user and pass
require_once (DIR_FS_INC.'xtc_db_connect.inc.php'); //I use this to connect the DB
$conn = xtc_db_connect() or die('Unable to connect to database server!');
$manu_lenght="select max(manufacturers_id) from authors;";
for ($i = 0;$i<=$manu_lenght;$i++){ //"for" not in use nor not working if i replace 1 for $i
$update= " update authors set products_amount = (SELECT DISTINCT count(products_id)
FROM products
INNER JOIN authors_to_manufacturers as am ON am.manufacturers_id = products.manufacturers_id
WHERE authors_id = 1)
WHERE manufacturers_id = 1;";
} //will only update 1 author with authors_id = 1 so i needed to make a loop, but if i replace 1 for $i. it doesn't update at all
$retval = mysql_query( $update, $conn );
if(! $retval )
{
die('Could not update data: ' . mysql_error());
}
echo "Updated data successfully\n";
?>
How may i use the $i variable instead of a specific number? (so it would update all at once because of the loop)
Edit: My manu_lenght is not working (it doesn't show the result of the select) but i just changed that part into a number and it's still not working, any thoughts?
Edit 2: Why is this code not working? It works if it's only $a=1; but not if i loop or make a bucle of $a.
$a = 1;
do{
$update= " update authors set products_amount = (SELECT DISTINCT count(products_id)
FROM products
INNER JOIN authors_to_manufacturers as am ON am.manufacturers_id = products.manufacturers_id
WHERE authors_id =$a)
WHERE manufacturers_id =$a;";
echo $a;
$a++;
}
while($a <= 10);
What im doing wrong?
After several tries i got what i need.
This is my code:
<?php
require('includes/configure.php');
require_once (DIR_FS_INC.'xtc_db_connect.inc.php');
$conn = xtc_db_connect() or die('Unable to connect to database server!');
//getting the total amount of authors into $manu_lenght variable
$manu_lenght = mysql_query("select max(manufacturers_id) as sum from authors;" );
if(!$manu_lenght){
die("DB query failed : " . mysql_error());
$sum = "";
} //needed to fetch the result of the select query
while ( $result = mysql_fetch_assoc($manu_lenght)){
$sum = $result["sum"];
}
do{
$author_update= " update authors set products_amount = (SELECT DISTINCT count(products_id)
FROM products
INNER JOIN authors_to_manufacturers as am ON am.manufacturers_id = products.manufacturers_id
WHERE authors_id =$a)
WHERE manufacturers_id =$a;";
$a++;
//while was here, so that's why it wasn't working
$ret_author = mysql_query( $author_update, $conn );
}
while($a <= $sum); //now is correct, it sends the query now
if(!$ret_author )
{
die('Could not update data: ' . mysql_error());
}
echo "Updated authors successfully\n";
?>
What i was basically doing wrong is ending the loop too early, and not letting the mysql_query function send the query (update in this case)
Instead of calling the procedure, i did the procedure translation through PHP. Hope this is useful for anyone else.

php Num rows of stored procedure MySQL

I have a stored procedure in MySQL. I call my procedure in php as
$qry = $mysqli->prepare("CALL seen_table()");
i tried to get the resulting rows by
$row = $qry->num-rows;
but its resulting 0 even there is a resulting set.Then I tried also to put output parameter in my procedure where in inside of my proc is ...
SELECT COUNT(*) INTO cnt FROM TBL
...then this is my codes
$qry = $mysqli->prepare("CALL seen_table(#cnt)");
$qry1 = $mysqli->query("SELECT #cnt");
$row = $qry1->num_rows;
then now its always results 1 even there is no count. when i try to execute CALL and SELECT #cnt in Mysql . if there is no count. the result will be
|#cnt|
|(null)|
does null really count as one?please help. thanks a lot.
EDIT: Added seen_table Procedure codes
DELIMITER $$
USE `xiroosco_mundoxiro`$$
DROP PROCEDURE IF EXISTS `seen_table`$$
CREATE DEFINER=`xiroosco`#`103.16.170.%` PROCEDURE `seen_table`(bound
VARCHAR(255),IN cmntId INT,IN cmntViewID VARCHAR(255),OUT viewCNT INT)
BEGIN
DECLARE seen_ID INT DEFAULT 0;
DECLARE seen_notifica_ID INT DEFAULT 0;
DECLARE seen_viewers TEXT;
DECLARE occurance INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE splitted_value INT;
DECLARE done INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT seen.seen_ID, seen.seen_notifica_ID,
seen.seen_viewers
FROM seen
WHERE seen.seen_notifica_ID = cmntId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS seen2;
CREATE TEMPORARY TABLE seen2(
`seen_ID` INT NOT NULL,
`seen_notifica_ID` INT NOT NULL,
`seen_viewers` VARCHAR(255) NOT NULL
) ENGINE=MEMORY;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO seen_ID,seen_notifica_ID, seen_viewers;
IF done THEN
LEAVE read_loop;
END IF;
SET occurance = (SELECT LENGTH(seen_viewers) -
LENGTH(REPLACE(seen_viewers, bound, '')) +1);
SET i=1;
WHILE i <= occurance DO
SET splitted_value = (SELECT
REPLACE(SUBSTRING(SUBSTRING_INDEX(seen_viewers, bound, i),
LENGTH(SUBSTRING_INDEX(seen_viewers, bound, i - 1)) + 1), ',', ''));
INSERT INTO seen2 VALUES (seen_ID,seen_notifica_ID, splitted_value);
SET i = i + 1;
END WHILE;
END LOOP;
IF cmntViewID = "*" THEN
SELECT * FROM seen2 GROUP BY seen2.seen_viewers;
SELECT COUNT(*) INTO viewCNT FROM seen2;
ELSE
SELECT * FROM seen2 WHERE seen2.seen_viewers = cmntViewID GROUP BY
seen2.seen_viewers;
SELECT seen_ID INTO viewCNT FROM seen2 WHERE seen2.seen_viewers =
cmntViewID GROUP BY seen2.seen_viewers;
END IF;
CLOSE cur1;
END$$
DELIMITER ;
this is how i call my procedure example
CALL seen_table (',',2995,'356',#count);
NULL counts as one, but as far as I can see it is against the ANSI standard: If there are not results, there should also be no NULL returned.
To get a row count returned from a procedure (or any result set) in MySQL, there are information functions.
I do not know which select you want to return the count, so just giving you an example:
{your procedure before this part}
IF cmntViewID = "*" THEN
SELECT SQL_CALC_FOUND_ROWS * FROM seen2 GROUP BY seen2.seen_viewers;
SELECT COUNT(*) INTO viewCNT FROM seen2;
ELSE
SELECT * FROM seen2 WHERE seen2.seen_viewers = cmntViewID GROUP BY
seen2.seen_viewers;
SELECT seen_ID INTO viewCNT FROM seen2 WHERE seen2.seen_viewers =
cmntViewID GROUP BY seen2.seen_viewers;
END IF;
{your procedure after this part}
Then execute:
CALL seen_table();
SELECT FOUND_ROWS();
That will return the number of rows in the "SELECT SQL_CALC_FOUND_ROWS * FROM seen2 GROUP BY seen2.seen_viewers;" query.

Echoing out a field and a value from one row while running a query that ranks all rows

I have a MySQL query called $sqlStr5 that ranks rows by a metric called totalScore2. One of the fields that $sqlStr5 returns is called username.
I would like to echo out the rank and the value of totalScore2 where username equals a variable called $u.
How can I do this?
Below is what I have so far.
Thanks in advance,
John
$result = mysql_query($sqlStr5);
$count = 1;
$arr = array();
while ($row = mysql_fetch_array($result)) {
echo '<div class="sitename1edit2a">'.$count++.'.</div>';
echo '<div class="sitename1edit2">'.number_format(($row["totalScore2"])).'</div>';
}
This should work:
$result = mysql_query($sqlStr5);
$count = 1;
while($row = mysql_fetch_array($result))
{
if($u == $row['username'])
{
echo '<div class="sitename1edit2a">'.$count.'</div>';
echo '<div class="sitename1edit2">'.number_format($row["totalScore2"]).'</div>';
}
$count++;
}
Note however that this is not the most efficient way. It should be possible to make a SQL query that returns the rank and the total score for user $u.
The following solution uses a stored procedure to work out a user's rank based on a simple ranking system which you could replace with your own more complex one.
call get_user_rank(<user_id>)
I've added another stored procedure which lists the top ten ranks and flags whether the user_id passed in is included in the top ten as I remember that being a requirement from another question of yours.
call list_top_ten_ranks(<user_id>)
Testing (call these sprocs from your php)
select count(*) from users;
count(*)
========
250000
call get_user_rank(54193);
-- 0:00:00.300: Query OK
call get_user_rank(1);
-- 0:00:00.291: Query OK
call list_top_ten_ranks(54193);
-- 0:00:00.208: Query OK
call list_top_ten_ranks(1);
-- 0:00:00.215: Query OK
PHP
$result = $conn->query(sprintf("call get_user_rank(%d)", 1));
$row = $result->fetch_assoc();
$result->close();
echo sprintf("user = %s rank = %s points = %s<br/>",
$row["user_id"],$row["rank"],$row["points"]);
$conn->close();
Hope some of this proves useful.
Script
-- TABLES
drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
points smallint unsigned not null default 0
)
engine=innodb;
-- PROCEDURES
drop procedure if exists get_user_rank;
delimiter #
create procedure get_user_rank
(
p_user_id int unsigned
)
proc_main:begin
-- replace this simple ranking method by your own
set #rank = 0;
create temporary table tmp engine=memory
select
#rank:=#rank+1 as rank,
u.user_id,
u.points
from
users u
order by
u.points desc, u.user_id;
select * from tmp where user_id = p_user_id;
drop temporary table if exists tmp;
end proc_main #
delimiter ;
drop procedure if exists list_top_ten_ranks;
delimiter #
create procedure list_top_ten_ranks
(
p_user_id int unsigned
)
proc_main:begin
-- replace this simple ranking method by your own
set #rank = 0;
set #in_top_ten = 0;
create temporary table tmp engine=memory
select
#rank:=#rank+1 as rank,
u.user_id,
u.points
from
users u
order by
u.points desc, u.user_id
limit 10;
if exists (select 1 from tmp where user_id = p_user_id) then
set #in_top_ten = 1;
end if;
select tmp.*, #in_top_ten as in_top_ten from tmp order by tmp.rank;
drop temporary table if exists tmp;
end proc_main #
delimiter ;

Categories