I got a problem while executing my stored procedure in web service that I create in PHP language. If I execute the SP below directly in SQL Server Management Studio, it works perfectly. But when I execute the SP from my web service with PHP, it only executes some of the data in the looping I made in SP.
I got a service table as a master room data. In that SP below, I would like to check is the room available in a date range that I input to stored procedure one by one.
For example, I got 6 rooms in service table, and I want to check it one by one in looping with cursor. When I execute the SP in web service, it only execute 4 rooms in looping, but if I execute the SP in management studio directly, it works perfectly.
Can somebody help me to solve this problem?
Thank you.
Create Procedure GetAvailableRoom
#Date1 Datetime,
#Date2 Datetime,
#UserID Varchar(15)
AS
Begin
Delete From Room_Availability Where UserID = #UserID
Declare #KL Varchar(50)
Declare Cursor_RA Cursor For SELECT Service_Code FROM Services Where Status = 'ROOM' Order By Service_Code
Open Cursor_RA
Fetch Next From Cursor_RA Into #KL
While ##FETCH_STATUS = 0
Begin
print #KL
Declare #MyDate DateTime
Set #MyDate = #Date1
Declare #Diff Int
Set #Diff = DateDiff(Day, #Date1, #Date2)
Declare #Counter Int
Set #Counter = 0
print #MyDate
print #Diff
print #Counter
While (#Counter <= #Diff)
Begin
Print 'My Date is ' + Convert(Varchar, format(#MyDate,'yyyy-MM-dd'))
if exists(SELECT #KL, format(#MyDate,'yyyy-MM-dd 00:0:00'), Customers.Name + ' | ' + Customers.HP, #UserID
FROM Reservation INNER JOIN Reservation_Details ON Reservation.Reservation_Code = Reservation_Details.Reservation_Code
INNER JOIN Customers ON Reservation.Customer_ID = Customers.Customer_ID
WHERE Reservation_Details.Kode_Service = #KL AND
Reservation_Details.Checkin <= format(#MyDate,'yyyy-MM-dd 23:59:59') AND
Reservation_Details.Checkout >= format(#MyDate,'yyyy-MM-dd 00:0:00'))
Begin
print 'exists'
Insert Into Room_Availability (Service_Code,Service_Date,Customer,UserID)
SELECT #KL, format(#MyDate,'yyyy-MM-dd 00:0:00'), Customers.Name + ' | ' + Customers.HP, #UserID
FROM Reservation INNER JOIN Reservation_Details ON Reservation.Reservation_Code = Reservation_Details.Reservation_Code
INNER JOIN Customers ON Reservation.Customer_ID = Customers.Customer_ID
WHERE Reservation_Details.Service_Code = #KL AND
Reservation_Details.Checkin <= format(#MyDate,'yyyy-MM-dd 23:59:59') AND
Reservation_Details.Checkout >= format(#MyDate,'yyyy-MM-dd 00:0:00')
End
Else
Begin
print 'not exists'
Insert Into Room_Availability (Service_Code,Service_Date,Customer,UserID)
Values(#KL, format(#MyDate,'yyyy-MM-dd 00:0:00'), 'EMPTY', #UserID)
End
Set #MyDate = dateadd(dd,1,#MyDate)
Set #Counter = #Counter + 1
End
Fetch Next From Cursor_RA Into #KL
End
Close Cursor_RA
Deallocate Cursor_RA
End
This is the web service code.
<?php
include 'settings.php';
ini_set('mssql.connect_timeout',15);
$sqlconn = sqlsrv_connect($serverName, $connectionOptions);
if ($sqlconn === false)
die(FormatErrors(sqlsrv_errors()));
$tsql = "GetAvailableRoom '" . $_POST['Date1'] . "','" . $_POST['Date2'] . "','" . $_POST['UserID'] . "'";
//echo $tsql;
$cursorType = array("Scrollable" => SQLSRV_CURSOR_DYNAMIC);
$getexec = sqlsrv_query($sqlconn, $tsql, null, $cursorType);
if ($getexec === false)
die(FormatErrors(sqlsrv_errors()));
sqlsrv_free_stmt($getexec);
sqlsrv_close($sqlconn);
Related
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
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( )...
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.
I'm running a connection with PDO to a local MSSQL database. Running any Stored procedure at all through the connection doesn't give me any error at all.
This one single Stored procedure is giving me the following error:
Error in SQL: [Microsoft][SQL Server Native Client 10.0]Invalid cursor state - Query: exec sp_Get_SaldosWeb #Tipo=1, #IdDato=15368
This is my current PDO string for connecting inside this function and returning the array:
$query = $this->db->prepare($qry, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$final = $query->execute();
$this->setRows($query);
if(!$final) {
$this->error($qry, $query, $ret);
} else {
return $query->fetchAll();
}
I've tried closing the cursor both before the execute and after fetchAll like so:
$rows = $query->fetchAll();
$query->closeCursor();
return $rows;
But that also doesn't work. FYI, there are no queries executed before this call to this stored procedure anywhere in my code.
Not sure why this stored procedure is giving so many errors. If I run this exact same SP from MSSQL Management console it runs fine and returns 3 rows.
EDIT:
Here is the stored procedure:
USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[sp_Get_SaldosWeb]
#Tipo int , --1 = Alumno 2 = Familia
#IdDato int
as
if #Tipo = 1
begin
select SC_Alumno.Codigo ,
SC_Alumno.Nombres + ' ' + SC_Alumno.Apellidos as [Nombre],
SC_Moneda.Nombre as Moneda, upper(replace(replace(replace(replace(replace( replace(lower(SC_TipoCargo.Nombre),char(237),'i'), char(243),'o'), char(233),'e') , char(225),'a') ,char(250),'u'),char(241),'ñ')) as [Tipo de Cargo]
, cast(round(Sum(SC_CargoxAlumno.Debe),2) as decimal(18,2)) as Monto ,
SC_Alumno.Codigo as Codigo2
from SC_CargoxAlumno
inner join SC_Moneda on SC_CargoxAlumno.IdSC_Moneda = SC_Moneda.IdSC_Moneda
inner join SC_TipoCargo on SC_CargoxAlumno.IdSC_TipoCargo = SC_TipoCargo.IdSC_TipoCargo
inner join SC_Alumno on SC_Alumno.IdSC_Alumno = SC_CargoxAlumno.IdSC_Alumno
inner join SC_Familia on SC_Alumno.IdSC_Familia = SC_Familia.IdSC_Familia
where
SC_Alumno.IdSC_Alumno = #IdDato
and SC_CargoxAlumno.Debe <> 0
group by
SC_Alumno.Codigo ,
SC_Alumno.Nombres + ' ' + SC_Alumno.Apellidos ,
SC_Moneda.Nombre , SC_TipoCargo.Nombre
end
else
begin
select SC_Alumno.Codigo ,
SC_Alumno.Nombres + ' ' + SC_Alumno.Apellidos as [Nombre],
SC_Moneda.Nombre as Moneda, upper(replace(replace(replace(replace(replace( replace(lower(SC_TipoCargo.Nombre),char(237),'i'), char(243),'o'), char(233),'e') , char(225),'a') ,char(250),'u'),char(241),'ñ')) as [Tipo de Cargo] ,
cast(round(Sum(SC_CargoxAlumno.Debe),2) as decimal(18,2)) as Monto ,
SC_Alumno.Codigo as Codigo2
from SC_CargoxAlumno
inner join SC_Moneda on SC_CargoxAlumno.IdSC_Moneda = SC_Moneda.IdSC_Moneda
inner join SC_TipoCargo on SC_CargoxAlumno.IdSC_TipoCargo = SC_TipoCargo.IdSC_TipoCargo
inner join SC_Alumno on SC_Alumno.IdSC_Alumno = SC_CargoxAlumno.IdSC_Alumno
inner join SC_Familia on SC_Alumno.IdSC_Familia = SC_Familia.IdSC_Familia
where
SC_Familia.IdSC_Familia = #IdDato
and SC_CargoxAlumno.Debe <> 0
group by
SC_Alumno.Codigo ,
SC_Alumno.Nombres + ' ' + SC_Alumno.Apellidos ,
SC_Moneda.Nombre , SC_TipoCargo.Nombre
end
Add "SET NOCOUNT ON" to the beginning of your procedure.
You might find references here :
PHP Data Objects
My stored procedure "best practices" checklist
i trie to execute a Stored Procedure from PHP. My other SP´s are working correctly. But this one will make problems.
Here is my code for calling the SP:
$sqlStmt = "EXEC MOBILE_CSKLIENT_LoadForSync #pCEGERAETNR = ?";
$con = DatabaseManager::GetDatabaseConnection($serial);
$deviceNr = $this->GetDeviceNr($serial, $deviceId);
$res = sqlsrv_query($con, $sqlStmt, array($deviceNr));
if($res == false)
{
die( print_r( sqlsrv_errors(), true));
}
else
{
die( print_r( sqlsrv_errors(), true));
$result = array();
while($zeile = sqlsrv_fetch($res))
{
echo sqlsrv_get_field($res, 0);
}
}
here is my SP:
GO
/****** Object: StoredProcedure [dbo].[MOBILE_CSKLIENT_LoadForSync] Script Date: 25.02.2014 08:36:01 ******/
ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[MOBILE_CSKLIENT_LoadForSync](#pCEGERAETNR FLOAT)
AS
BEGIN
DECLARE #pLASTCHANGE datetime
SET #pLASTCHANGE = (SELECT MAX(LASTCHANGE) FROM CEMITARB WHERE CEGERAETNR = #pCEGERAETNR)
IF #pLASTCHANGE IS NULL
BEGIN
SELECT K.KLIENTNR, K.PROGRAMMNR, K.NAME,
K.VORNAME, K.[STR], K.PLZ, K.ORT , K.TELEFON1, K.TELEFON2, K.GEBDAT, K.GESCHLECHT, K.KEYKLIFR1, K.MAINVERSION
FROM CSKLIENT K
INNER JOIN S1PAT P ON P.KLIENTNR = K.KLIENTNR
INNER JOIN CSKLIZR Z ON Z.KLIENTNR = K.KLIENTNR
WHERE P.AKTIV = 'J'
AND (Z.AUFNAHME IS NULL OR Z.AUFNAHME <= GetDate())
AND (Z.ENTLASSUNG IS NULL OR Z.ENTLASSUNG >= GetDate())
UNION
SELECT K.KLIENTNR, K.PROGRAMMNR, K.NAME,
K.VORNAME, K.[STR], K.PLZ, K.ORT , K.TELEFON1, K.TELEFON2, K.GEBDAT, K.GESCHLECHT, K.KEYKLIFR1, K.MAINVERSION
FROM CSKLIENT K
INNER JOIN H1BEW B ON B.KLIENTNR = K.KLIENTNR
WHERE B.AKTIV = 'J' AND ZIMMER IS NOT NULL AND BEREICH IS NOT NULL
END
ELSE
BEGIN
SELECT K.KLIENTNR, K.PROGRAMMNR, K.NAME,
K.VORNAME, K.[STR], K.PLZ, K.ORT , K.TELEFON1, K.TELEFON2, K.GEBDAT, K.GESCHLECHT, K.KEYKLIFR1, K.MAINVERSION
FROM CSKLIENT K
INNER JOIN S1PAT P ON P.KLIENTNR = K.KLIENTNR
INNER JOIN CSKLIZR Z ON Z.KLIENTNR = K.KLIENTNR
WHERE P.AKTIV = 'J' AND K.LASTCHANGE >= #pLASTCHANGE
AND (Z.AUFNAHME IS NULL OR Z.AUFNAHME <= GetDate())
AND (Z.ENTLASSUNG IS NULL OR Z.ENTLASSUNG >= GetDate())
UNION
SELECT K.KLIENTNR, K.PROGRAMMNR, K.NAME,
K.VORNAME, K.[STR], K.PLZ, K.ORT , K.TELEFON1, K.TELEFON2, K.GEBDAT, K.GESCHLECHT, K.KEYKLIFR1, K.MAINVERSION
FROM CSKLIENT K
INNER JOIN H1BEW B ON B.KLIENTNR = K.KLIENTNR
WHERE B.AKTIV = 'J' AND ZIMMER IS NOT NULL AND BEREICH IS NOT NULL
AND K.LASTCHANGE >= #pLASTCHANGE
END
END
So i now get the Error:
Error: [Microsoft][SQL Server Native Client 10.0][SQL Server]Warnung: Ein NULL-Wert wird durch einen Aggregat- oder sonstigen SET-Vorgang gel\224scht.
Translatet to English:
A Null value will be delete by a aggregat or a set action
My Procedure works fine if i execute it from the SQL Management Studio.
The Procedure should return 222 rows.
I tried to set:
sqlsrv_configure("WarningsReturnAsErrors", 0);
But then nothing was returned from the Procedure.
i found the solution:
the problem was this line in my SP:
SET #pLASTCHANGE = (SELECT MAX(LASTCHANGE) FROM CEMITARB WHERE CEGERAETNR = #pCEGERAETNR)
LastChange can be Null and this was the problem.
So i changed the code to:
IF((SELECT DISTICT LASTCHANGE FROM CEMITARB WHERE CEGERAETNR = #pCEGERAETNR) IS NULL)
BEGIN
SET #pLASTCHANGE = NULL
END
ELSE
BEGIN
SET #pLASTCHANGE = (SELECT MAX(LASTCHANGE) FROM CEMITARB WHERE CEGERAETNR = #pCEGERAETNR)
END
Now my code executes fine. And sqlsrv_query returns the correct items.