PHP PDO MSSQL SP - no return values - php

I need some help in relation to PHP PDO MSSQL Stored Procedure.
I have a Stored Procedure which is called with two parameters userId and pwd, the Stored Procedure then returns two values status and token (using SELECT #status as status, null as token in the Stored Procedure to return the value)
When I try to call the Stored Procedure from PHP (ver. 7.0) using PDO I don't receive any return values
This is the PHP code:
$conn = new PDO("sqlsrv:server=".$host.";Database=".$db_name,
$username,$password);
$userId = "2465";
$pwd = "460";
$query = "exec sp_getToken #userId=:userId, #pwd=:pwd";
$stmt = $conn->prepare($query);
$stmt->bindValue(':userId', $userId);
$stmt->bindValue(':pwd', $pwd);
$stmt->execute();
while($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
var_dump($result);
}
Can anyone tell what to do?

It is almost the same, but you may try with this:
<?php
$host = 'server\instance,port';
$db_name = 'database';
$username = 'user';
$password = 'password';
# Connection
try {
$conn = new PDO("sqlsrv:server=".$host.";Database=".$db_name, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
die("Error connecting to SQL Server: ".$e->getMessage());
}
# Stored procedure
try {
$query = "{call sp_getToken(#userId=?, #pwd=?)}";
$userId = "2465";
$pwd = "460";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $userId, PDO::PARAM_STR);
$stmt->bindParam(2, $pwd, PDO::PARAM_STR);
$stmt->execute();
while($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
var_dump($result);
echo"</br>";
}
} catch(PDOException $e) {
die("Error executing stored procedure: ".$e->getMessage());
}
$stmt = null;
#
$conn = null;
?>

Problem solves :)
By adding "SET NOCOUNT ON" to my stored procedure. Obviously the problem was related to the facts, that a stored procedure returns two results, the first result containing the number of rows affected and the second result containing the actual data.
Thanks to everybody for trying helping me :)

Stored procedures are stored in the database schema I believe.
If you add the schema to your query SQL server should know where to "look" for your stored procedure.
$query = "EXEC [dbo].[sp_getToken] #userId=:userId, #pwd=:pwd";
Also when binding the parameters it might help defining the type. I've had issues with SQL server where defining the parameter typed resolved the issue.
$stmt->bindValue(':userId', $userId, PDO::PARAM_STR);
$stmt->bindValue(':pwd', $pwd, PDO::PARAM_STR);
Also, make sure that the user that PHP logs into the database has the Execute permission in SQL Server.
https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/grant-permissions-on-a-stored-procedure?view=sql-server-2017
In Object Explorer, connect to an instance of Database Engine and then expand that instance.
Expand Databases, expand the database in which the procedure belongs, and then expand Programmability.
Expand Stored Procedures, right-click the procedure to grant permissions on, and then click Properties.
From Stored Procedure Properties, select the Permissions page.
To grant permissions to a user, database role, or application role, click Search.
In Select Users or Roles, click Object Types to add or clear the users and roles you want.
Click Browse to display the list of users or roles. Select the users or roles to whom permissions should be granted.
In the Explicit Permissions grid, select the permissions to grant to the specified user or role. For a description of the permissions, see Permissions (Database Engine).
Selecting Grant indicates the grantee will be given the specified permission.
Selecting Grant With indicates that the grantee will also be able to grant the specified permission to other principals.

Related

MYSQLi Creates Database with ? as name

