I am using mysql to create a search function from a database, however from the way the rest of the program is designed the user must only return 1 result from the info they enter. That is fine for me to program errors and such but I am having trouble accepting multiple strings as inputs to select the data from the table?
How do I make people be able to enter a combination of multiple fields (firstname, phone) etc. and come up with the results that match them without having the empty fields skew the results? i.e(Phone number is blank so only returning people with blank phone numbers)?
SELECT * FROM `users` WHERE `First_Name` = '$_SESSION[queryfname]
At the moment above is what the query is and I am unsure of what function to use (AND, OR) any help would be appreciated. Thanks it advance.
Generally this is something you would handle in your programming language (seems to be PHP here), and only query for the fields you are provided. You could do that like so :
$wheres = array('1=1');
if($_SESSION['queryfname']){
$wheres[] = "`First_Name` = '{$_SESSION['queryfname']}'";
}
if($_SESSION['querypnumber']){
$wheres[] = "`Phone_Number` = '{$_SESSION['querypnumber']}'";
}
$sql = "
SELECT *
FROM `users`
WHERE " . implode($wheres,' AND ');
however if you are limited to doing it in your SQL, you could do something like this
SELECT
*
FROM `users`
WHERE
(
`First_Name` = '{$_SESSION['queryfname']}'
AND
`First_Name != ''
)
OR --Could also be AND
(
`Phone_Number` = '{$_SESSION['querypnumber']}'
AND
`Phone_Number` != ''
)
LIMIT 1
You can try the limit:
SELECT * FROM `users` WHERE `First_Name` = '$_SESSION[queryfname] LIMIT 1;
Related
Good afternoon all,
I'm in the finishing stages of making a website where users can register and login. After that they can upload documents such as .pdf and .docx and search for those documents. The users data gets stored in my users table which contains following:
idUsers int(11) PRIMARY KEY NOT NULL,
uidUsers TINYTEXT NOT NULL,
emailUsers TINYTEXT NOT NULL,
pwdUsers LONGTEXT NOT NULL,
Then I have a table called "files" where the files that are being uploaded by the user i stored. The table contains following:
id int(11) PRIMARY KEY NOT NULL,
usersId int(11) NOT NULL, - (Foreign key for idUsers in users table)
name varchar(255) NOT NULL,
title varchar(255) NOT NULL,
forfatter varchar(255) NOT NULL, (forfatter = author)
size int(11),
download int(11) (for later use)
So when a specific user are logged in and uploads document, the users "id" (primary key in users table) gets passed to "usersId" in my files table.
All of this is working perfectly fine so far.
Then the user are able to use a search function, where the user can search for name, title and author of the document, which also works fine.
I only need to make sure the user only can see the documents, that are being uploaded by themselves. But I can't figure it out. I've tried many different solutions so far.
I've tried a suggestion i saw, where i tried to make my mysqli_query look like this:
"
SELECT *
FROM files
WHERE id
AND usersId name LIKE '%$searchingq%'
OR title LIKE '%$searchingq%'
OR forfatter LIKE '%$searchingq%'
AND usersId='.$usersId.'"
That wasn't working out well. It felt like the sessions wasn't finding the id of the current $_SESSION.
My search .php looks like this:
$usersId = $_SESSION['userId'];
$output = '';
if (isset($_GET['search']) && $_GET['search'] !== ' ') {
$searchingq = $_GET['search'];
$q = mysqli_query($conn, "SELECT * FROM files WHERE `usersId` = {$usersId} AND (`name` LIKE '%{$searchingq}%' OR `title` LIKE '%{$searchingq}%' OR `forfatter` LIKE '%{$searchingq}% )");
$c = mysqli_num_rows($q);
if($c == 0) {
$output = '<p>No search results for: "' .$searchingq. '"</p>';
} else {
while($row = mysqli_fetch_array($q)) {
$name = $row['name'];
$title = $row['title'];
$forfatter = $row['forfatter'];
$download = $row['downloads'];
$output .=
Help is very appreciated!
When doing code like this, I like to first run the query itself just to get it right.
This type of filtering should be easy because you already have each file associated to a user.
The base query would be like this:
Assuming you are looking for files for user 99.
This is the basic query and is intended only to show how to get the files for a user. This does not go into the code.
SELECT * FROM files
WHERE `usersId` = 99
This would give you only files that belong to that user. Again, this is only to explain the query, not to go in the code.
Now let's add to the above query to include the search criteria. Assume we are looking for 'foo'
SELECT * FROM files
WHERE `usersId` = 99
AND (`name` LIKE '%foo%'
OR `title` LIKE '%foo%'
OR `forfatter` LIKE '%foo%' )
We now have a query we can use in code. Try this out by running it directly against your database.
This query says to find all the files for that user when any of the columns match the search criteria. You can, therefore, write this in PHP something like this:
(Some code has been removed for the sake of brevity)
$usersId = $_SESSION['userId']; // the user id of the logged in user.
// code removed
$searchingq = $_GET['search']; // the search string
$q = mysqli_query($conn, "
SELECT * FROM files
WHERE `usersId` = {$usersId}
AND (`name` LIKE '%{$searchingq}%'
OR `title` LIKE '%{$searchingq}%'
OR `forfatter` LIKE '%{$searchingq}% )";
while($row = mysqli_fetch_array($q)) {
// Do output here
}
The following is how to do it with prepared statements.
You can learn more about Prepared Statements here: https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
$stmt = $mysqli_prepare($conn, "
SELECT * FROM files
WHERE `usersId` = ?
AND (`name` LIKE '%?%'
OR `title` LIKE '%?%'
OR `forfatter` LIKE '%?% )");
// Replace the ?'s with the actual values.
mysqli_stmt_bind_param($stmt, "isss", $usersId, $searchingq, $searchingq, $searchingq);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
// output goes here
}
Maybe you could try adding AND usersId=".$userId to the end of your query.
I have fields id and date defined as VARCHAR(16)
When I do this query:
SELECT *
FROM `members`
WHERE `id` = '4412040999876'
AND `date` = '201706054783'
I get no results.
When I do it like this:
SELECT *
FROM `members`
WHERE `id` = 4412040999876
AND `date` = 201706054783
Note - without the quotes - I get the result I am expecting.
EDIT: Here is the code used - I am not manually adding quotes. CI's DB class is adding them.
public function get_member_match($id, $mem, $field = 'name')
{
$sql = "
SELECT *
FROM `members`
WHERE `id` = ?
AND `" . $field . "` = ?
";
$sql_array = array($id, $mem);
$q = $this->db->query($sql, $sql_array);
return $q->result_array();
}
And I call this function as:
$this->members_model->get_member_match($id, $date, 'date');
I output the query, and the variables are matched correctly, no errors, only the quotes.
Any idea why? I never had this problem before. Working on CodeIgniter 3 using Query Builder.
EDIT2: Summary of findings so far:
Localhost (MySQL 5.6.24) works, server (MySQL 5.5.55-0+deb7u1) doesn't.
The problem occurs in my code and in PHPMyAdmin on the server but works locally, so I eliminate a code issue.
The show variables like 'char%' query shows all character set settings identical on local and on the server.
Database and fields have the same encoding on both server and local.
Does not seem to be a casting issue as many of the comments suggest, as the problem is not present on localhost, only on the server, unless the server has config or other issues.
...?
id might be defined as integer in your database. To match against integer fields you do not need to use quotes. Quotes are used when you match against string or text fields.
This should cast it back from the codeigniter's auto cast:
SELECT *
FROM `members`
WHERE `id` = '4412040999876'
AND `date` = '201706054783'
SELECT *
FROM `members`
WHERE CAST(`id` as INTEGER) = '4412040999876'
AND `date` = '201706054783'
Try to use this
$this->db->from('members');
$this->db->where('id',$id);
$this->db->where($field,$mem);
$q = $this->db->get();
return $q->result_array();
It's because the quotes imply that it is a string, whereas id field is an integer and must be written without quotes.
Same for date. Internally date is stored as an integer but is able to convert string into dates as long as they have an appropriate format
I am attempting to write a search algorithm, nothing too advanced but it isnt just WHERE field1 = 'searchtext'. I am trying to search all keywords across multiple fields.
I have done a bit of searching and it seems as though my take on the matter is not compliant with MySQL's use of 'IN' with other functions, however I cannot find anything that seems to suggest a better way either here on stackoverflow or using google on independant blogs and other tutorial sites.
$fields = array('type','suburb','postcode','address'); // Fields in db being searched
$queried = $db->real_escape_string($_REQUEST['keyword']); // Input from form
$keys = explode(" ",$queried); // Determine individual keywords
$sql = "SELECT * FROM `properties` WHERE "; // Beginning of SQL Statement
$frc = 0; // Field Counter
foreach($fields as $f){
$inner = ''; // Reset $inner each run
$irc = 0; // Reset Inner Counter each run
$frc++; // Increase Field Counter
if($frc != 1){ $sql .= " OR "; } // All except first runthrough
$sql .= "`".$f."` IN "; // `field` IN
foreach($keys as $k){
$irc++; // Increase inner counter
if($irc == 1){
$inner .= "('%".$k."%'"; // First Inner per run (aka each keyword)
}else{
$inner .= ", '%".$k."%'"; // All other Inners
}
}
$inner .= ")"; // Inner finishes run before reset
$sql .= $inner; // Add Inner to SQL ready for query
}
$sql .= ";"; // Clean finish to SQL statement
$SearchProperties = $db->query($sql); // Run Query
I have included commentary to help you understand my messy code and what I felt I was doing. The code is giving me the expected output, for example if I search the keyword "house" my output is as follows;
$queried = house 3064
$sql = SELECT * FROM `properties` WHERE `type` IN ('%house%', '%3064%') OR `suburb` IN ('%house%', '%3064%') OR `postcode` IN ('%house%', '%3064%') OR `address` IN ('%house%', '%3064%');
Within the type column there is house and townhouse, it should be able to hit both, and should hit anything with the postcode 3064 regardless of if it has house in another column (According to what I want to accomplish)
However after several hours of searching, although my output is as desired I don't believe it to be correct. Could anybody help shed some light on the CORRECT method of solving my quandry and WHY this does not work? I always like to understand and learn from these sort of misunderstandings.
Thank you for your help.
If you have wildcards, you want like rather than in:
SELECT *
FROM `properties`
WHERE (`type` LIKE '%house%') OR
(`suburb` LIKE '%house%') OR
(`postcode` LIKE '%house%') OR
(`address` LIKE '%house%');
However, I would strongly suggest that you investigate full text indexes (see here). The use of MATCH() may greatly simplify your efforts.
EDIT:
Your query is still incorrect. And you should still be using like:
SELECT *
FROM `properties`
WHERE (`type` LIKE '%house%' or type like '%3064%') OR
(`suburb` LIKE '%house%' or suburb like '%3064%') OR
(`postcode` LIKE '%house%' or postcode like '%3064%') OR
(`address` LIKE '%house%' or address like '%3064%');
Try change 'IN' to 'LIKE'.
For example
$queried = house
$sql = SELECT * FROM `properties` WHERE
`type` LIKE '%house%'
OR `suburb` LIKE '%house%'
OR `postcode` LIKE '%house%'
OR `address` LIKE '%house%';
If you have a several keywords, then you need change query.
For example
$queried = house 3064
$sql = SELECT * FROM `properties` WHERE
(`type` LIKE '%house%' AND `type` LIKE '%3064%')
OR (`suburb` LIKE '%house%' AND `suburb` LIKE '%3064%')
OR (`postcode` LIKE '%house%' AND `postcode` LIKE '%3064%')
OR (`address` LIKE '%house%' AND `address` LIKE '%3064%');
I'm trying to write a search function and am using multiple drop-down lists for search criteria.
i have a sql statement like
SELECT * FROM TABLE WHERE OFFICE='$office', NAME='$name', DEPARTMENT='$department';
Sometime I want to search with specific 'name' but without talking about 'department' and 'office'. But when I pass Blank '' to '$office' and '$department' it only return the person with no office and department. Is there anyway around to overcome it?
I tried to use '%' instead of blank but it didn't work as well.
I'm coding with php and MSSQL.
Thanks in Advance
If you want to work with wildcards, you dont need =, but LIKE. Unsure if this query works, but try it:
SELECT * FROM TABLE WHERE OFFICE LIKE '$office', NAME LIKE '$name', DEPARTMENT LIKE '$department';
Now you just have to check if the field is blank, if yes, replace it with a %. As i said, im unsure. I dont have a database availible at the moment for testing this.
for achieving this you have to write some php code like
$sql = "SELECT * FROM TABLE WHERE";
if(isset($office)){
$sql .= "OFFICE='$office',";
}
if(isset($name)){
$sql .= " NAME='$name',";
}
if(isset($department)){
$sql .= " DEPARTMENT='$department'";
}
You can easily do this as follow:
if(isset($office) && isset($department)){
$sql = "SELECT * FROM TABLE WHERE OFFICE='$office', NAME='$name', DEPARTMENT='$department'";
}
else{
$sql = "SELECT * FROM TABLE WHERE NAME LIKE '$name'";
}
mysql_query($connection, $sql);
look at this table please
table
|id| |name| |order|
i must get the rows, where name = something and order = somevalue
so i write
select `id` from `table` where `name` = 'something' and `order` = 'somevalue'
but depend on php logic, sometimes i need to get all rows, where name = something, independently of order value. i don't want to change the query structure, because in practise there are many number of fields, and possible count of queries will become very big. so i want to save the structure of query, and when i need to select just by name, i want to write something like this:
select `id` from `table` where `name` = 'something' and `order` = any value
is it possible?
thanks
Well, it's kind of a hack, but if you really need to do this, it'll work like this:
select `id` from `table` where `name` = 'something' and `order` = `order`
Then you're just saying "wherever order is the same as itself", so it's always true.
No, this is not possible. You need to change the structure (optionally to a LIKE so you can use '%', but that's very ugly).
However, you don't need to write a different query to handle every possible combination. You can simply create the query dynamically:
//create base query
$query = "select `id` from `table` where `name` = 'something' ";
//add order if we need it
if ($use_order)
$query .= "and `order` = 'somevalue' ";
//repeat for any other optional part
Note that you should of course still take proper measures to avoid SQL injection and other security issues - I have not included this here in order to keep things simple.
If you are using bound parameters, it would be impossible.
If you just substitute the values, you can do the following:
select `id` from `table` where `name` = 'something' and `order` = `order`
This is a common theme with database queries - you need a variable query depending on how much filtering you wish to apply to the data it queries. You could go the route of having your query repeated as a string throughout your code, but that is bad practice as it increases the complexity of the code needlessly. Chances for errors occur if you need to change the query for some reason, and have to change it in multiple places as a result.
The better solution is to create a function which builds the query for you execute:
function buildMyQuery($name, $order = null) {
$sql = "SELECT `id` FROM `table` WHERE `name`='$name'";
if ($order != null) {
$sql .= " AND `order`='$order'";
}
return $sql;
}
You could then run this for just using the 'name' field:
$query = buildMyQuery("somename");
Or this for using both fields:
$query = buildMyQuery("somename", "someorder");
As someone mentioned above, this code is deliberately simplified and contains no contingency for possibly dangerous data passed in via $name or $order. You would need to use mysql_real_escape_string or something similar to clean the data first, at the beginning of the function before either piece of data is used.
Dynamic query generation is a fact of life as Byron says, so I would become accustomed to it now rather than using hack-ish workarounds.
I don't think you have any choice... Once you do a selection you can't "unfilter" and get more rows.
You should just use two queries-- either two independent queries, or one that selects on the name into a temp table, and then (optionally) one that further selects on the order attribute.
Like Chad said above, just set the column equal to itself. But be careful, on some platforms / install configurations, NULL != NULL:
select `id` from `table` where `name` = 'something' and coalesce(`order`,'') = coalesce(`order`,'')
On reflection, I have a better answer. My colleague showed me a way this can be done.
My example...
Select rentals.* From rentals Where ((? = '') OR (user_id = ?))
The variables must be the same.
If they are both 5 for example, the first boolean will be false, but the second will be true, for the rows where the users id is 5.
If you require "all", setting as an empty string will result in all rows being seen to meet the where clause condition.
Can't you just use a not null query here?
select `id` from `table` where `name` = 'something' and `order` is not null;
You should be able to do it like this:
select `id` from `table` where `name` <>'' and `order` <>''
That will select anywhere that the value is not equal to blank.
$sql = "SELECT * FROM auctions WHERE id = id ";
if ($category !== "ANY") {
$sql .= "AND category = $category "; }
if ($subcategory !== "ANY") {
$sql .= "AND subcategory = $subcategory "; }
if ($country !== "ANY") {
$sql .= "AND country = $country "; }
$sql .= "ORDER BY $order $sort LIMIT $limit OFFSET $offset";