PHP and mysqli: Select with multiple conditions using prepared statements - php

I'm working on some prepared statements using mysqli in a php file with a database running on InnoDB. Most of the statements are working pretty well, but I have a select statement with multiple conditions that keeps returning a syntax error in my select statement, to be specific: near ? AND section_num = ? AND dept = ? AND semester = ? AND year = ? at line 1 as well as the following error:
Call to a member function bind_param() on a non-object.
Here's the snippet of code:
if (!$rs = $mysqli->query("SELECT id FROM courses WHERE course_num = ? AND section_num = ? AND dept = ? AND semester = ? AND year = ?")) {
echo "Select Query Failed!: (" . $mysqli->errno . ") ". $mysqli->error;
}
if(!$rs->bind_param("ssssi", mysqli_real_escape_string($mysqli,$course_num), mysqli_real_escape_string($mysqli,$section_num),
mysqli_real_escape_string($mysqli,$dept), mysqli_real_escape_string($mysqli,$semester), mysqli_real_escape_string($mysqli,$year))) {
echo "Select Binding parameters failed: (" . $rs->errno .") " . $rs->error;
}
if (!$rs->execute()) {
echo "Execute select failed: (" . $rs->errno . ") " . $rs->error;
}
Any suggestions for how to form this statement to retrieve an id based on the 4 inputs would be great. Thanks!

You should be using prepare to prepare a statement, not query as that just executes a query.

$query = "
SELECT id
FROM courses
WHERE
course_num = ? AND section_num = ? AND dept = ? AND semester = ? AND year = ?
";
$rs = $mysqli->prepare($query);
$rs->bind_param("ssssi", $course_num, $section_num, $dept, $semester, $year);
$rs->execute();

Change: $mysqli->query("SELECT id ...
To: $mysqli->prepare("SELECT id ...

It is quite simple just do this
$query = "SELECT * FROM `$table_tran` WHERE `$mem_id` ='$member_id' and $status` = '$cur_status'";
$result = mysqli_query($link,$query);
It gets the data from the transaction table using the and statement.

Related

Advice on Prepared-Statements and Joins

I'm trying to build a back end solution to a web page project for a class i'm taking. The class doesn't cover anything about back end coding so I've had to learn everything myself. I want to understand how to utilize prepared statements and joins in the PHP code below. There are three tables in my database, but i only want back the data from one of them and only sometimes need to reference the other two to hone in my search.
The code currently works as expected, but is vulnerable to sql injection. I'm getting three form inputs from the user: a text input ($_POST["spell_name"]), a select element ($_POST["classList"]), and some checkboxes ($_POST["school"]). It still needs to work when the checkbox sends an empty array (none of the checkboxes are checked) and the select element sends the default value "all".
$sql = "SELECT * FROM dnd5_spells WHERE ";
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name='{$_POST["classList"]}')) AND";
};
$sql .= " spell_name LIKE '%{$_POST["spell_name"]}%'";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x = 0; $x < $valueLength; $x++) {
if ($x>0) {
$sql.= " OR";
};
$sql .= " spell_type" . " LIKE" . " '%" . $spellschools[$x] . "%'";
};
$sql .= ")";
};
$result = mysqli_query($conn, $sql);
How do i make a prepared statement when i can receive all or none of the possible input values and i don't know what i'm getting ahead of time (in my case sending the form data blank returns the entire table and this is good)? Can i iterate over an array into a prepared statement when the array can either be empty or have multiple values? Should i be concerned about including sections of the sql query when that part of the query isn't needed?
Also, i know my use of ANY could possibly be replaced with a JOIN, but i couldn't wrap my head around it and it's less important to me than figuring out the prepared statement issue.
Here is the solution I found. I needed to use PDO then build my statement as I went with prepared statements in mind, placing ? where I wanted my input data, and at the same time build an array with the corresponding data values. I doubt it's perfect but it works just as well as my initial code and is less susceptible to SQL injection.
$sql = "SELECT * FROM dnd5_spells WHERE ";
$parameters = [];
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name= ?)) AND";
$parameters[] = $_POST["classList"];
};
$sql .= " spell_name LIKE ?";
$parameters[]= "%" . $_POST["spell_name"] . "%";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x =0; $x < $valueLength; $x++){
if ($x>0){
$sql.= " OR";
};
$sql.= " spell_type LIKE ?";
$parameters[] ="%" . $spellschools[$x] . "%";
};
$sql .= ")";
};
//bind the peramaters into the prepared statment
$stmt = $conn->prepare($sql);
$stmt->execute($parameters);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

