I'm using sqlsrv_num_rows in order to check if a user exists in the DB.
When i'm running the query in my DB i'm getting 1 result, but in my PHP I'm not getting anything (echo doesn't print anything). Why is that?
$query = "SELECT TOP 1 id, tourOp FROM users WHERE (valid = 1) AND (email = '".trim($_POST['email'])."') AND (password = '".trim($_POST['password'])."')";
$stmt = sqlsrv_query( $conn, $query);
echo "num: ".sqlsrv_num_rows( $stmt );
if (!sqlsrv_num_rows( $stmt )) {
return (false);
} else {
}
Example query
SELECT TOP 1 id, name FROM users WHERE (valid = 1) AND (email = 'roi#some_email.com') AND (password = '8521')
I'm using PHP and MSSQL.
Explanations:
Function sqlsrv_num_rows() requires a client-side, static, or keyset cursor, and will return false if you use a forward cursor or a dynamic cursor (the default cursor is forward cursor). Execute sqlsrv_query() with additional $options parameter and set the appropriate cursor type with "Scrollable" => SQLSRV_CURSOR_KEYSET
Use parameterized statements. Function sqlsrv_query() does both statement preparation and statement execution and can be used to execute parameterized queries.
If you want to check if the result set has one or more rows, you may use sqlsrv_has_rows().
Example, based on your code:
<?php
$query = "
SELECT TOP 1 id, tourOp
FROM users
WHERE (valid = 1) AND (email = ?) AND (password = ?)";
$params = array(trim($_POST['email']), trim($_POST['password']));
$options = array("Scrollable" => SQLSRV_CURSOR_KEYSET);
$stmt = sqlsrv_query( $conn, $query, $params, $options);
if ($exec === false){
echo print_r( sqlsrv_errors());
echo "<br>";
return (false);
}
$count = sqlsrv_num_rows($stmt);
if ($count === false) {
echo print_r( sqlsrv_errors());
echo "<br>";
return (false);
} else {
echo "num: ".$count;
}
?>
Notes:
Do not send user credentials in plain text.
Related
I have an unusually long query (13sec+ for our system) that returns no results while using sqlsrv_query, but gives me 331 rows when I enter directly the SQL query on the server. sqlsrv_num_rows returns 0 and sqlsrv_errors is empty.
<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);
if ($conn)
{
$sql_q = "SELECT TblOrder.FldJobNb, TblOrder.FldOrdCre As DateReception, TblOrder.FldReclamerDate As DateDebutPORev, TblOrder.FldPOReviewApprovedDate As DateFinPORev,
TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
CASE
WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0
THEN capsule_order.temps_reception_planification
ELSE TblOrder.FldContractReviewCompletedDate
END As TempsFinRevue,
(SELECT TOP 1 TblOrderXFeredNotifications.FldDate FROM [TCS].[dbo].[TblOrderXFeredNotifications] WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID ORDER BY TblOrderXFeredNotifications.FldNoLigne) As DatePlanification,
TblOrder.FldXfer2Sched, TblOrder.FldOrdMod As DateDernierMod, TblOrder.FldOrdStatusDate As DateDernierStatut, TblOrder.FldOrdReq As DateBesoin
FROM [TCS].[dbo].[TblOrder] RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
WHERE '" . $dateDebut->format('Y-m-d H:i:s.').'000' . "' <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= '" . $dateFin->format('Y-m-d H:i:s.').'000' . "'";
// die($sql_q); Query that I enter into SQL Server and gives me 331 results after 13secs
$query= sqlsrv_query($conn, $sql_q, array(), array( "Scrollable" => 'static' ));
if ($query)
{
if (sqlsrv_num_rows($query) > 0)
{
while ($result= sqlsrv_fetch_array($query))
{
// ...
}
}
else
{ die(var_dump(sqlsrv_num_rows($query))); }
}
else
{ die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); }
}
else
{ die ("Connection défectueuse."); } ?>
Thank you a lot for your support,
Renaud
You may consider the following:
Pass datetime values to SQL Server using unambiguous datetime format (yyyy-mm-ddThh:mm:ss.zzz) (my experience is summarized here).
Don't concatenate strings to generate a statement. 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.
If you want to check if the result set from your current statement has one or more rows, you may use sqlsrv_has_rows() instead of sqlsrv_num_rows() and use a default (forward) cursor.
The following example, based on your code, is a possible solution to your problem:
<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);
if ($conn)
{
$sql_q = "
SELECT
TblOrder.FldJobNb,
TblOrder.FldOrdCre As DateReception,
TblOrder.FldReclamerDate As DateDebutPORev,
TblOrder.FldPOReviewApprovedDate As DateFinPORev,
TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
CASE
WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0 THEN capsule_order.temps_reception_planification
ELSE TblOrder.FldContractReviewCompletedDate
END As TempsFinRevue,
(
SELECT TOP 1 TblOrderXFeredNotifications.FldDate
FROM [TCS].[dbo].[TblOrderXFeredNotifications]
WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID
ORDER BY TblOrderXFeredNotifications.FldNoLigne
) As DatePlanification,
TblOrder.FldXfer2Sched,
TblOrder.FldOrdMod As DateDernierMod,
TblOrder.FldOrdStatusDate As DateDernierStatut,
TblOrder.FldOrdReq As DateBesoin
FROM [TCS].[dbo].[TblOrder]
RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
WHERE ? <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= ?
";
$query = sqlsrv_query(
$conn,
$sql_q,
array($dateDebut->format('Y-m-d\TH:i:s').'.000', $dateFin->format('Y-m-d\TH:i:s').'.000')
);
if ($query)
{
if (sqlsrv_has_rows($query))
{
while ($result= sqlsrv_fetch_array($query))
{
// ...
}
}
else
{ die(var_dump(sqlsrv_num_rows($query))); }
}
else
{ die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); }
}
else
{ die ("Connection défectueuse."); }
?>
I am trying to call an SQL Server stored procedure from a PHP page, and have the stored proc return a string value in an output parameter.
I already have a number of PHP pages which successfully call SQL Server stored procedures, and the procedures return an integer value. I also have a PHP page which executes a simple SELECT statement and gets back a string value. But now I have a stored proc which accepts an INPUT parameter from the PHP page, then it selects some data from a couple of tables, and creates a completely new string by concatenating it with some static text. I want to return that concatenated string to the calling PHP page.
Here is my stored proc:
CREATE PROCEDURE CHECK_SPONSOR_CODE
#cr_code VARCHAR(50),
#sponsor VARCHAR(255) OUTPUT
AS
DECLARE #xrowcount INT;
BEGIN
SET NOCOUNT ON;
BEGIN
SELECT #xrowcount = count(custom0)
FROM person_table
WHERE custom0 = #cr_code
AND custom5 = 'Yes';
IF (#xrowcount = 0)
BEGIN
SELECT #sponsor = 'Error (Unknown Code) - the Sponsor Code provided is invalid. Please check that you have entered the correct code.';
END
IF (#xrowcount > 1)
BEGIN
SELECT #sponsor = 'Error (Multiple Sponsors) - the Sponsor Code provided is invalid. Please contact the System Administrator.';
END
IF (#xrowcount = 1)
BEGIN
SELECT
#sponsor = 'Success! Your Sponsor is: ' + p.fname + ' ' + p.lname + ' (' + c.name + ')'
FROM
person_table p INNER JOIN
company_table c ON p.company_id = c.id
WHERE
p.custom0 = #cr_code
AND p.custom5 = 'Yes';
END
END
END
Here is my PHP page (check_code.php):
<?php
$crcode = "";
$sponsor = "";
$serverName = "server_name\db_name, 31433";
$connectionInfo = array( "Database"=>"db_name", "UID"=>"username", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
$query = "{call CHECK_SPONSOR_CODE (?, ?)}" ;
$crcode = "test_cr_code";
if(! $conn ){
die('Could not connect: ');
}
$params = array(
array($crcode, SQLSRV_PARAM_IN),
array($sponsor, SQLSRV_PARAM_INOUT)
);
$stmt = sqlsrv_query($conn, $query, $params);
if ($stmt) {
sqlsrv_next_result($stmt);
echo $sponsor;
} else {
echo "Error encountered, please contact support";
}
sqlsrv_close($conn);
?>
Note: the variable $crcode is hard-coded just for testing purposes
When I load the PHP page in my browser, I get the message:
Error encountered, please contact support
I have tested the stored proc in MSSQL Management Studio, and it works fine.
I think the problem might be something to do with the procedure returning a result set to the PHP page, and the last thing it returns is the OUTPUT parameter. And somehow that is causing the PHP page to get upset (sorry for getting technical). I tried modifying it as follows:
$params = array(
array($crcode, SQLSRV_PARAM_IN),
array($sponsor, SQLSRV_PARAM_INOUT)
);
$stmt = sqlsrv_query($conn, $query, $params);
$row_count = sqlsrv_num_rows( $stmt );
if ($stmt) {
sqlsrv_next_result($stmt);
echo $sponsor;
} else {
echo "Error encountered, please contact support";
}
But that just produced the following error:
Warning: sqlsrv_num_rows() expects parameter 1 to be resource, boolean given in D:\Apache2.2\htdocs\check_code2.php on line 23
Error encountered, please contact support
Any thoughts on how I can get the string back from the stored proc?
So I never figured out how to solve the problem with a stored procedure (and if anyone feels inclined to provide guidance on how to do that, I would be most grateful); but I did solve the problem using a slightly different approach. Here is my PHP code:
<?php
function check_sponsor_code() {
//$sponsor_code = $_GET['crcode'];
$sponsor_code = "test_cr_code";
$sponsor = "";
$serverName = "server\dbname, 31433";
$connectionInfo = array( "Database"=>"dbname", "UID"=>"username", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
$query = "SELECT
p.fname + ' ' + p.lname + ' (' + c.name2 + ')' AS sponsor
FROM
person_table p INNER JOIN
company_table c ON p.company_id = c.id
WHERE
p.custom5 = 'Yes'
AND p.custom0 = ?";
if(! $conn ){
die('Could not connect: ');
}
$params = array($sponsor_code);
$stmt = sqlsrv_query($conn, $query, $params, array( "Scrollable" => 'static' ));
if ($stmt) {
$row_count = sqlsrv_num_rows($stmt);
//echo "Row count: ".$row_count."<br/>";
if ($row_count == 0) {
$sponsor = "Error (Unknown Code) - the Sponsor Code provided is invalid. Please check that you have entered the correct code.";
} elseif ($row_count > 1) {
$sponsor = "Error (Multiple Sponsors) - the Sponsor Code provided is invalid. Please contact the System Administrator.";
} elseif ($row_count == 1){
while($row = sqlsrv_fetch_array($stmt)){
$sponsor = "Success! Your Headway DNA Sponsor is: ".($row['sponsor']);
}
} else {
$sponsor = "An unknown error occurred.";
}
} else {
echo "Error verifying record: Invalid Sponsor Code...<br/>";
}
sqlsrv_close($conn);
echo $sponsor;
}
check_sponsor_code();
?>
It works nicely, so unless someone tells me it's not a good solution I'm going to run with it.
I want to make a consult to the MSSQLSERVER with a SELECT STATEMENT but the sqlsrv_query is returning FALSE to me.
I already tested the query and its working fine, am I passing the parameters correctly?
Here is my code:
if($conn === false)
{
die(print_r(sqlsrv_errors()));
}
try
{
$email = "somedbemail#email.com";
$sql = "select Usuario.Email, Usuario.Senha FROM Usuario WHERE Usuario.Email = (?)";
$params = array($email);
$stmt = sqlsrv_query( $conn, $sql, $params);
if($stmt != False)
{
if($row = sqlsrv_fetch_Array($stmt))
{
$email_Con = $row['Email'];
$psw_Con = $row['Senha'];
}
else
{
echo "alguma coisa";
}
}
else
{
echo "It always enters here!";
}
Two possible problems.
The first is the format of your query. You are using:
select Usuario.Email, Usuario.Senha FROM Usuario WHERE Usuario.Email = (?)
Where I think you should be doing:
select Usuario.Email, Usuario.Senha FROM Usuario WHERE Usuario.Email = ?
The second is that the An invalid parameter was passed to sqlsrv_query() message is common when the connection is not correct (Reference). So double check that your connection is a valid resource.
So I have a php script that uses a stored procedure to interact with my SQL database. The stored procedure works just fine, the problem is I don't know how to get my php to echo the Return Value from the stored procedure. The stored procedure is basically activating an account using an activation key and sets the username and password.
It basically says "if the activation key provided does not have a username yet, set it to the one provided and RETURN 1, if it already has a username RETURN 2, and if the activation key does not exist RETURN 3". It works perfectly in SQL and even give the correct Return Value. Now how can I get my php to echo that? I have tried the following:
$link = sqlsrv_connect($myServer, array('Database' => $myDB, 'UID' => $myUser, 'PWD' => $myPass));
if($link === FALSE) {
die('Could not connect: ' . sqlsrv_errors(SQLSRV_ERR_ALL));
}
$key = $_REQUEST['key'];
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
$query = "EXEC Activate_Account";
$query .=" #key = ";
$query .= $key;
$query .=", #user = ";
$query .= $username;
$query .=", #pass = ";
$query .= $password;
$result = sqlsrv_query($link, $query);
while($row = sqlsrv_fetch_array($result))
{
echo $row[0];
}
sqlsrv_close($link);
and
while($row = sqlsrv_fetch_array($result))
{
echo $row['Return Value'];
}
Neither of them echo anything.
To return a value with a stored procedure:
For example:
SQL :
CREATE DEFINER=`user`#`localhost` PROCEDURE `ProcedureName`(IN `Input_Value` INT, OUT `Out_val` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
// Your SQL Code
SET Out_val= Your Value;
SELECT Out_val;
END
PHP Code:
$insert = "CALL ProcedureName(:Input_Value,
#Out_val)";
$bdd = new PDO('mysql:host=localhost;dbname=db-name', 'user', 'password');
$stmt = $bdd->prepare($insert);
$stmt->bindParam(':Input_Value', $an_input_value, PDO::PARAM_STR);
$stmt->execute();
$tabResultat = $stmt->fetch();
$Out_val = $tabResultat['Out_val'];
var_dump($Out_val);
The following example enables you to retrieve the RETURN value from a stored procedure and allows you to retrieve the OUTPUT values.
SQL:
CREATE PROCEDURE [ProcedureName]
#input_parameter as int,
#output_parameter as int out
AS
BEGIN
-- Your SQL code
SELECT #output_parameter = #input_parameter;
RETURN 2
END
PHP:
// Connect.
$link = sqlsrv_connect($myServer, array('Database' => $myDB, 'UID' => $myUser, 'PWD' => $myPass));
$returnValue = 0;
$inputParameter = 10;
$outputParameter = 0;
$parameters = [
[&$returnValue, SQLSRV_PARAM_OUT],
[$inputParameter, SQLSRV_PARAM_IN],
[&$outputParameter, SQLSRV_PARAM_OUT],
];
$sql = "EXEC ? = ProcedureName ? ?";
$stmt = sqlsrv_query($link, $sql, $parameters);
if ($stmt === false)
{
// Throw/Handle Error.
}
// $returnValue and $outputParameter should be updated here because they were passed by Reference.
// Retrieve query rows if any.
$rows = [];
while (($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ?? false) !== false) {
$rows[] = $row;
}
Some more reading about this topic can be found on the following links: How to retrieve input and output parameters using the sqlsrv driver and Sqlsrv query
the PHP below works fine in instances of insertion, but with a select query of bound parameters, not much luck has come through with the json reading. The application I'm creating now always returns false with the if statement evaluating the number of rows. I have a feeling the issue truly lies with the scope of the mysqli_stmt_store_result($query). The login credentials of the user do not work when attempting to login even though they are correct. Please let me know if more information is needed. The database connection is fine.
//parameter checking
$username = safe(stripslashes(trim($_POST['username'])));
$mypassword=hash('sha256', $salt.$_POST['password']);
//sanitize input parameters
function safe($value)
{
global $db;
$secureString = mysqli_real_escape_string($db, $value);
return $secureString;
}
//query check
$query= mysqli_prepare($db, "SELECT * FROM Users WHERE username =? AND password =? AND block_status < 1");
//$result=mysqli_query($db,$query);
mysqli_stmt_bind_param($query,'ss',$username,$mypassword);
mysqli_stmt_execute($query);
/* store result */
mysqli_stmt_store_result($query);
$query2="UPDATE Users SET last_login=NOW() WHERE username ='" . $username . "' AND password = '" . $mypassword . "'";
$result2=mysqli_query($db,$query2);
//if match found, create an array of data and json_encode it
if(mysqli_stmt_num_rows($query)>0)
{
$row=mysqli_fetch_array($query,MYSQLI_ASSOC);
$response=array(
'logged'=>true,
'name'=>$row['name'],
'email'=>$row['email']
);
echo json_encode($response);
}
else
{
$response=array(
'logged'=>false,
'message'=>'Invalid credentials or your access has been revoked'
);
echo json_encode($response);
}
/* free result */
mysqli_stmt_free_result($query);
/* close statement */
mysqli_stmt_close($query);
mysqli_close($db);
?>
According to the docs, you should be using mysql_stmt_store_result() before calling mysql_stmt_num_rows().
Also, you should use parameter binding for your UPDATE query, but only after you've confirmed a successful login.
I highly recommend PDO over MySQLi. The API is much cleaner and easier to understand. Here's how I would do it...
// assuming your user table has a primary key `id`
$stmt = $db->prepare('SELECT `id`, `name`, `email` FROM `Users` WHERE `password` = ? AND `username` = ? AND block_status < 1');
$stmt->execute(array($passwordHash, $username));
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user !== false) {
$response = array('logged' => true) + $row;
$update = $db->prepare('UPDATE `Users` SET `last_login` = NOW() WHERE `id` = ?');
$update->execute(array($row['id']));
} else {
$response = array(
'logged' => false,
'message' => 'Invalid credentials or your access has been revoked'
);
}
$stmt->closeCursor();
header('Content-type: application/json');
echo json_encode($response);
exit;