Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute a stored procedure in php using sqlsrv and "?" style parameters

I've looked over several other questions that seem (from the titles) the same as this. However, my case is a bit different.

The following works (i.e. I get "success" and my database performs what I expect when running the procedure with the given variables):

$sql = "MyDB.dbo.myProcedure {$var1}, {$var2}, {$var3}";
$result = sqlsrv_query($myConn, $sql);
if (!$result) {
    echo 'Your code is fail.';
}
else {
    echo 'Success!';
}

I want to avoid (or lessen the possibility of) SQL injection by creating the SQL string using parameters. For example:

$sql = "select * from aTable where col1 = ? AND col2 = ?";
$result = sqlsrv_query($myConn, $sql, array($var1, $var2));
//please note. This code WILL work!

But when I do that with a stored procedure it fails. It fails with no errors reported via sqlsrv_errors(), no action taken in database, and $result === false.

To be clear, the following fails:

$sql = "MyDB.dbo.myProcedure ?, ?, ?";
$result = sqlsrv_query($myConn, $sql, array($var1, $var2, $var3));

Likewise a prepare/execute statement created the same way will also fail:

$sql = "MyDB.dbo.myProcedure ?, ?, ?";
$stmt = sqlsrv_prepare($myConn, $sql, array(&$var1, &$var2, &$var3));
foreach($someArray as $key => $var3) {
    if(sqlsrv_execute($stmt) === false) {
        echo 'mucho fail.';
    }
}
//this code also fails.

For completeness, I have confirmed that the stored procedure in question works directly within SQL Management Studio AND if called the way I mentioned above. Likewise, I have confirmed that I can use parameterized queries for any raw query (like an insert, select, update vs a stored procedure).

So, my question is how can I call a stored procedure using the parameterized query vs embedding the variables in the query string?

More importantly, I am actually wanting to use a prepare/execute, so hopefully the answer will allow this to work as well.

like image 600
LittleTreeX Avatar asked Jul 22 '15 22:07

LittleTreeX


People also ask

Can you call a stored procedure from a UDF?

Is it possible to call a stored procedure in a user defined function in sql server, mysql or oracle ? In SQL Server: no, you cannot call stored procedures from inside functions.

How can we call stored procedure with parameters in PHP with SQL Server?

To call a stored procedure from a PHP application, you prepare and execute an SQL CALL statement. The procedure that you call can include input parameters (IN), output parameters (OUT), and input and output parameters (INOUT).

How do you call a stored procedure with parameters?

Expand the database that you want, expand Programmability, and then expand Stored Procedures. Right-click the user-defined stored procedure that you want and select Execute Stored Procedure. In the Execute Procedure dialog box, specify a value for each parameter and whether it should pass a null value.


3 Answers

The user contributions on the php.net have a write up on how to execute a stored procedure using the sqlsrv-prepare.

In case that is removed from the php.net user contributions in the future here is what it had(has) listed:

$procedure_params = array(
array(&$myparams['Item_ID'], SQLSRV_PARAM_OUT),
array(&$myparams['Item_Name'], SQLSRV_PARAM_OUT)
);
// EXEC the procedure, {call stp_Create_Item (@Item_ID = ?, @Item_Name = ?)} seems to fail with various errors in my experiments
$sql = "EXEC stp_Create_Item @Item_ID = ?, @Item_Name = ?";
$stmt = sqlsrv_prepare($conn, $sql, $procedure_params);

Here's the manual's page, http://php.net/manual/en/function.sqlsrv-prepare.php

like image 145
chris85 Avatar answered Oct 07 '22 18:10

chris85


This is a follow up to the answer by @chris85.

It's worth noting here that once the statement is prepared, you need to execute it:

$sql = "EXEC stp_Create_Item @Item_ID = ?, @Item_Name = ?";
$stmt = sqlsrv_prepare($conn, $sql, $procedure_params);
if (!sqlsrv_execute($stmt)) {
    echo "Your code is fail!";
    die;
}
while($row = sqlsrv_fetch_array($stmt)){
    //Stuff
}

sqlsrv_execute() only returns true/false. If you want to parse the data returned by the stored procedure you can process it just like the result from sqlsrv_query().

If you forget the sqlsrv_execute() you'll get an error saying that the result has to be executed before it can be used.

like image 12
AndyD273 Avatar answered Oct 07 '22 19:10

AndyD273


This is another followup to the answer by @chris85.

I tried the answer, combined with the followup answer by @AndyD273, but got the following error: I get the exception "The formal parameter "@param1" was not declared as an OUTPUT parameter, but the actual parameter passed in requested output"

I solved this by changing all instances of SQLSRV_PARAM_OUT to SQLSRV_PARAM_IN. The documentation for SQLSRV_PARAM_IN says:

Indicates an input parameter when passed to sqlsrv_query() or sqlsrv_prepare().

The updated version of @chris85's answer to prepare the stored procedure parameters now looks like:

$procedure_params = array(
    array(&$myparams['Item_ID'], SQLSRV_PARAM_IN),
    array(&$myparams['Item_Name'], SQLSRV_PARAM_IN)
);
like image 3
Zishi Wu Avatar answered Oct 07 '22 17:10

Zishi Wu