Why i am getting datatype mismatch error?

SQLSTATE[42804]: Datatype mismatch: 7 ERROR: argument of WHERE must be
type boolean, not type integer LINE 1
$sql = "SELECT mod_modulegroupcode, mod_modulegroupname FROM module "
. " WHERE 1 GROUP BY `mod_modulegroupcode` "
. " ORDER BY `mod_modulegrouporder` ASC, `mod_moduleorder` ASC ";
$stmt = $DB->prepare($sql);
$stmt->execute();
$commonModules = $stmt->fetchAll();
$sql = "SELECT mod_modulegroupcode, mod_modulegroupname, mod_modulepagename, mod_modulecode, mod_modulename FROM module "
. " WHERE 1 "
. " ORDER BY `mod_modulegrouporder` ASC, `mod_moduleorder` ASC ";
$stmt = $DB->prepare($sql);
$stmt->execute();
$allModules = $stmt->fetchAll();
$sql = "SELECT rr_modulecode, rr_create, rr_edit, rr_delete, rr_view FROM role_rights "
. " WHERE rr_rolecode = :rc "
. " ORDER BY `rr_modulecode` ASC ";
$stmt = $DB->prepare($sql);
$stmt->bindValue(":rc", $_SESSION["rolecode"]);
$stmt->execute();
$userRights = $stmt->fetchAll();
You are getting a datatype mismatch error because the where clause of a SQL statement expects you to provide conditions, not integer values. Your third query has a condition for its where clause, but your first two try to just give an integer value. There are some programming languages where 1 treated like "true", but SQL is not one of those languages.
Given that you're assembling the SQL with your code, if there's no condition to provide for the where clause, then just leave the where clause out, like this:
$sql = "SELECT mod_modulegroupcode, mod_modulegroupname FROM module "
. " GROUP BY `mod_modulegroupcode` "
. " ORDER BY `mod_modulegrouporder` ASC, `mod_moduleorder` ASC ";
But then you're going to have a problem because mod_modulegroupname is not aggregated. Since you're not doing any aggregation, I suggest just taking the GROUP BY clause out, too. You should also take the backticks out of your order by. This would leave you with:
$sql = "SELECT mod_modulegroupcode, mod_modulegroupname FROM module "
. " ORDER BY mod_modulegrouporder ASC, mod_moduleorder ASC ";
If I can kindly say so, it sounds like you should do a SQL tutorial.

php mysql query adds quotes in the end

