function get_tags_by_criteria($gender_id, $country_id, $region_id, $city_id, $day_of_birth=NULL, $tag_id=NULL, $thread_id=NULL) {
$query = "SELECT tags.*
FROM tags, thread_tag_map, threads
WHERE thread_tag_map.thread_id = threads.id
AND thread_tag_map.tag_id = tags.id
AND threads.gender_id = $gender_id
AND threads.country_id = $country_id
AND threads.region_id = $region_id
AND threads.city_id = $city_id
AND tags.id LIKE '%$tag_id%'
AND threads.id LIKE '%$thread_id%'";
if(!$day_of_birth)
{
$query += "AND threads.min_day_of_birth <= '$day_of_birth AND threads.max_day_of_birth >= '$day_of_birth' ";
}
$query += "GROUP BY tags.name";
$result = $this->do_query($query);
return $result;
}
if no $day_of_birth is passed as an argument i want the sql to omit the 2 lines inside the if. i used:
$all_tags = $forum_model->get_tags_by_criteria(1, 1, 0, 0);
i wonder why this sql returns a error:
Couldn't execute query: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '0' at line 1
You're using the addition (+=) operator when you should be using the concatenation (.=) operator.
You should be escaping your inputs too, to avoid SQL injection - see mysql_real_escape_string()
there's missing white space between " and AND in appended string
Your problem is that you left out a ' by the date of birth.
Change it to AND threads.min_day_of_birth <= '$day_of_birth' (Note closing ' and opening )
Also, as others have pointed out, you should write $query .= instead of $query +=
(note .)
You have a SQL Injection vulnerability; you should use parameters.
Remember Bobby Tables!
.= is used for string concatenation in PHP, not +=
You can also use placeholders in your query. If an option/parameter is set the script sets the contents of the placeholder to the appropriate sql code otherwise the placeholder is empty/null.
e.g.
function get_tags_by_criteria($gender_id, $country_id, $region_id, $city_id, $day_of_birth=NULL, $tag_id=NULL, $thread_id=NULL) {
if ( !is_null($day_of_birth) ) {
$day_of_birth = "AND ('$day_of_birth' BETWEEN threads.min_day_of_birth AND threads.max_day_of_birth)"
}
$query = "
SELECT
tags.*
FROM
tags, thread_tag_map, threads
WHERE
thread_tag_map.thread_id = threads.id
AND thread_tag_map.tag_id = tags.id
AND threads.gender_id = $gender_id
AND threads.country_id = $country_id
AND threads.region_id = $region_id
AND threads.city_id = $city_id
AND tags.id LIKE '%$tag_id%'
AND threads.id LIKE '%$thread_id%'
{$day_of_birth}
GROUP BY
tags.name
";
$result = $this->do_query($query);
return $result;
}
edit: as mentioned before: keep the possible sql injection in mind.
Related
public function get_modno_sno($id)
{
$query = 'select a.model_no,a.serial_no,a.stock_id from tra_item_stock a where a.trans_id is NULL and a.model_no = '.$id.'
union
select a.model_no,a.serial_no,a.stock_id from tra_indent_issue_details_2 a where a.flag = 3 and a.model_no ='.$id;
$result = $this->db->query($query);
return $result->result();
}
When I run this query error displayed as:
column "kb234" does not exist
kb234 is character varying value passed to $id
You do not surround kb234 with quotes, so the database identifies it as a column name.
You could modify you code to include the quotes:
public function get_modno_sno($id)
{
$query = "select a.model_no,a.serial_no,a.stock_id from tra_item_stock a where a.trans_id is NULL and a.model_no = '$id'
union
select a.model_no,a.serial_no,a.stock_id from tra_indent_issue_details_2 a where a.flag = 3 and a.model_no = '$id'";
$result = $this->db->query($query);
return $result->result();
}
Note, however, that creating SQL queries by using string manipulation is a dodgy practice, that leaves your code vulnerable to SQL injection attacks. You should consider using a prepared statement.
.model_no ='.$id;
is missing an ' at the end for the union query
I am trying to implement a delete function in my MVC site. I have the following error
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'id=27' at line 1
At the moment while I am trying to fix the error I have hard coded in the id 27, I have looked through the syntax for a simple row delete everywhere (eg. http://www.w3schools.com/php/php_mysql_delete.asp) but cant seem to find why I am getting the error?
deleteItem function
function deleteItem($parameters) {
$id = '27';
if ($this->model->deleteItem( $id )) {
$this->model->hasDeleteFailed = false;
$this->model->setDeleteItemConfirmation();
return (true);
}
else
$this->model->deleteItemError ( DELETE_ITEM_ERROR_STR );
}
SQL Code
public function deleteItem($id) {
$delId = $id;
$sqlQuery = "DELETE FROM items";
$sqlQuery .= "WHERE id=$delId;";
$result = $this->getDbManager () -> executeQuery ( $sqlQuery );
}
The code
$sqlQuery = "DELETE FROM items";
$sqlQuery .= "WHERE id=$delId;";
is the problem, since your SQL statement pretty much amounts to:
DELETE FROM itemsWHERE id=$delId
Notice that there is no space between the word "items" and the word "WHERE" in the SQL statement.
Also, you might as well refactor your code to
$sqlQuery = "DELETE FROM items WHERE id=$delId";
since there is no benefit to creating the SQL statement over two strings.
Also, you NEED to properly escape your SQL input parameters to prevent SQL Injection attacks. I don't know which PHP Framework you're using, so you'll need to look at how the framework does it. Take a look at the mysqli_real_escape_string function for this.
Also, you need to validate that the $id variable is actually an integer to prevent SQL Injection, since mysqli_real_escape_string is not entirely safe on its own. Use intval for this.
In your case you only need to make sure that $id is an integer value.
Thus, you should change your code to something like:
public function deleteItem($id) {
$delId = intval($id);
if ($delId <= 0)
return /* fail since ID is invalid */;
$sqlQuery = "DELETE FROM items WHERE id=$delId;";
$result = $this->getDbManager () -> executeQuery ( $sqlQuery );
}
This:
$sqlQuery = "DELETE FROM items";
$sqlQuery .= "WHERE id=$delId;";
Should be:
$sqlQuery = "DELETE FROM items "; // note the extra space at the end
$sqlQuery .= "WHERE id=$delId;";
Or:
$sqlQuery = "DELETE FROM items";
$sqlQuery .= " WHERE id=$delId;"; // note the extra space at the beggining
public function deleteItem($id) {
$delId = $id;
$sqlQuery = "DELETE FROM items";
$sqlQuery .= " WHERE id=$delId;";
$result = $this->getDbManager () -> executeQuery ( $sqlQuery );
}
Use space in $sqlQuery as I mention.
Please help. I need to print result of this query but nothing appears
$fetch_a = "
SELECT
programs.Program_Description
FROM
programs
WHERE
programs.Programid =
('
SELECT
memberprogram.Programid
FROM
memberprogram
WHERE
memberprogram.Memberid = $Memberid &&
memberprogram.Option_No = 'Option A'
')
";
$result_a = mysqli_query($dbc, $fetch_a);
echo $result_a;
You should use fetch_row or fetch_array first
mysqli_fetch_row
example:
while($row=mysqli_fetch_row($result_a))
echo $row[0]."<br/>";
EDIT:
as far as the query is concerned:
use "WHERE programs.Programid IN" instead of "WHERE programs.Programid ="
remove the apostrophes
replace && with AND
Ok, first thing is your query is a mess. Without knowing the details of your schema design, I'd take a guess with this
// note I'm using HEREDOC format
$sql = <<<_SQL
SELECT p.Program_Description
FROM programs p
WHERE EXISTS (
SELECT 1 FROM memberprogram m
WHERE m.Option_No = 'Option A'
AND m.Memberid = ?
AND m.Programid = p.Programid
)
_SQL;
Then, you should really be using parameter binding with a prepared statement. For example
$stmt = $dbc->prepare($sql);
$stmt->bind_param('i', $Memberid); // assuming $Memberid is an integer
$stmt->execute();
$stmt->bind_result($programDescription);
$stmt->fetch();
$stmt->close();
echo $programDescription;
I'm very new to php/SQL (1 day) so forgive me if I am doing this in a backwards way.
This php below is intended to return the 100 most recent entries into the DB. I attempt to do it by selecting 100 entries to be returned and sort by the date(time stamp) the entry was made. Will this return the 100 more recent entries to the DB? Or am I understanding this wrong?
$type = isset($_GET['type']) ? $_GET['type'] : "global";
$offset = isset($_GET['offset']) ? $_GET['offset'] : "0";
$count = isset($_GET['count']) ? $_GET['count'] : "100";
$sort = isset($_GET['sort']) ? $_GET['sort'] : "date DESC";
// Localize the GET variables
$udid = isset($_GET['udid']) ? $_GET['udid'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";
// Protect against sql injections
$type = mysql_real_escape_string($type);
$offset = mysql_real_escape_string($offset);
$count = mysql_real_escape_string($count);
$sort = mysql_real_escape_string($sort);
$udid = mysql_real_escape_string($udid);
$name = mysql_real_escape_string($name);
// Build the sql query
$sql = "SELECT * FROM $table WHERE ";
switch($type) {
case "global":
$sql .= "1 ";
break;
case "device":
$sql .= "udid = '$udid' ";
break;
case "name":
$sql .= "name = '$name' ";
break;
}
$sql .= "ORDER BY $sort ";
$sql .= "LIMIT $offset,$count ";
$result = mysql_query($sql,$conn);
if(!$result) {
die("Error retrieving scores " . mysql_error());
}
//echo $result;
$rows = array();
while($row = mysql_fetch_assoc($result)) {
$rows[] = $row;
}
This should work, although date is a MySQL keyword, so you would either need to enclose date in backquotes or rename that column.
Also, definitely make sure you've sanitized those inputs before building your query. Building a query off of user-editable values from $_GET or $_POST with no sanitation is very unsafe.
For WHERE parameters, you should be running mysql_real_escape_string() on those (which I see you are, I'm not sure if you were before or not). That's enough because you're wrapping those values in quotes in your query, and since you're escaping that string, any attempt to break out of those quotes won't work.
For the stuff like the ORDER BY you have, I would define a valid "list" of allowed values and check to make sure your parameter is in that list. For example:
$valid_orderbys = array('`date` DESC', '`date` ASC', '`name` DESC', '`name` ASC');
if (in_array($_GET['sort'], $valid_orderbys))
{
// you're good, you can use this value
}
else
{
// unexpected value, either alert the user or
// use a default value you define
}
Or for LIMIT, you could use PHP's built-in is_numeric() to verify that the value you're being given is a number, not a crafted string.
It's not enough to simply escape the $table, ORDER BY and LIMIT parameters because they're not wrapped in quotes and therefore someone can just maliciously inject a value of ; DROP TABLE whatever; --. This ends up making your query something like:
SELECT * FROM ; DROP TABLE whatever; --WHERE ...
Queries are separated by semicolons, so there are three queries here. The first fails because it's invalid, the second succeeds in dropping the table, and the third is just a comment so nothing happens. But you can see, if you let users throw whatever they want as one of those parameters, it's a wide open security hole. (I'm not sure if enclosing the table name in backquotes helps this, someone let me know if you know. But in any case, you can do the same attack on the LIMIT and ORDER BY parameters.)
If you have a unique, auto-increment ID for each record (as you should), it would be more efficient to ORDER BY id DESC.
Actually, you already got it right. You should only look into specifying the columns instead of using *.
I want to make an category-system CMS. Everything is fine, except a big trouble.
How can I can handle and generate the mysql query depends by some inputs like:
site.com/some-category&sortby=views&from=smt&anotherInput=key
For example, for this input my query should be something like
SELECT * FROM `articles` WHERE from='smt' AND afield='key' ORDER BY VIEWS
But these inputs will be different. How I can write this code? I don't know much things about designs patterns, but, I've heard about Factory pattern, is this a part of my solution?
Than
Factory pattern can help you with e.g. connecting/quering various databases without need to rewrite the entire code. This has nothing to do about query itself.
You can look at PDO extension, I usually use it together with prepared statements.
It will let you write queries like this:
$prepare = $db->prepare('
SELECT
*
FROM
articles
WHERE
from=:from AND afield=:afield
ORDER BY
views
');
$prepare->bindValue(':from', $_GET['from'], PDO::PARAM_STR);
$prepare->bindValue(':afield', $_GET['afield'], PDO::PARAM_STR);
$prepare->execute();
return $prepare;
The good thing about it is that you don't need to protect this from sql injections as PDO makes it for you. Also, the query is cached and you can run it several times with different params.
Very bad practice to use raw GET params in query directly, i.e. you shouldn't make constructions like
SELECT * FROM articles WHERE from=$_GET['from'] AND afield='key' ORDER BY VIEWS
but instead something like
if ($_GET['from'] == 'smt') $from = 'smt'
SELECT * FROM articles WHERE from='$from' AND afield='key' ORDER BY VIEWS
and so on
P.S. keyword is 'sql injection'
You can build the query string as pieces depending on what you need:
$query = "SELECT * FROM `articles` WHERE 1 = 1";
$where = ''
if (isset($_GET['from'])) {
$where .= " AND `from` = '" . mysql_real_escape_string($_GET['from']) . "'"
}
if (isset($_GET['anotherInput'])) {
$where .= " AND `from` = '" . mysql_real_escape_string($_GET['anotherInput']) . "'"
}
if (isset($_GET['sortby'] == 'views') {
$orderby = " ORDER BY `views` DESC"
} else {
$orderby = " ORDER BY `id` DESC"
}
$query = $query . $where . $orderby;
$result = mysql_query($query);
This is sort of the straight PHP/MySQL way, but I actually do suggest that you use prepared statements as in Pavel Dubinin's answer.
This has nothing to do with patterns. Use the $_GET superglobal variable to dynamically generate your query string.
$query = "SELECT * FROM articles WHERE from='".
$_GET['from'].
"' AND afield='".
$_GET['anotherInput'].
"' ORDER BY ".
$_GET['sortby'];
Disclaimer: This is prone to SQL injection. Use input escaping and prepared statements, ex PDO, in a production environment like:
$query = "SELECT * FROM articles WHERE from='?' AND afield='?' ORDER BY ?";
$clean_from = htmlentities($_POST['from'], ENT_QUOTES, 'UTF-8');
$clean_anotherInput = htmlentities($_POST['anotherInput'], ENT_QUOTES, 'UTF-8');
$clean_sortby = htmlentities($_POST['sortby'], ENT_QUOTES, 'UTF-8');
$clean_inputs = array($clean_from, $clean_anotherInput, $clean_sortby);
$sth = $dbh->prepare($query);
$sth->execute($clean_inputs);