I tried to call a SQL Server stored procedure from PHP.
Here is my stored procedure:
CREATE procedure [dbo].[tester]
#id NVARCHAR(MAX)
AS
BEGIN
DECLARE #tab TABLE (myxml XML)
INSERT INTO #tab(myxml)
SELECT map
FROM forms
WHERE mapid = #id
SELECT * FROM #tab
END
and my PHP script:
<?php
$serverName = "servername";
$connectionInfo = array("UID" => "sa","PWD" => "mypass","Database" => "database");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if ($conn) {
$tsql = "exec tester 'FORMgRGVL7bfpEnpBpg7vz2sHoKAs5zxU5LW'";
$result = sqlsrv_query($conn, $tsql);
if ($result === false) {
die( print_r( sqlsrv_errors(), true) );
$response=array('response'=>'notok','data'=>'loyo');
$serverresponse=JSON_encode($response);
} else {
$row = sqlsrv_fetch_array( $result, SQLSRV_FETCH_NUMERIC);
$response=array('response'=>'ok','data'=>$row[0]);
$serverresponse=JSON_encode($response);
}
sqlsrv_free_stmt($stmt);
} else {
$response=array('response'=>'notok','flag'=>$flag,'data'=>'cc');
$serverresponse = $serverresponse=JSON_encode($response);
}
echo ($serverresponse);
?>
When I execute the stored procedure from SSMS it returns the value as expected, but when I execute it from PHP, it returns null.
Explanations:
You need to put SET NOCOUNT ON as first line in your stored procedure to prevent returning the number of rows affected by the T-SQL statements as part of the result set. This is the reason for your NULL results.
As a note, always use prepared statements and parameterized queries to prevent SQL injection. With PHP Driver for SQL Server, function sqlsrv_query() does both statement preparation and statement execution and can be used to execute parameterized queries.
Example:
There are errors in your script, which are fixed in the example:
sqlsrv_free_stmt($stmt) is changed to sqlsrv_free_stmt($result)
variable $flag is not defined
$serverresponse = $serverresponse=JSON_encode($response) is changed to $serverresponse = json_encode($response)
T-SQL:
CREATE procedure [dbo].[tester]
#id nvarchar(max)
as
begin
SET NOCOUNT ON
declare #tab table (myxml xml)
insert into #tab(myxml)
select map from forms where mapid=#id
select * from #tab
end
PHP:
<?php
$flag = "";
$serverName = "servername";
$connectionInfo = array("UID" => "sa", "PWD" => "mypass", "Database" => "database");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if ($conn) {
$tsql = "exec tester ?";
$params = array('FORMgRGVL7bfpEnpBpg7vz2sHoKAs5zxU5LW');
$result = sqlsrv_query($conn, $tsql, $params);
if ($result === false) {
die( print_r( sqlsrv_errors(), true) );
$response = array('response'=>'notok', 'data'=>'loyo');
$serverresponse = json_encode($response);
} else {
$row = sqlsrv_fetch_array( $result, SQLSRV_FETCH_NUMERIC);
$response = array('response'=>'ok', 'data'=>$row[0]);
$serverresponse = json_encode($response);
}
sqlsrv_free_stmt($result);
} else {
$response = array('response'=>'notok', 'flag'=>$flag, 'data'=>'cc');
$serverresponse = json_encode($response);
}
echo ($serverresponse);
?>
Related
Hello i need a little Help.
I have a MSSQL Server and i need the ID of the Last Entery.
My PHP Code is:
$conn = sqlsrv_connect( $serverName, $connectionInfo);
$sqlnextid = "Select IDENT_CURRENT('dbo.Person')";
echo $sqlnextid;
$nextid = sqlsrv_query( $conn, $sqlnextid );
echo $nextid;
Unfortunately $nextid only returns "Resource id#3" and not the correct ID in the SQL Management Studio. The sql query "Select IDENT_CURRENT('dbo.Person')" works fine an give the correct answer - (33).
Where is my mistake? Thanks in advance :)
You need to fetch the data from the executed query uisng sqlsrv_fetch_array(). As is explained in the documentation, the function sqlsrv_query() returns a statement resource or false if the statement cannot be created and/or executed.
As a side note, always check the result from the sqlsrv_connect() and sqlsrv_query() calls.
<?php
...
// Connection
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false ) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Query
$sqlnextid = "SELECT IDENT_CURRENT('dbo.Person') AS [CurrentIdent]";
$stmt = sqlsrv_query( $conn, $sqlnextid );
if( $stmt === false ) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
// Data
$ident = 0;
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$ident = $row["CurrentIdent"];
}
echo $ident;
...
?>
sqlsrv_query returns returns a statement resource on success and FALSE if an error occurred.
You can access the result using sqlsrv_fetch_object.
$sqlnextid = "SELECT IDENT_CURRENT('dbo.Person') AS LastId"
$result = sqlsrv_query($conn, $sqlnextid);
$row = sqlsrv_fetch_object($result)
echo $row->LastId;
I wrote an php application which should select data from the database depending on a given date. The date in the Database is stored like 2020-07-03. The code which executes the statement looks like
$from = $_POST['from'];
$to = $_POST['to'];
$sql = "SELECT * FROM Database WHERE Date < $from";
$stmt = sqlsrv_query($conn, $sql);
if($stmt == false){
die( print_r( sqlsrv_errors(), true) );
}
echo $sql;
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
echo $row[0].", ".$row[1]."<br />";
}
$from and $to is a range which is given by the user with date-input fields and return the userinput like 2020-07-02. The datatype of the field "Date" is Date. I do not get any error or something similar but it won't execute the while loop and I can't figure out why.
You need to use parameters in your statement. As is mentioned in the documentation, sqlsrv_query() function is well-suited for one-time queries and should be the default choice to execute queries unless special circumstances apply. This function provides a streamlined method to execute a query with a minimum amount of code. The sqlsrv_query function does both statement preparation and statement execution, and can be used to execute parameterized queries.
You need to pass the values of parameters in one of the following ways:
As text using an unambiguous date format (yyyymmdd),
Using extended parameters syntax and the appropriate data type bindings.
Example, based on the code in the question, using text values for dates:
<?php
// Connection
$server = 'server,port';
$database = 'database';
$uid = 'uid';
$pwd = 'pwd';
$cinfo = array(
"ReturnDatesAsStrings" => true,
"Database" => $database,
"UID" => $uid,
"PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Test input
$from = (new DateTime('2020-07-02'))->format('Ymd');
$to = (new DateTime('2020-07-03'))->format('Ymd');
// Statement
$sql = "
SELECT *
FROM Database
WHERE (? <= [Date]) AND ([Date] <= ?)"
;
$params = array($from, $to);
$stmt = sqlsrv_query($conn, $sql, $params);
if($stmt == false){
die( print_r( sqlsrv_errors(), true) );
}
echo $sql;
// Data
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
echo $row[0].", ".$row[1]."<br />";
}
// End
sqlsrv_free_stmt($stmt);
?>
Example, based on the code in the question, using PHP date objects and the appropriate parameters bindings:
<?php
// Connection
$server = 'server,port';
$database = 'database';
$uid = 'uid';
$pwd = 'pwd';
$cinfo = array(
"ReturnDatesAsStrings" => true,
"Database" => $database,
"UID" => $uid,
"PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Test input
$from = new DateTime('2020-07-02');
$to = new DateTime('2020-07-03');
// Statement
$sql = "
SELECT *
FROM Database
WHERE (CONVERT(date, ?) <= [Date]) AND ([Date] <= CONVERT(date, ?))"
;
$params = array(
array($from, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME),
array($to, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME)
);
$stmt = sqlsrv_query($conn, $sql, $params);
if($stmt == false){
die( print_r( sqlsrv_errors(), true) );
}
echo $sql;
// Data
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC) ) {
echo $row[0].", ".$row[1]."<br />";
}
// End
sqlsrv_free_stmt($stmt);
?>
I am using Laravel 7 and I want to show the results from the stored procedure. My code is given below. When I execute the stored procedure with parameters in SQL Server, it's showing data. But in Laravel application data is not showing.
Please, help me to find the problem.
$serverName = env("DB_HOST");
$connectionInfo = array( "Database"=>env("DB_DATABASE"), "UID"=>env("DB_USERNAME"), "PWD"=>env("DB_PASSWORD") );
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true));
}
$tsql= " EXEC USP_Daily_TA_Punching_Detailswith_OT '$employee','$datefrom','$dateto'";
$getResults= sqlsrv_query($conn, $tsql);
$data = array();
if ($getResults == FALSE)
{
echo '';
}
else {
//$data[] ='';
do
{
while ($row = sqlsrv_fetch_array($getResults, SQLSRV_FETCH_ASSOC))
{
$data[] = $row;
}
}
while (sqlsrv_next_result($getResults));
}
if(count($data)>0){
sqlsrv_free_stmt($getResults);
$total_row = count($data);
}
Always try to use parameters in your statements to prevent possible SQL injection issues. As an additional note, use unambiguous date format, when you pass date values to SQL Server:
Example using PHP Driver for SQL Server:
<?php
// Connection
$serverName = env("DB_HOST");
$connectionInfo = array(
"Database"=>env("DB_DATABASE"),
"UID"=>env("DB_USERNAME"),
"PWD"=>env("DB_PASSWORD")
);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if ($conn === false) {
die(print_r(sqlsrv_errors(), true));
}
// Statement
$employee = '000010993';
$datefrom = '20200601';
$dateto = '20200610';
$tsql = "EXEC USP_Daily_TA_Punching_Detailswith_OT ?, ?, ?";
$params = array($employee, $datefrom, $dateto);
$getResults = sqlsrv_query($conn, $tsql, $params);
if ($getResults === false) {
die(print_r(sqlsrv_errors(), true));
}
// Results
$data = array();
do {
while ($row = sqlsrv_fetch_array($getResults, SQLSRV_FETCH_ASSOC)) {
$data[] = $row;
}
} while (sqlsrv_next_result($getResults));
// End
sqlsrv_free_stmt($getResults);
sqlsrv_close($conn);
$total_row = count($data);
?>
Example using Laravel:
<?php
...
$employee = '000010993';
$datefrom = '20200601';
$dateto = '20200610';
DB::select("SET NOCOUNT ON; EXEC USP_Daily_TA_Punching_Detailswith_OT ?, ?, ?", array($employee, $datefrom, $dateto));
...
?>
Try the below to call the store procedure in laravel
DB::select("call USP_Daily_TA_Punching_Detailswith_OT('".$employee."','".$datefrom."','".$dateto."')");
I have pleasure to work with legacy PHP application using SQL Server via PDO.
How in PHP can I retrieve return value of stored procedure which is using RETURN statement as output channel?
Example procedure
CREATE PROCEDURE [dbo].[mleko_test]
#param INT
AS
BEGIN
RETURN #param * 3;
END
GO
If possible, I would prefer to not modify procedure.
I am aware that there are similar questions, but they don't cover this case
Get RETURN value from stored procedure in SQL
Get Return Value from SQL Stored Procedure using PHP
Execute stored procedure like this: "exec ?=mleko_test(?)".
Working example:
<?php
#------------------------------
# Connection info
#------------------------------
$server = 'server\instance,port';
$database = 'database';
$uid = 'user';
$pwd = 'password';
#------------------------------
# With PDO
#------------------------------
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch ( PDOException $e ) {
die ( "Error connecting to SQL Server" );
}
try {
$sql = "exec ? = mleko_test (?)";
$param = 3;
$spresult = 0;
$stmt = $conn->prepare($sql);
$stmt->bindParam(1, $spresult, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(2, $param);
$stmt->execute();
} catch ( PDOException $e ) {
die ( "Error connecting to SQL Server" );
}
$stmt = null;
$conn = null;
echo 'Stored procedure return value (with PDO): '.$spresult."</br>";
#------------------------------
# Without PDO
#------------------------------
$cinfo = array (
"Database" => $database,
"UID" => $uid,
"PWD" => $pwd
);
$conn = sqlsrv_connect($server, $cinfo);
if ( $conn === false )
{
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
$sql = "exec ? = mleko_test (?)";
$param = 3;
$spresult = 0;
$params = array(
array(&$spresult, SQLSRV_PARAM_OUT),
array($param, SQLSRV_PARAM_IN),
);
$stmt = sqlsrv_query($conn, $sql, $params);
if ( $stmt === false ) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
echo 'Stored procedure return value (without PDO): '.$spresult."</br>";
?>
Notes:
Tested with PHP 7.1.12 and PHP Driver for SQL Server (pdo_sqlsrv version 4.3.0+9904).
I came to a solution using multi-query but #Zhorov answer is cleaner
<?php
$connection = new PDO($connectionString, $DB_USERNAME, $DB_PASSWORD);
$stmt = $connection->prepare(<<<SQL
DECLARE #a INT;
EXEC #a = mleko_test :in
SELECT #a AS result;
SQL
);
$stmt->execute([":in" => 123]);
echo $stmt->fetch()["result"] . "\n";
I had to change
$sql = "exec ?=mleko_test(?)";
for
$sql = "{?=call mleko_test(?)}";
I have recently switched a PHP app from mssql to sqlsrv and would like to continue using a couple custom functions to handle all my SQL requests. I get an error
Warning: sqlsrv_fetch_array(): 2 is not a valid ss_sqlsrv_stmt
resource in...
when using the following function to handle all sqlsrv_query() calls:
<?php
function tko_query($sql)
{
//Check for db connection
$serverName = "server\sqlexpress";
$connectionInfo = array( "Database"=>"db", "UID"=>"uid", "PWD"=>"pwd");
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true));
}
return sqlsrv_query($conn,$sql, array(), array('Scrollable' => 'buffered'));
}
$sql = "SELECT * FROM jobs";
$stmt = tko_query($sql);
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) )
{
echo $row['name']."<br />";
}
sqlsrv_free_stmt( $stmt);
?>
You should declare $conn variable as global or try to fetch data inside tko_query function body. When tko_query ends the connection is closed and you cannot fetch data..