I have set up a query as such:
$query = 'SELECT SGC.sys_id, TBL.semester, SGC.bonus, SGC.exam, SGC.ca FROM SubjectGradeComponent AS SGC, ';
$query .= '(SELECT `sys_id`, `semester` FROM AcademicYearTerm AS AYT, SubjectYearTermLevel AS SYTL WHERE academic_year = "' . $academic_year . '" AND SYTL.subject_id = ' . $subject_id . ' AND SYTL.form_level = ' . $form_level. ' AND SYTL.yearTerm_id = AYT.yearTerm_id) AS TBL ';
$query .= 'WHERE SGC.sys_id = TBL.sys_id;';
However when I run the query, $mysql->query($query);it returns an empty result with 0 rows. Running the same query on phpmyadmin shows the desired result. I have looked around but do not understand the problem.
$mysql->error does not show any error message either
EDIT:
generated query is like this:
SELECT SGC.sys_id, TBL.semester, SGC.bonus, SGC.exam, SGC.ca FROM SubjectGradeComponent AS SGC, (SELECT `sys_id`, `semester` FROM AcademicYearTerm AS AYT, SubjectYearTermLevel AS SYTL WHERE academic_year = "2018-2019" AND SYTL.subject_id = 1 AND SYTL.form_level = 1 AND SYTL.yearTerm_id = AYT.yearTerm_id) AS TBL WHERE SGC.sys_id = TBL.sys_id;""
Question is where are the "" from?
Looks like you want a JOIN query instead.
You should also use prepared statement with placeholders ? instead of injecting values directly into the query.
$query = "SELECT SGC.sys_id,
AYT.semester,
SGC.bonus,
SGC.exam,
SGC.ca
FROM SubjectGradeComponent AS SGC
JOIN AcademicYearTerm AS AYT
ON SGC.sys_id = AYT.sys_id
JOIN SubjectYearTermLevel AS SYTL
ON SYTL.yearTerm_id = AYT.yearTerm_id
WHERE academic_year = ?
AND SYTL.subject_id = ?
AND SYTL.form_level = ?";

how to do sql query check if empty without useing php

In this SQL query I select by id was set in the session but at some cases there is no found any id match the field in the table, so I put if/else statement with mysql_num_rows function to avoid error message...
So my question is: Is thre any SQL code to check if is there is value or not without using mysql_num_rows function?
SELECT *
, d_articles.ar_id
, d_articles.ar_article_title
, d_articles.ar_article_desc
, d_articles.ar_created
, d_articles.ar_link_img
, d_articles.ar_img
FROM
d_articles
WHERE
d_articles.ar_hide = 1 AND
d_articles.ar_category_id ='" . $this->session->userdata('branch_id') . "'
ORDER BY
ar_created desc limit 1
<?php
$result = mysql_query('SELECT * WHERE 1=1');
if (!$result) {
die('Invalid query: ' . mysql_error());
}
?>
FOR SQL QUERY:
$tsql = "SELECT ProductID, Name, Color, Size, ListPrice
FROM Production.Product
WHERE Name LIKE '%' + ? + '%' AND ListPrice > 0.0";
$params = array( $_REQUEST['query'] );
$getProducts = sqlsrv_query( $conn, $tsql, $params);
if ( $getProducts === false)
{ die( FormatErrors( sqlsrv_errors() ) ); }
READ MORE

PDO prepared statement not returning expected results

The prepared query returns the following resultset, when $this->show is set to saved-by-the-bell:
season
------
1
2
3
4
When I execute the following code:
$seasons = array( );
$query = $db->prepare(
"SELECT `season` " .
"FROM `tv` " .
"WHERE `show_url` = ':show' " .
"GROUP BY `season` " .
"ORDER BY `season` ASC;"
);
$query->bindParam( ':show', $this->show );
$query->execute( );
$query->setFetchMode( PDO::FETCH_OBJ );
while( $row = $query->fetch( ) )
{
$season = new stdClass;
$season->number = $row->season;
$season->title = "Season {$row->season}";
$season->url = $row->season;
$seasons[] = $season;
}
return $seasons;
$seasons is an empty array, why?
$db is an instantiated object that extends PDO.
I've tried all kinds of debugging methods, but when I echo the rowCount, it says 0. I'm still new to PDO, but I can't seem to see what's wrong here.
Thanks in advance.
Ahhh, I figured it out. I'll leave my stupidity up here, in case anyone else happens across this.
Apparently, when using prepared statements, you don't need to wrap your parameters in quotes in the SQL code.
So, the prepare statement should look like this:
$query = $db->prepare(
"SELECT `season` " .
"FROM `tv` " .
"WHERE `show_url` = :show " .
"GROUP BY `season` " .
"ORDER BY `season` ASC;"
);

Categories