Error calling MySQL stored procedure through PHP - php

I'm trying to call a stored procedure from MySQL and get back the two OUT parameters (#eset and #leng). I would like to echo out these two parameters back to JavaScript where I have an XMLHttpRequest waiting for the results.
I'm getting this error :
Strict standards: mysqli::next_result(): There is no next result set.
Here's my code:
<?php
//get the q parameter from URL
$q=$_GET["q"];
$eset= "";
$length= 0;
// Opens a connection to a MySQL server
$db= new mysqli('localhost', 'db_name', 'pass');
if (!$db) { die('Not connected : ' . mysql_error());}
// Set the active MySQL database
$db_selected = $db->select_db('db_name');
if (!$db_selected) {
die ('Can\'t use db : ' . mysql_error());
}
// Select all the rows in the markers table
$db->multi_query( "CALL mst2($q, #eset, #leng);SELECT #eset as eset;SELECT #leng as length" );
$db->next_result(); // flush the null RS from the call
$eset=$db->store_result(); // get the RS containing the id
//echo $eset->fetch_object()->eset, "\n";
$length= $db->store_result();
//echo $length->fetch_object()->leng, "\n";
$response= $eset.$length;
//$eset->free();
//$length->free();
//$response=str_shuffle($q);
//output the response
echo $response;
?>

I'm assuming the first argument of your stored procedure is VARCHAR, so the first problem is that you are passing the $q variable without quotes in the query. It should be like this:
$db->multi_query("CALL mst2('$q', #eset, #leng); SELECT #eset as eset; SELECT #leng as length");
Also, you don't need to make two SELECT calls, do it only once:
SELECT #eset AS eset, #leng AS leng;
Needless to say that user inputs should never be trusted. You should use prepared statements:
if (($stmt = $db->prepare("CALL mst2(?, #eset, #leng)"))) {
$stmt->bind_param("s", $q);
$stmt->execute();
$stmt->close();
if (($res = $db->query("SELECT #eset AS eset, #leng AS leng"))) {
list($eset, $leng) = $res->fetch_array();
$result = $eset.$length;
echo $result;
$res->free();
}
}

Related

How to query my table if there is an apostrophe in search term?

How can I search for a name in my table if there is an apostrophe in the name?
If I insert name with an apostrophe like Ender's Game in my search box, it gives an error.
I already tried solutions provided on stackoverflow, but I am not able to solve this.
Here is my code:
$string1 = $_GET['name'];
$quer = "SELECT * FROM info WHERE name = '$string1'";
$q = mysqli_query($conn, $quer);
If there is an apostrophe in $_GET['name'], an error is shown.
How can I solve this?
Code in that form is vulnerable to SQL injection. Use mysqli::prepare instead:
$string1 = $_GET['name'];
$quer = "SELECT * FROM info WHERE name = ?";
$stmt = $conn->prepare($quer);
$stmt->bind_param('s', $string1);
$stmt->execute();
$stmt->bind_result($result);
$stmt->fetch();
$stmt->close();
var_export($result);
If you're adapting legacy, insecure code, it may be faster to use mysqli_real_escape_string. This should be reserved as a last resort, but it's there if you need it, and it's better than a regex.
The best practice that you can expect to hear over and over again from knowledgeable StackOverflow volunteers is to use prepared statements to ensure query security and reliability.
For your case, I recommend the following snippet which not only safely executes your SELECT query, but also provides informative diagnostic/debugging checkpoints throughout the process and allows you to process the resultset - represented by an multi-dimensional associative array.
$_GET['name'] = "vinay's name";
$string1 = $_GET['name'];
if (!$conn = new mysqli("host", "user", "pass", "db")) {
echo "Database Connection Error: " , $conn->connect_error; // do not show this to public
} elseif (!$stmt = $conn->prepare("SELECT * FROM info WHERE name = ?")) {
echo "Prepare Syntax Error: " , $conn->error; // do not show this to public
} elseif (!$stmt->bind_param("s", $string1) || !$stmt->execute()) {
echo "Statement Error: " , $stmt->error; // do not show this to public
}else{
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC)){
var_export($row); // do what you like here
}
}
It is important to note that using $stmt->bind_result($result) (like in Zenexer's answer) will not work (generates $result = NULL) if the info table contains more than one column (I assume it will work with one column, but I didn't test); and it will generate a Warning because of an imbalance between the number of selected columns from SELECT * and the number of nominated variables.
Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
If you want to enjoy the benefits of explicitly binding a result variable, you should specify your desired columns in the SELECT clause like this:
if (!$conn = new mysqli("host", "user", "pass", "db")) {
echo "Database Connection Error: " , $conn->connect_error; // do not show this to public
} elseif (!$stmt = $conn->prepare("SELECT id FROM info WHERE name = ?")) {
echo "Prepare Syntax Error: " , $conn->error; // do not show this to public
} else {
if (!$stmt->bind_param("s", $string1) || !$stmt->execute() || !$stmt->bind_result($id)) {
echo "Statement Error: " , $stmt->error; // do not show this to public
} else {
while ($stmt->fetch()) {
echo "<div>$id</div>";
}
}
$stmt->close();
}

