The SQL guy wrote a stored procedure that is suppose to return a list of item that'd be affected by the request.
If I call the stored procedure within SQL Server Management Studio like the example below, I can see the list in a column named after the alias
DECLARE #RETURN_CLIENTS_SET nvarchar(max)
EXEC [dbo].[Sp_IHM_SET_FORMS_INDPROD_CLOSE_DATE]
#Date = N'20171110',
#RETURN_ITEMS = #RETURN_ITEMS OUTPUT
SELECT #RETURN_ITEMS as N'#RETURN_ITEMS'
Now, If I try to show the result via a PHP like I'd do for a simple table fetch
$query_setdata = "DECLARE #RETURN_CLIENTS_SET nvarchar(max)
EXEC [dbo].[Sp_IHM_SET_FORMS_INDPROD_CLOSE_DATE]
#Date = N'20171110',
#RETURN_ITEMS = #RETURN_ITEMS OUTPUT
SELECT #RETURN_ITEMS as N'#RETURN_ITEMS'";
$prep_setdata = sqlsrv_prepare($conn, $query_setdata);
if(sqlsrv_execute($prep_setdata))
{
while($data = sqlsrv_fetch_array($prep_setdata,SQLSRV_FETCH_ASSOC)) {
echo $data['#RETURN_ITEMS'];
}
}
else {
die(print_r( sqlsrv_errors(), true));
}
The stored procedure does its stuff in the database (changing some flags for certain items), I have no error, but it doesn't show the "RETURN_ITEMS" value
Try a batch like this:
SET NOCOUNT ON;
DECLARE #RETURN_ITEMS nvarchar(max);
EXEC [dbo].[Sp_IHM_SET_FORMS_INDPROD_CLOSE_DATE]
#Date = N'20171110',
#RETURN_ITEMS = #RETURN_ITEMS OUTPUT;
SELECT #RETURN_ITEMS as RETURN_ITEMS;
The row count messages confuse some client drivers. The resultset column name should be an ordinary identifier, and the local variable you declare needs to be the one you return. And it can have the same name as the stored proc output parameter.
Related
how i can get output value from stored procedure to php variable ..
example Stored procedure :
DROP PROCEDURE `test`; CREATE DEFINER=`mydbinstance`#`%` PROCEDURE `test`(OUT `max` INT(11)) NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
BEGIN
SELECT MAX(slno)+1 INTO #max FROM table1;
SELECT #max;
END
php:
$stmt=mysqli_query($conn,"CALL test();");
You should be able to get the result(s) of a stored procedure the same way you would any other query:
$stmt = mysqli_query($conn,"CALL test();");
if ($row = mysqli_fetch_row($stmt)) {
$value = $row[0];
}
Info:
PHP 7.0.0
SQL Server 2014
Using sqlsrv driver
The following code may not be optimal but this is the PHP:
$nombre = strval($info->nombre);
$idPerfil = 0;
$sqlAltaPerfil = "{CALL AltaPerfil(?,?)}";
$paramsAltaPerfil = [
[$nombre, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR(50)],
[&$idPerfil, SQLSRV_PARAM_INOUT, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT]
];
$stmtAltaPerfil = sqlsrv_query($conexion, $sqlAltaPerfil, $paramsAltaPerfil);
if($stmtAltaPerfil !== false) {
sqlsrv_next_result($stmtAltaPerfil);
$sqlAltaPerfilXExComp = "{CALL AltaPerfilXExamenComplementario(?, ?)}";
foreach($info->arrayIdExComp as $idExComp){
$idExComp = intval($idExComp);
var_dump($idExComp);
$paramsAltaPerfilXExComp = [
[$idPerfil, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT],
[$idExComp, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT]
];
$stmtAltaPerfilXExComp = sqlsrv_query($conexion, $sqlAltaPerfilXExComp, $paramsAltaPerfilXExComp);
if($stmtAltaPerfilXExComp !== false){
//bien
}
else{
$exito = false;
$erroresPhp .= print_r(sqlsrv_errors(), true);
break;
}
}
}
This is the SP:
ALTER PROCEDURE [dbo].[AltaPerfil](
#Descripcion varchar(50),
#IdPerfil int OUTPUT
) AS
BEGIN
INSERT INTO PERFILEXAMENCOMPLEMENTARIO (Descripcion) VALUES (#Descripcion)
SET #IdPerfil = ##IDENTITY
RETURN
END
I know by the error message i display in the client side that $idPerfil remains equal to 0 (line 2). The fun fact is that in SSMS the SP works just fine, but when calling it from PHP the $idPerfil isn't modified
EDIT: I found that the problem is not the code, it's a trigger in the DB that
for some reason interferes with the ##IDENTITY variable in the SP.
This is the trigger:
ALTER TRIGGER [dbo].[NombresPerfilesUnicos] ON [dbo].[PERFILEXAMENCOMPLEMENTARIO] INSTEAD OF INSERT, UPDATE AS
BEGIN
DECLARE #NombrePerfil varchar(50)
SELECT #NombrePerfil = Descripcion FROM inserted
IF EXISTS(SELECT PEC.IdPerfil FROM PERFILEXAMENCOMPLEMENTARIO PEC WHERE Descripcion = #NombrePerfil)
PRINT 'ERROR, la descripcion ' + #NombrePerfil + ' ya esta registrada'
else
INSERT INTO PERFILEXAMENCOMPLEMENTARIO SELECT Descripcion FROM inserted
END
So my new question is: Why this is happening? What do i have to do to keep this trigger working (modify if necessary) and make everything work?
Try using SCOPE_IDENTITY() instead of ##Identity.
Sourced from :
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
"SELECT ##IDENTITY
It returns the last IDENTITY value produced on a connection, regardless of the table that produced the value, and regardless of the scope of the statement that produced the value."
"SELECT SCOPE_IDENTITY()
It returns the last IDENTITY value produced on a connection and by a statement in the same scope, regardless of the table that produced the value."
You can use in the following way: and you don't need second variable if you don't have any transaction with that next in the stored procedure.Using IDENT_CURRENT with table name is much better than others because it just return you identity value of mentioned table.
--Procedure Part
ALTER PROCEDURE [dbo].[AltaPerfil](
#Descripcion VARCHAR(50)
) AS
BEGIN
INSERT INTO PERFILEXAMENCOMPLEMENTARIO(Description) VALUES (#Descripcion)
SELECT IDENT_CURRENT('PERFILEXAMENCOMPLEMENTARIO') AS rowID
END
--Call From PHP replace with your variable and It will return your column rowID with value:
EXEC AltaPerfil 'test'
In the end, all i had to do was adding SET NOCOUNT ON to the SP and it magically worked
ALTER PROCEDURE [dbo].[AltaPerfil](
#Descripcion varchar(50),
#IdPerfil int out
) AS
BEGIN
SET NOCOUNT ON;
INSERT INTO PERFILEXAMENCOMPLEMENTARIO (Descripcion) VALUES (#Descripcion)
SET #IdPerfil = ##IDENTITY
END
I am trying to run a procedure in which i will send the table name to fetch all records from it..so that i don't have to create different procedure...but i am facing some problem in that.
ALTER PROCEDURE [dbo].[getTableData]
-- Add the parameters for the stored procedure here
#tableName Varchar(100),
#whrFldName NVarchar(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #ActualTableName AS NVarchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #tableName
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'SELECT * FROM ' + #ActualTableName + ' WHERE ' +
#whrFldName + ' = ''y'' ;'
--PRINT #sql
EXEC(#SQL)
END
The PHP code is this..
$sql ="EXEC [dbo].[getTableData] 'tbl_services','serviceStatus'";
$rst = odbc_exec($connection, $sql);
$i = 0;
while($result = odbc_fetch_array($rst))
{
$returnPageData[$i] = $result;
$i++;
}
It executes just fine in server but when I call it from my PHP code, it returns null.
Here if I remove * and place fields it works fine..I have tested my code well,it specially creates the problem for a Text type field..
If i change the procedure to this,it works fine..
ALTER PROCEDURE [dbo].[getTableData]
-- Add the parameters for the stored procedure here
#rowsPerPage as bigint,
#pageNum as bigint
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
WITH SQLPaging AS (
SELECT TOP(#rowsPerPage * #pageNum) ROW_NUMBER() OVER (ORDER BY creationDate DESC)
AS resultNum, *
FROM [DB_SB].[dbo].[tbl_blog] )
SELECT
blogTitle,
blogSlug,
blogImage,
substring( blogContent, 1, 210 ) AS blogContent,
creationDate,
blogAddedBy
FROM SQLPaging WITH (nolock) WHERE resultNum > ((#pageNum - 1) * #rowsPerPage)
END
But this is no logical..if i send fields everytime..this is not what i want exactly..
Any solution??please help...
You need to use SQL Server Profiler to see what’s actually getting to database engine.
If your stored procedure is executed correctly when run from SSMS then there is a problem somewhere in PHP part.
Are you using the same database using when testing from SSMS? There might be some issue in that…
I have created this procedure:
DROP PROCEDURE IF EXISTS add_com;
DELIMITER //
CREATE PROCEDURE add_com (cd CHAR(16), n VARCHAR(20), t VARCHAR(20), i VARCHAR(20))
BEGIN
DECLARE num INT;
DECLARE msg varchar(20);
set #num=select COUNT(*) from commercianti where codice_fiscale=cd;
IF num==0 THEN
insert into commercianti values (cd,n,i,t);
set #msg="Commerciante inserito";
ELSE
insert into errors values (1);
set #msg="Commerciante presente";
END IF;
return #msg;
END; //
then in a PHP page I execute this code:
<?php
$cd=$_POST['codice_fiscale'];
$n=$_POST['nominativo'];
$t=$_POST['telefono'];
$i=$_POST['indirizzo'];
if(!$cd||!$n||!$t||!$i)
echo "No data";
else{
require dirname(__FILE__) . '/' . 'dbconfig.php';
$mysqli = new MySQLI(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$result = $mysqli->query("CALL add_com('$cd','$n','$t','$i')");
echo $result;
}
?>
But the value of $result is undefined and seems the procedure doesn't work or isn't called.
If you want to get data back from a routine, you should be using a function, rather than a procedure. They have nearly the same syntax, but most notably is the RETURNS type section of the declaration. Take a look at the official documentation:
http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
Note that the SECOND create block there is the one regarding functions. The first deals with procedures.
So I think that would look something like this:
DROP FUNCTION IF EXISTS add_com;
DELIMITER //
CREATE FUNCTION add_com (cd CHAR(16), n VARCHAR(20), t VARCHAR(20), i VARCHAR(20))
RETURNS VARCHAR(20)
BEGIN
DECLARE num INT;
DECLARE msg varchar(20);
SELECT COUNT(*) INTO #num FROM commercianti WHERE codice_fiscale = cd;
IF num==0 THEN
insert into commercianti values (cd,n,i,t);
set #msg="Commerciante inserito";
ELSE
insert into errors values (1);
set #msg="Commerciante presente";
END IF;
return #msg;
END; //
I'm not 100% sure about the RETURNS VARCHAR(20). That might have to be simply RETURNS VARCHAR.
Try changing
IF num==0 THEN
to
IF num=0 THEN
I've been trying to find an answer to this question, but haven't found any definitive "yes" or "no" in all my research.
I'm running a simple MySQL query like this:
UPDATE item SET `score`=`score`+1 WHERE `id`=1
Is there a way for that query to return the updated value, instead of the number of rows affected? Just as a reference, I'm doing this in PHP, so the actual code looks like:
$sql = "UPDATE item SET `score`=`score`+1 WHERE `id`=1";
$new_value = mysql_query($sql);
//Unfortunately this does not return the new value
I know I could do a second query and just SELECT the value, but I'm trying to cut down on queries as much as possible. Is there a way?
You can do it with a stored procedure that updates, and then selects the new value into an output parameter.
The following returns one column new_score with the new value.
DELIMITER $$ -- Change DELIMITER in order to use ; withn the procedure
CREATE PROCEDURE increment_score
(
IN id_in INT
)
BEGIN
UPDATE item SET score = score + 1 WHERE id = id_in;
SELECT score AS new_score FROM item WHERE id = id_in;
END
$$ -- Finish CREATE PROCEDURE statement
DELIMITER ; -- Reset DELIMITER to standard ;
In PHP:
$result = mysql_query("CALL increment_score($id)");
$row = mysql_fetch_array($result);
echo $row['new_score'];
No, there's nothing like postgresql's UPDATE ... RETURNING output_expression in MySQL (yet?).
If you don't want to run another Query SELECT then here is another way to do it. I have modified Mr. Berkowski code for reference:
DELIMITER $$
CREATE PROCEDURE increment_score
(
IN id_in INT
)
BEGIN
set #newScore := null;
UPDATE item SET score = IF((#newScore := score+1) <> NULL IS NULL, #newScore, NULL) WHERE id = id_in;
SELECT #newScore;
END
DELIMITER ;
No you cant. You could make a function or stored procedure that could do the insert and return the updated value but that would still require you to execute two queries from within the function or stored procedure.
You can create a trigger, and you will know everything about the modifications.