I wrote an Install File for my own CMS which I'm working atm. I changed the SQL statements to make it a bit saver but now nothing works and I can't figure out why...
I change my code from:
$db = new mysqli($_POST['db_ip'], $_POST['db_user'], $_POST['db_key'], '', $_POST['db_port']);
if(!$db) {
exit('Connection error to database');
}
$query = "CREATE DATABASE IF NOT EXISTS $db_name;";
$ergebnis = mysqli_query($db, $abfrage);
to:
$db = new mysqli($_POST['db_ip'], $_POST['db_user'], $_POST['db_key'], '', $_POST['db_port']);
if(!$db) {
exit('Error connecting to database'); //Should be a message a typical user could understand in production
}
$db_name = $_POST['db_name'];
$query = "CREATE DATABASE IF NOT EXISTS ?;";
$stmt->bind_param('s', $db_name);
$stmt = $db->prepare($query);
$stmt->execute();
I even tried:
$db = new mysqli($_POST['db_ip'], $_POST['db_user'], $_POST['db_key'], '', $_POST['db_port']);
if(!$db) {
exit('Error connecting to database'); //Should be a message a typical user could understand in production
}
$db_name = $_POST['db_name'];
$query = mysqli_prepare "CREATE DATABASE IF NOT EXISTS ?;";
mysqli_stmt_bind_param($query, 's', $db_name);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
last one added me a database but with the ? as name...
I hoped some one here can help me with that.
Not every SQL statement supports prepared statements. And CREATE DATABASE is one of them.
So, as a general rule, you are supposed to choose the database/table name from the white list.
In your specific case, however, when a user is apparently a database owner, there is not much point in protecting them from SQL injection as they apparently has the database password and can run any SQL statement much more convenient way. So you changed the code for nought. Just revert it back to the regular query() call.
I would only add backticks around the table name so it would always make a correct identifier name. And also may be add a regex validation just in order to avoid a human error.

PHP PDO Service No Data

I have the below REST web service that I am using to get user information from User table:
$name = htmlentities($_GET["name"]);
$name = strtoupper($name);
$dbh = new PDO("oci:dbname= $dbhost", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $dbh->prepare("select * from Users where username =:name");
$sth->bindParam(':name', $name);
$sth->execute();
$result = array();
$result["User"] = $sth->fetchAll((PDO::FETCH_ASSOC));
print_r ($result); //returns no data
When I print out the results, no data is returned. If I hard code a username value instead of using :name, then data comes back:
$sth = $dbh->prepare("select * from Users where username ='TESTUSER'");
I am not sure what I am doing wrong with the binding of the variable that is causing the SQL to run incorrectly. I tried using bindValue and bindParam and still returns no data. I am not recieving any errors, just no data.
UPDATE: It looks like the syntax is correct. Is there anything on the Oracle side that would prevent a prepared statement from being run?
I figured out why data wasn't returning on the query. The database has the username field set as a CHAR(8) and usernames that were being passed only had 7 characters so it was failing. I need to append a blank space at the end of the string for it to match.

PHP Multiple Tasks One File

I am learning the php game - and am in need of completing two tasks in one .php file. What I need is
1) Connect To Server
2) Execute Stored Procedure (runs an insert into statement)
3) When stored proc fully executes run select statement against table
4) Echo the results
This is my syntax -> and I get an error that the table tablecreatedfromproc does not exist. Is the Select statement firing before the stored proc fully executes? If I run the stored procedure manually, it executes as it should (meaning it is valid syntax) - but when I try to run it from my php file I get the error.
How should this syntax be updated so that it executes as I need it to?
//connection string
$hostname = 'hostname';
$dbname = 'dbname';
$username = 'username';
$password = 'password';
$dbh = new PDO("dblib:host=$hostname;dbname=$dbname","$username","$password");
//Parsing the passed in data
$passedparams = implode(',',$_REQUEST['passedparams']);
//Capturing the dates from passed in data
$d1 = $_REQUEST['d1'];
$d2 = $_REQUEST['d2'];
//Run Stored Procedure To Create Table
$proc = mssql_init('HoldingPattern',$conn);
mssql_bind($proc,'#d1',$d1,SQLVARCHAR);
mssql_bind($proc,'#d2',$d2,SQLVARCHAR);
//Create Query String to query newly created table
$sql = "SELECT ".$passedparams." FROM tablecreatedfromproc";
$stmt = $dbh->prepare($sql);
$stmt->execute();
you are using PDO to connect, in the same time that you are trying to execute another function mssql_* -which is removed in php7-
use PDO to execute your procedures ,
$stmt = $dbh->prepare("HoldingPattern");
$stmt->bindParam(/* your required parameters goes here */);
$stmt->execute();
as mentioned here:
If you need to get Output variable from MSSQL stored procedure, try this :
-- PROCEDURE
CREATE PROCEDURE spReturn_Int #err int OUTPUT
AS
SET #err = 11
GO
$sth = $dbh->prepare("EXECUTE spReturn_Int ?");
$sth->bindParam(1, $return_value, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT);
$sth->execute();
print "procedure returned $return_value\n";