How to select a column for a MySQL table and compare it with a PHP variable

I am trying to compare a MySQL table column which I have imported to my script and compare it with a PHP value which I have defined.
I am trying to make an if loop that checks if any of the values in the column are equal to the variable.
// Connect to database containing order information
$servername = "server";
$username = "user";
$password = "pass";
// Create connection
$conn = new mysqli($servername,$username,$password);
// Check connection
if ($conn->connect_error)
{
die("Connection failed: " . $conn->connect_error);
}
// define variables and set to empty values
$name = $ordernumber = "";
// Load up data from the form
$ordernumber = ($_POST['order_number']);
// Get SQL info
$sql = "SELECT order_number FROM p_orders;";
if ($conn->query($sql) === TRUE)
{
echo "Checked Orders.....";
}
else
{
echo "Failed to check orders, please contact Support for assistance" . $conn->error;
}
// Checking Script
if ($ordernumber === $orders)
{
echo "Order Number Found.... Let's Select a Seat";
}
else
{
echo "Your Order was not found, either you did not order a reservation ticket, have not waited 3 days or you entered the number wrong. If issues persist then please contact Support."
};
The end part of the script should be like this...
$stmt = $mysqli->stmt_init();
if ($stmt->prepare('SELECT order_number FROM p_orders WHERE orderID = ?')) {
$stmt->bind_param('s',$_POST['order_number']); // i if order number is int
$stmt->execute();
$stmt->bind_result($order_number);
$stmt->fetch();
if (!empty($order_number))
echo "Order Number Found.... Let's Select a Seat";
}else {
echo "Your Order was not found...";
}
$stmt->close();
}
$mysqli->close();
...note that the query now looks for only the records that match and note the use of prepared statement to make safe the post variable from SQL Injection.
The reason to collect only the matching items from SQL is otherwise, if you have a million records, the database would return all of them and then PHP will need to loop through them (this can cause maximum execution, memory and other errors). Instead databases where built to look things up like this - note an index on this field would be good and also use of a "youtube style" id is recommended, which is why I've assumed the use of a string for it's instead of a number as the variable minght imply - and it's not the "id" which is good for a number of reasons... I've added a link to explain "youtube style" id which I'll not go into detail here but there is a lot of win in using that :)
UPDATED based on...
http://php.net/manual/en/mysqli-stmt.prepare.php
MySQL prepared statement vs normal query. Gains & Losses
https://www.youtube.com/watch?v=gocwRvLhDf8 (Will YouTube Ever Run Out Of Video IDs?)
Preferably use a WHERE clause searching for the order id and mysqli prepared statement, like below.
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$name = "";
// Load up data from the form
$ordernumber = $_POST['order_number'];
/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT COUNT(*) FROM p_orders WHERE orderID=?")) {
/* bind parameters for markers */
$stmt->bind_param("i", $ordernumber ); // "i" if order number is integer, "s" if string
/* execute query */
$stmt->execute();
/* bind result variables */
$stmt->bind_result($counter);
/* fetch value */
$stmt->fetch();
if ($counter>0) { // if order id is in array or id's
echo "Order Number Found.... Let's Select a Seat";
} else {
echo "Your Order was not found, either you did not order a reservation ticket, have not waited 3 days or you entered the number wrong. If issues persist then please contact Support."
}
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();

MySQLi Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in

I keep getting this error when deleting from a database. It worked on a different server, no error message. I'm scratching my head here. $id is a number (the id column in the MySQL table) and I can't figure it out. I've seen a few answers that matched my code, but I still get it. Here's the code.
$db = new mysqli('localhost', 'user', 'pass', 'table');
// get id number
$id=$_GET['page'];
if ($db->connect_errno) {
echo "Failed to connect to MySQL: ("
. $db->connect_errno . ") " . $db->connect_error;
}
$query =
"DELETE FROM listing WHERE id='$id'";
$conn = $db->prepare($query);
// the problem line
$conn->bind_param('i', $id);
if ($conn->execute()) {
print "Successfully deleted the entry";
} else {
echo ' No ';
$db->close();
}
The point of preparing is to not insert the variable directly - that is, so that you don't have to do WHERE id='$id'. Instead, mysqli takes care of this for you. In fact, you don't even need the quotes.
What you want is to put a placeholder there, like this:
$query = "DELETE FROM listing WHERE id = ?";
Then, when you bind the parameter later, the system looks for the placeholder:
$conn->bind_param('i', $id);
The 'i' means to treat the $id as an integer.

