I simply want to execute a MySQL stored procedure. But I want to use the parameter parsing technique for all the usual reasons. So I've taken the example from the php manual here and now have this:
$stmt = $dbh->prepare("CALL update_bug_status(?,?)");
$stmt->bindParam(1, $bug_id);
$stmt->bindParam(2, $bug_status);
$stmt->execute();
The missing piece of the puzzle is the $dbh variable, which the manual seems to forget to mention!
I thought for $dbh I could use an ODBC connection variable like this:
$connection_string = "DRIVER={MySQL ODBC 5.1 Driver};Server=10.32.27.6;Database=bugs";
$dbh=odbc_connect($connection_string,'root','xxxxxx');
But this doesn't work because 'odbc_connect' simply returns an id number.
I've seen other examples that seem to make use of mysql specific functions. But I don't have these functions available so I want an answer that uses standard ODBC functions if possible.
You are using a PDO method on an ODBC connection (see the menu on the left to see which portion of the manual you are in), and you should use odbc_prepare and odbc_execute (either that, or rather then doing an odbc_connect use the PDO driver).
Related
I have used mysql_query() throughout my project; but I've just learned that mysql_ was deprecated as of PHP 5.5, has been removed in PHP 7.
So, I would like to know if I can replace all mysql_ functions with mysqli_ in my project blindly? For example, just replacing mysql_query() with mysqli_query(). Is there any adverse effect?
The short answer is no, the functions are not equivalent.
The good news is there is a converter tool that will help you if you've got a lot of calls/projects to change. This will allow your scripts to work right away.
https://github.com/philip/MySQLConverterTool
It's a forked version of the Oracle original version, and it's kosher.
That said, it's not too difficult to update your code, and you might want to migrate to an object orientated methodology anyway ...
1) The Connection
For all intents and purposes, you need a new connection function that saves the connection as a PHP variable, for example;
$mysqli = new mysqli($host, $username, $password, $database);
Notice I've saved the connection to $mysqli. You can save to $db or whatever you like, but you should use this throughout your code to reference the connection.
Remember to enable error reporting for mysqli before opening the connection;
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
2) The Query
Note: You should protect against SQL injection with prepared statements, which are available in MySQLi. Take a look at How can I prevent SQL injection in PHP?, but I'm just going to cover the basics here.
You now have to include the connection as an argument in your query, and other mysqli_ functions. In procedural code it's the first argument, in OO you write it like a class method.
Procedural:
$result = mysqli_query($mysqli, $sql);
OO:
$result = $mysqli->query($sql);
3) Fetch Result
The fetching of the result is similar to the old mysql_ function in procedural;
while ($row = mysqli_fetch_assoc($result))
but as $result is now an object in mysqli, you can use the object function call;
while ($row = $result->fetch_assoc())
4) Close Connection
So as before, you need to include the connection in the close function; as an argument in procedural;
mysqli_close($mysqli);
and as the object that you run the function on in OO;
$mysqli->close();
I would be here forever if I went through them all, but you get the idea. Take a look at the documentation for more information. Don't forget to convert any connection close, result release, or error and row counting functions you have.
The basic rule of thumb is for functions that use the database connection, you need to include it in the function now (either as the first argument in procedural, or the object you use to call the function in OO), or for a result set you can just change the function to mysqli_ or use the result set as the object.
If you cannot convert all calls to the mysqli functions on a old project, you could install and include the library php7-mysql-shim.
It will try to create a transparent replacement for mysql on PHP 7 using mysqli.
Obviously the performance is slower, but it's a solution to get around the problem in a couple of minutes.
You may safely include the library in projects working with PHP 5.6 (it will be ignored).
if (defined('PHP_VERSION_ID') && (PHP_VERSION_ID >= 50600)) { require_once "mysql-shim.php"; }
You can't. some of the functions of mysql and mysqli require different parameters. So you should know which will use the same parameters.
The question is a fairly open one. I've been using Stored Procs with MS SQLServer for some time with classic ASP and ASP.net and love them, lots.
I have a small hobby project I'm working on and for various reasons have gone the LAMP route. Any hints/tricks/traps or good starting points to get into using stored procedures with MySQL and PHP5? My version of MySQL supports Stored Procedures.
#michal kralik - unfortunately there's a bug with the MySQL C API that PDO uses which means that running your code as above with some versions of MySQL results in the error:
"Syntax error or access violation: 1414 OUT or INOUT argument $parameter_number for routine $procedure_name is not a variable or NEW pseudo-variable".
You can see the bug report on bugs.mysql.com. It's been fixed for version 5.5.3+ & 6.0.8+.
To workaround the issue, you would need to separate in & out parameters, and use user variables to store the result like this:
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(:in_string, #out_string)");
$stmt->bindParam(':in_string', 'hello');
// call the stored procedure
$stmt->execute();
// fetch the output
$outputArray = $this->dbh->query("select #out_string")->fetch(PDO::FETCH_ASSOC);
print "procedure returned " . $outputArray['#out_string'] . "\n";
Forget about mysqli, it's much harder to use than PDO and should have been already removed. It is true that it introduced huge improvements over mysql, but to achieve the same effect in mysqli sometimes requires enormous effort over PDO i.e. associative fetchAll.
Instead, take a look at PDO, specifically
prepared statements and stored procedures.
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $value\n";
It isn't actually mandatory to use mysqli or PDO to call stored procedures in MySQL 5. You can call them just fine with the old mysql_ functions. The only thing you can't do is return multiple result sets.
I've found that returning multiple result sets is somewhat error prone anyway; it does work in some cases but only if the application remembers to consume them all, otherwise the connection is left in a broken state.
You'll need to use MySQLI (MySQL Improved Extension) to call stored procedures. Here's how you would call an SP:
$mysqli = new MySQLI(user,pass,db);
$result = $mysqli->query("CALL sp_mysp()");
When using SPs you'll need close first resultset or you'll receive an error. Here's some more information :
http://blog.rvdavid.net/using-stored-procedures-mysqli-in-php-5/
(broken link)
Alternatively, you can use Prepared Statements, which I find very straight-forward:
$stmt = $mysqli->prepare("SELECT Phone FROM MyTable WHERE Name=?");
$stmt->bind_param("s", $myName);
$stmt->execute();
MySQLI Documentation: http://no.php.net/manual/en/book.mysqli.php
I have been using ADODB, which is a great thing for abstracting actual commands to make it portable between different SQL Servers (ie mysql to mssql). However, Stored procedures do not appear to be directly supported. What this means, is that I have run a SQL query as if it is a normal one, but to "call" the SP.
An example query:
$query = "Call HeatMatchInsert('$mMatch', '$mOpponent', '$mDate', $mPlayers, $mRound, '$mMap', '$mServer', '$mPassword', '$mGame', $mSeason, $mMatchType)";
This isn't accounting for returned data,which is important. I'm guessing that this would be done by setting a #Var , that you can select yourself as the return #Variable .
To be Abstract though, although making a first php stored procedure based web app was very difficult to work around (mssql is very well documented, this is not), It's great after its done - changes are very easy to make due to the seperation.
I'm currently working with PHP 5.4.x and SQL Server 7 and I'm having TONS of issues with the PDO object for the ODBC Driver (Which is the only one that works on Sql Server 7), Statements throw errors everywhere ....
I finally got it working using PDO::query() method, BUT I need to escape the Input .... And PDO::quote IS NOT WORKING, I red the Documentation on php pdo docs about PDO and it says that PDO::quote is Not well implemented on PDO_ODBC, which might explain why im getting errors.
For Example: this
$escapedString = $pdoObject->quote($myQueryString);
returns False, it does not return the escaped string.
That been said,
Do you know a good way to escape input to prevent SQL INJECTION???
PS: Due to driver issues (old tech) I CANNOT Trust in SQL Statements, so is not an option.
Any ideas??
EDIT:
For Example. This does not work
getQueryFromFile is only retrieving a query from a file.
and SqlServerPdo is just a wrapper class I wrote over the PHP PDO so I get the connection as a Singleton
For the Record, the query actually WORKS, it has been tested on the Sql Server Engine
$conn = SqlServerPdo::connect();
$query = SqlServerPdo::getQueryFromFile('STUDENTS_FIND');
$statement = $conn->prepare($query);
$statement->bindParam(':id', $id, PDO::PARAM_INT);}
$statement->execute();
This throws the error:
text is incompatible with int (SQLExecute[206] at ext\pdo_odbc\odbc_stmt.c:133)
It seems as if the statement is treating the :id param as a text, not as an INT.
bindValue returns the same error
I want to optimize this section of code a bit to use an array such as $_SESSION['user']= $arr;.
// Store user db info in session for use
$stmt = $mysqli->prepare("SELECT id,user,pass,email,timezone,lastIP,currIP,dtLastLogin,dtCurrLogin FROM test_users WHERE user = ?");
// bind params
$stmt->bind_param('s', $user);
// execute prepared statement
$stmt->execute();
// Bind result variables
$stmt->bind_result($_SESSION['id'], $_SESSION['user'], $_SESSION['pass'], $_SESSION['email'], $_SESSION['timezone'], $_SESSION['lastIP'], $_SESSION['currIP'], $_SESSION['dtLastLogin'], $_SESSION['dtCurrLogin']);
// fetch values
$stmt->fetch();
// close statement
$stmt->close();
I tried using :
$rs = $stmt->get_result();
$arr = $rs->fetch_all(MYSQLI_ASSOC);
// close statement
$stmt->close();
//store array into session
$_SESSION['user']= $arr;
but I received a Call to undefined method mysqli_stmt::get_result(). I have php 5.3.8 and MySQL 5.1.70-cll running.
mysqli_stmt::get_result is only available if you are running the MySQL native driver (mysqlnd).
This is documented in the manual page for the method.
To clarify:
There are three ways of accessing a MySQL database from PHP: the ancient mysql functions, the modern mysqli functions/class, and the PDO mysql extension.
All three of these interact with the database in the same way, using the library called libmysqlclient. Properly speaking, this is not part of PHP. It is a C library, which PHP uses.
In PHP 5.3, however, the mysqlnd driver was introduced. This is a native part of PHP (that's what the n stands for). In 5.3, it needs to be installed deliberately. From 5.4, it is the default way to access MySQL.
So to get it working, either install PHP 5.4 or compile PHP 5.3 with the options given in the installation page for mysqlnd.
In the meantime, your method is probably the best to get the data. The only other way would be to use PDO instead, which might offer a nicer syntax. This, for instance, would be possible:
$stmt = $dbh->prepare("SELECT id,user,pass,email,timezone,lastIP,currIP,dtLastLogin,dtCurrLogin FROM test_users WHERE user = :user");
$stmt->bindParam(':user', $user);
$stmt->execute();
$_SESSION['user'] = $stmt->fetch(PDO::FETCH_ASSOC);
The question is a fairly open one. I've been using Stored Procs with MS SQLServer for some time with classic ASP and ASP.net and love them, lots.
I have a small hobby project I'm working on and for various reasons have gone the LAMP route. Any hints/tricks/traps or good starting points to get into using stored procedures with MySQL and PHP5? My version of MySQL supports Stored Procedures.
#michal kralik - unfortunately there's a bug with the MySQL C API that PDO uses which means that running your code as above with some versions of MySQL results in the error:
"Syntax error or access violation: 1414 OUT or INOUT argument $parameter_number for routine $procedure_name is not a variable or NEW pseudo-variable".
You can see the bug report on bugs.mysql.com. It's been fixed for version 5.5.3+ & 6.0.8+.
To workaround the issue, you would need to separate in & out parameters, and use user variables to store the result like this:
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(:in_string, #out_string)");
$stmt->bindParam(':in_string', 'hello');
// call the stored procedure
$stmt->execute();
// fetch the output
$outputArray = $this->dbh->query("select #out_string")->fetch(PDO::FETCH_ASSOC);
print "procedure returned " . $outputArray['#out_string'] . "\n";
Forget about mysqli, it's much harder to use than PDO and should have been already removed. It is true that it introduced huge improvements over mysql, but to achieve the same effect in mysqli sometimes requires enormous effort over PDO i.e. associative fetchAll.
Instead, take a look at PDO, specifically
prepared statements and stored procedures.
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $value\n";
It isn't actually mandatory to use mysqli or PDO to call stored procedures in MySQL 5. You can call them just fine with the old mysql_ functions. The only thing you can't do is return multiple result sets.
I've found that returning multiple result sets is somewhat error prone anyway; it does work in some cases but only if the application remembers to consume them all, otherwise the connection is left in a broken state.
You'll need to use MySQLI (MySQL Improved Extension) to call stored procedures. Here's how you would call an SP:
$mysqli = new MySQLI(user,pass,db);
$result = $mysqli->query("CALL sp_mysp()");
When using SPs you'll need close first resultset or you'll receive an error. Here's some more information :
http://blog.rvdavid.net/using-stored-procedures-mysqli-in-php-5/
(broken link)
Alternatively, you can use Prepared Statements, which I find very straight-forward:
$stmt = $mysqli->prepare("SELECT Phone FROM MyTable WHERE Name=?");
$stmt->bind_param("s", $myName);
$stmt->execute();
MySQLI Documentation: http://no.php.net/manual/en/book.mysqli.php
I have been using ADODB, which is a great thing for abstracting actual commands to make it portable between different SQL Servers (ie mysql to mssql). However, Stored procedures do not appear to be directly supported. What this means, is that I have run a SQL query as if it is a normal one, but to "call" the SP.
An example query:
$query = "Call HeatMatchInsert('$mMatch', '$mOpponent', '$mDate', $mPlayers, $mRound, '$mMap', '$mServer', '$mPassword', '$mGame', $mSeason, $mMatchType)";
This isn't accounting for returned data,which is important. I'm guessing that this would be done by setting a #Var , that you can select yourself as the return #Variable .
To be Abstract though, although making a first php stored procedure based web app was very difficult to work around (mssql is very well documented, this is not), It's great after its done - changes are very easy to make due to the seperation.