Use prepared statements to check user override credentials, user override rights, and delete MySQL table Record

I am trying to build an override feature so users can manually remove a MySQL table row if they have the correct rights to do so. The user is prompted to input the same credentials used for program login as well as the uniqueID for the row that needs to be removed. Upon hitting the 'Submit' function, I run a series of if statements/ MySQL SELECT statements to check credentials, user rights and finally row Deletion with the result output as an alert.
However, my alert shows up blank and the row is not removed so I know there is a problem with my if statements. Upon testing, I believe the problem is when I try to use the previous query's results to run the next if statement logic.
How do I properly determine if the MySQL query returned a row using prepared statements?
All help is appreciated! Thank you!
My CODE:
if ((isset($_POST['overrideUsername'])) and (isset($_POST['overridePassword'])) and (isset($_POST['overrideUniqueID']))) {
$overridePasswordInput = $_POST['overridePassword'];
$overrideUsername = $_POST['overrideUsername'];
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
$roleID = '154';
$overrideUniqueID = $_POST['overrideUniqueID'];
//connect to the database
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if(mysqli_connect_errno() ) {
printf('Could not connect: ' . mysqli_connect_error());
exit();
}
$conn->select_db($dbname);
if(! $conn->select_db($dbname) ) {
echo 'Could not select database. '.'<BR>';
}
$sql1 = "SELECT users.id FROM users WHERE (users.login = ?) AND (users.password = ?)";
$stmt1 = $conn->prepare($sql1);
$stmt1->bind_param('ss', $overrideUsername, $overridePassword);
$stmt1->execute();
$stmt1->bind_result($userID);
//$result1 = $stmt1->get_result();
if ($stmt1->fetch()) {
$sql2 = "SELECT * FROM rolestousers WHERE (rolestousers.userid = ?) AND (rolestousers.roleid = ?)";
$stmt2 = $conn->prepare($sql2);
$stmt2->bind_param('ss', $userID, $roleID);
$stmt2->execute();
$stmt2->store_result();
if ($stmt2->fetch()) {
$sql3 = "DELETE * FROM locator_time_track_out WHERE locator_time_track_out.uniqueid = ?";
$stmt3 = $conn->prepare($sql2);
$stmt3->bind_param('s', $overrideUniqueID);
$stmt3->execute();
$stmt3->store_result();
if ($stmt3->fetch()) {
echo 'Override Successful! Please scan the unit again to close it out.';
} else {
echo 'Could Not Delete Record from the table.';
}//End $sql3 if.
} else {
echo 'User does not have override permission. Please contact the IT Department.';
}//End $sql2 if.
} else {
echo 'Your login information is incorrect. Please try again. If the issue persists, contact the IT Department.';
}//End $sql1 if.
//Free the result variable.
$stmt1->free();
$stmt2->free();
$stmt3->free();
$stmt1->close();
//Close the Database connection.
$conn->close();
}//End If statement
NOTE: I am definitely sure my DB connection information is correct. The issue resides after I connect into the database. I have also tested the code using only the first if statement and get the blank alert so I'm not making it past the first if statement.
EDIT:: My php Script was definitely failing, but even earlier than expected, at the following code:
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
So my issue is that I need to properly compare the password and encryption seed information. However, the previous programmer used the following line to do the same process (which is obviously unsafe):
$querystatement = "SELECT id, firstname, lastname, email, phone, department, employeenumber, admin, usertype FROM users WHERE login=\"".mysql_real_escape_string($user)."\" AND password=ENCODE(\"".mysql_real_escape_string($pass)."\",\"".mysql_real_escape_string(ENCRYPTION_SEED)."\")";
$queryresult = $this->db->query($querystatement);
I will need to fix this issue before I can even test the functionality of the if logic using prepared statements.
Your are passing wrong variable for delete query
$stmt3 = $conn->prepare($sql3);
Please refer [ http://www.plus2net.com/php_tutorial/pdo-delete.php ]

Why does my PHP transaction not work?

I'm working on a school project creating a CMS for my portfolio site. I am having trouble getting my update function to work. I have a feeling it has something to do with the way I'm constructing my PDO Transaction. In my database I have a projects table, category table, and the associative content_category table. I'm able to insert my projects into those tables just fine. What I want to do is insert into my projects table then delete all records from the content_category table and finally insert the current category records into that associative table to complete the transaction. I do get my return statement "Project Updated" returned. But the tables aren't being updated. Any ideas anyone?
Here's the code:
This is a function in my Project class.
public function update(){
try {
$conn = getConnection();
$conn->beginTransaction();
$sql = "UPDATE project
SET project_title = :title,
project_description = :desc,
project_isFeatured = :feat,
project_mainImage = :image
WHERE project_id = :id";
$st = $conn->prepare($sql);
$st->bindValue(":id", $this->id, PDO::PARAM_INT);
$st->bindValue(":title", $this->title, PDO::PARAM_STR);
$st->bindValue(":desc", $this->description, PDO::PARAM_STR);
$st->bindValue(":feat", $this->isFeatured, PDO::PARAM_BOOL);
$st->bindValue(":image", $this->mainImage, PDO::PARAM_INT);
$st->execute();
$sql = "DELETE from content_category
WHERE content_id = :id";
$st = $conn->prepare($sql);
$st->bindValue("id", $this->id, PDO::PARAM_INT);
$st->execute();
$sql = "INSERT into content_category (content_id, cat_id)
VALUES (?,?)";
$st = $conn->prepare($sql);
foreach($this->categories as $key=>$value){
$st->execute(array(intval($projectID), intval($value)));
}
$conn->commit();
$conn = null;
return "Project updated";
}
catch(Exception $e) {
echo $e->getMessage();
$conn->rollBack();
return "Error... Unable to update!";
}
}
Your database engine for the tables needs to be INNODB. If you are using phpMyAdmin, it defaults to MyISAM. (I don't know if that will cause the updates not to go through or just the transaction line to be ignored. Edit: Pretty sure the documentation is saying that it will throw an error and not do anything if you beginTransaction on a myISAM)
In order to make sure you are not encountering a PDO error, you should set the PDO error reporting like this:
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
There are functions in PDO such as prepare() which will either return false or throw a PDOException depending on what error mode is set. This way, it will throw an exception and you'll definitely know if you are having a problem!
Also, if your database doesn't support transactions (like MyISAM), the beginTransaction() function will return false. So, maybe add a check in there like:
if($conn->beginTransaction()) {
// Do transaction here
} else {
echo("Unable to use transactions with this database.");
}
Oddly enough, according to PHP documentation, you would be getting an exception if your database doesn't support transactions...
Unfortunately, not every database supports transactions, so PDO needs to run in what is known as "auto-commit" mode when you first open the connection. Auto-commit mode means that every query that you run has its own implicit transaction, if the database supports it, or no transaction if the database doesn't support transactions. If you need a transaction, you must use the PDO::beginTransaction() method to initiate one. If the underlying driver does not support transactions, a PDOException will be thrown (regardless of your error handling settings: this is always a serious error condition).
Commit returns TRUE on success or FALSE on failure. You can check it. Also check for errorCode.

Categories