update mysql_num_rows to new Mysqli standard: mysqli_stmt_num_rows

I have a PHP page with some Mysqli that I am attempting to convert from MySql. I think I've converted most of it correctly, but I am getting the following error message when I try to execute the code (below):
Connection was OK!
Warning: mysqli_stmt_num_rows() expects parameter 1 to be mysqli_stmt, object given in /quantityremaining5.php on line 25
9999
I'm a bit new to this, so please be gentle - what is that I'm doing wrong? thanks!
<?php
include 'quantitytest_config.php';
// Create connection to MySQL
$link = mysqli_connect($hostname, $username, $password);
// Check connection
if (mysqli_connect_errno($link))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
} else { echo "Connection was OK!\n";}
//select a database to work with
$selected = mysqli_select_db($link, "grace59_countdown");
// or die("Could not select countdown");
// use if TWO SEPARATE columns for date and time
//execute the SQL query and return records
$result = mysqli_query($link,
"SELECT items
FROM cases
WHERE datetime<=NOW()
Limit 1 ");
if(mysqli_stmt_num_rows($result) == 0){
echo "9999";
} else {
//fetch tha data from the database
while ($row = mysqli_fetch_array($result)) {
echo "Quantity:".$row{'items'}."<br>";
}
}
//close the connection
mysqli_close($link);
?>
Use mysqli_num_rows($result) or $result->num_rows. As the name indicates, mysqli_stmt_num_rows() is intended to be used with a mysqli_stmt object (as returned by mysqli_prepare()).
See the documentation.

prepared statement causing while loop error

I have the following simple mysqli php application, which should work fine. $pk is accepted perfectly and is a valid ARTICLE_NO, and the query works perfectly when executed directly by mysql. I have put output statements after every event and all except tetsing while executes. The while loop is never entered, and I am unsure why.
edit: I have narrowed the problem down to the fact that 0 rows are returned, but I have no idea why as the same query in phpmyadmin gives the right result.
edit2: if I get rid of the while loop and just have
if (!$getRecords->fetch()) {
printf("<p>ErrorNumber: %d\n", $getRecords->errno);
}
It shows that the errno is 0. So no records are fetched, and there is no error, yet it is a valid query.
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);
$pk = $_GET["pk"];
$con = mysqli_connect("localhost", "", "", "");
if (!$con) {
echo "Can't connect to MySQL Server. Errorcode: %s\n". mysqli_connect_error();
exit;
}
$con->set_charset("utf8");
echo "test outside loop";
if(1 < 2) {
echo "test inside loop";
$query1 = 'SELECT ARTICLE_NO FROM AUCTIONS WHERE ARTICLE_NO = ?';
if ($getRecords = $con->prepare($query1)) {
echo "inside second loop";
$getRecords->bind_param("i", $pk);
echo "test after bind param";
$getRecords->execute();
echo "test after bind execute";
$getRecords->bind_result($ARTICLE_NO);
echo "test after bind result";
while ($getRecords->fetch()) {
echo "test inside while";
echo "<h1>".$ARTICLE_NO."</h1>";
}
}
}
edit:
I tried with this code:
<?php
$mysqli = new mysqli("localhost", "", "", "");
$pk = $_GET["pk"];
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* prepare statement */
if ($stmt = $mysqli->prepare("SELECT ARTICLE_NAME, WATCH FROM AUCTIONS WHERE ARTICLE_NO = ? LIMIT 5")) {
$stmt->bind_param("i", $pk);
$stmt->execute();
/* bind variables to prepared statement */
$stmt->bind_result($col1, $col2);
/* fetch values */
while ($stmt->fetch()) {
printf("%s %s\n", $col1, $col2);
}
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
?>
This works without $pk, if I take away the parameters it works fine. It is not a problem with getting pk via GET, because if I assign $pk = 1; instead it still fails. 1 is a valid ARTICLE_NO, and SELECT ARTICLE_NAME, WATCH FROM AUCTIONS WHERE ARTICLE_NO = 1 LIMIT 5 works fine in phmyadmin.
edit: the problem was that mysqli could not handle bigint, I am now using k as a string and it works fine.
Check the value of:
$getRecords->num_rows
which should help reveal whether the earlier SELECT is actually returning any data
You may need to also add:
$getRecords->store_result()
first to ensure that you've the whole query has completed before asking for the number of rows in the result set.
Also - make sure you cast $pk to an integer! It's possible that the value being passed in is getting mangled.
I'm not sure if you've modified that code, but you don't seem to be selecting the database you want to connect to there.
Use mysqli_select_db(...) for that if that is the problem.
EDIT: It also looks like you're using uppercase for the column, table name etc.
Get case sensitivity right, it could be that you're presuming case insensitivity because it works from the command line. As far as I know the mysqlI driver in PHP is case sensitive about at least column names.

Categories