I'm working with an application that needs to make a where query to the database to return a rows with a "t1.address_city" (a column in the database) that is equal to any of the locations in an array. I understand I should be using implode() to make this into one big string, but this doesn't return any rows - presumably because it is looking for rows that match the big string (which of course isn't just one city, it is a list). Code:
$_GET["places"] contains something like this:
["madrid", "lisbon", "london", "paris", "new york"]
When the array name, $places, is put into the where clause like IN ('$places'), I get no rows. Following the advice of other similar questions on here, I imploded the array so that it looks like "madrid, lisbon, london, paris, new york" and then use the imploded variable like IN ('$implodedplaces') but as mentioned earlier, it doesn't find any rows.
I have found that entering each place name in quotes (IN ('madrid','lisbon','london')) separately works perfectly, but of course I need the IN clause to use the $_GET["places"] since this is manipulated by the user. Is there any way to enter all of the values in $_GET["places"] as separate strings with commas in between?
Any help appreciated - feel free to ask questions if my explanation wasn't great.
You need to keep in mind that you need to do escaping:
$in = [];
foreach ($_GET["places"] as $place) {
$in[] = mysql*_real_escape_string($place);
}
$in = '"' . implode('", "', $in) . '"';
$query = "select * from t where f IN (" . $in . ")";
Additionally you need to check count($_GET["places"]) because if it's empty you query will have IN() which is a syntax error.
Watch out with IN, in most cases it requires a full table scan, and this kills mysql performance ..
You should check a query with EXPLAIN it see it.
Try
$implodedplaces = implode("','", $places);
Note that this does not escape any quotes that may be in $places.
If $_GET["places"] is a string you could try:
$implodedplaces = str_replace('"', "'", str_replace('[',"'", str_replace(']',"'",$_GET["places"])));
This does make the assumption however that you won't find quotes and brackets in your place names.
Related
I have been at this for almost two hours and I'm pretty sure I'm just missing something simple. I have tried multiple iterations without success. SO searches have given insights but nothing exactly like this to see were I'm going wrong. Your input will be appreciated.
I have an array built [$prime_ids] made up of user IDs (individual email addresses). This is the look of the finished array:
["james.pruit#abcnet.com", "dan.smith#abcnet.com", "nathan.jones#abcnet.com", ...
Now I need to find matches in this list against matches in a database table. Note: there can be multiple matches with the information contained in the table (meaning a single user ID may show up multiple times in the list). That is being done for a specific reason.
My understanding is I need to use implode to make this work. Here is my query:
$sql_query = "SELECT * FROM worksheet4 WHERE worksheet4.user_id IN (" . implode(",", $prime_ids) . ");";
$result = $dbc->query($sql_query);
I then run a loop to build a second array ($kp_positions). Here is my code:
while($row = mysqli_fetch_assoc($result)) {
$kp_positions[] = $row;
}
This returns an empty array. While debugging I tried the same SELECT query using WHERE instead of IN and implode:
WHERE user_id = 'dan.smith#abcnet.com'";
... and it works perfectly (but only for this single-user). Thinking this might have something to do with single quotes (') in the implode statement I tried every possible combination that made sense without avail. Because this works perfectly with a single user ID, where my going wrong in my implode statement? Or, am I going about this the wrong way? Thank you.
if you print your query you will get something like this:
SELECT * FROM worksheet4 WHERE worksheet4.user_id IN (james.pruit#abcnet.com,dan.smith#abcnet.com,nathan.jones#abcnet.com);
Note that each member within the "in" should be wrapped in quotes
so try to run this line:
$sql_query = "SELECT * FROM worksheet4 WHERE worksheet4.user_id IN ('" . implode("','", $prime_ids) . "');";
and get
SELECT * FROM worksheet4 WHERE worksheet4.user_id IN ('james.pruit#abcnet.com','dan.smith#abcnet.com','nathan.jones#abcnet.com');
Another option, in my opinion better, is to use json_encode() to quote it.
$prime_ids = array_map('json_encode', $prime_ids)
https://3v4l.org/HPL2o
Then without quotes, which json_encode() adds for you:
$sql_query = "SELECT ... IN (" . implode(",", $prime_ids) . ")";
This will escape quotes that may exist, which is good.
I'm trying to include a list of strings to be used in an "in" expression in a sql statement for example:
select * from poop where id in ('asd','sas','ser')
I want to pass the in parameter from a variable. The quoting is really screwing me up. Should I be passing this as a string which I have been trying to no avail by making a comma seperated string that looks like this:
282366381A,240506808A,244154247A,491404349A,242443808B,328409296A,239723812A,383423679M
or "282366381A","240506808A","244154247A","491404349A","242443808B","328409296A"
or
'282366381A','240506808A','244154247A','491404349A','242443808B','328409296A'
None of these work or is there a different way using an array of values?
This is the statement I'm using with the string:
$cernerResults = $this->cernerdb->exec( "select
pat as HICN,
from pat
where
HICN in ( ? )", $hicsString );
Edit:
I was able to get around this by constructing the entire query as a string like this:
$query = "select pat as HICN from pat where HICN in (".$hicsString.")";
$hicsString has single quotes around each item like so:
'282366381A','240506808A','244154247A','491404349A','242443808B','328409296A'
The problem is that providing the string to the exec would result in no results. When looking at the freetds log file the in expression values would be double quoted as a whole or each one would be double single quoted and if i used no quotes they would not be quoted at all.
All of these would make the statement return no results. I should also mention that this is a Sybase database.
I think your problem may come from the fact that PDO parser needs to have one value per question mark so it is able to validate it. So your "hack" with one question mark which is assigned to more than one value is where it fails IMHO.
This is how I handle case like that:
$values = ['asd','sas','ser'];
$count = count($values);
$results = $db->exec(
"select * from poop where id in ( ?".str_repeat(", ?", $count-1).")",
$values
);
In general I would advice you using data mappers instead of running the queries on a DB object. It is easier to iterate through them and it is more secure.
I have a PHP script that is generating a MySQL select statement:
select * from words where word = 'Classic'
There is exactly one word in the words table with the variable word equal to Classic.
When my PHP page executes, I get no results from the query. If I echo the string that is being used to execute the query, cut and paste that into the SQL window in PHPMyAdmin in the database, I also get no results. However, if I re-type that EXACT string into the SQL window in PHPMyAdmin (with the same quote characters), I get the proper result of one row.
The word Classic from the select statement is gotten from a PHP GET (see code below). I can echo the $word variable, and get the correct result of 'Classic'. What am I doing wrong?
Here is my code:
<?php
require ('dbconnect.php');
$word = $_GET["word"];
$selectStr = "SELECT * FROM words WHERE word = '" . $word . "'";
if ($results = MySQL($dbName, $selectStr))
{
$rowCount = MySQL_NUMROWS($results);
}
$resultRow = MYSQL_FETCH_ROW($results);
$wordID = $resultRow[0];
?>
Please, please, please sanitize that word. mysql_real_escape_string() should do the trick.
$selectStr = "SELECT * FROM words WHERE word LIKE '" . $sanitized_word_i_promise . "'"; should work :)
Just to explain: "=" should work for exact matches. This includes uppercase / lowercase, spaces etc. You should probably trim that result first too, before using it in the query.
If you have foo stored in the database (note the space at the end) - it won't match foo, without a space. You'll want to use LIKE 'foo%' - probably.
Either way, Sourabh is right, although performance wise, this isn't a big hit when trying to match exact strings, you should look for the problem in other places first (such as, is the item in the database an exact match?).
First off you should not take any user input and directly input it into a query without sanitizing it, or using a prepared statement.
Now that we've gotten that out of the way: have you tried doing a strcmp() with the variable and your string written in? Such as
echo strcmp($_GET['word'], "Classic")
If you get a result other than 0 it means they are not the same, most likely there will be a whitespace of some sort in the $_GET variable. use trim() on it to take out whitespace. Also could be a case sensitivity issue as well.
I have two questions regarding my script and searching. I have this script:
$searchTerms = explode(' ', $varSearch);
$searchTermBits = array();
foreach($searchTerms as $term){
$term = trim($term);
if(!empty($term)){
$searchTermBits[] = "column1 LIKE '%".$term."%'";
}
}
$sql = mysql_query("SELECT * FROM table WHERE ".implode(' OR ', $searchTermBits)."");
I have a column1 with a data name "rock cheer climbing here"
If I type in "rock climb" this data shows. Thats perfect, but if I just type "Rocks", it doesn't show. Why is that?
Also, How would I add another "column2" for the keyword to search into?
Thank you!
Searching that string for "rocks" doesn't work, because the string "rocks" doesn't exist in the data. Looking at it, it makes sense to you, because you know that the plural of "rock" is "rocks", but the database doesn't know that.
One option you could try is removing the S from search terms, but you run into other issues with that - for example, the plural of "berry" is "berries", and if you remove the S, you'll be searching for "berrie" which doesn't get you any further.
You can add more search terms by adding more lines like
$searchTermBits[] = "column1 LIKE '%".$term."%'";
and replacing ".$term." with what you want to search for. For example,
$searchTermBits[] = "column1 LIKE '%climb%'";
One other thing to note... as written, your code is susceptible to SQL injection. Take this for example... What if the site visitor types in the search term '; DROP TABLE tablename; You've just had your data wiped out.
What you should do is modify your searchTermBits[] line to look like:
$searchTermBits[] = "column1 LIKE '%" . mysql_real_escape_string($term) . "%'";
That will prevent any nastiness from harming your data.
Assuming the data you gave is accurate, it shouldn't match because you're using "Rocks" and the word in the string is "rock". By default mysql doesn't do case sensitive matching, so it's probably not the case.
Also, to avoid sql injection, you absolutely should be using mysql_real_escape_string to escape your content.
Adding a second column would be pretty easy as well. Just add two entries to your array for every search term, one for column1 and one for column2.
Your column1 data rock cheer climbing here your search criteria %Rocks% it doesn't fit at all as rocks is not in your column1 data
you can add column2 as you do for column1 then put it all together by using an AND operator (column1 LIKE "%rock%" OR column1 LIKE "%climb%") AND (column2 LIKE "%rope%" OR column2 LIKE "%powder%")
TIPS:
If your table/schema are using xx_xx_ci collation (then this is mean case insensitive,mysql doesn't care case sensitive) but if other then you need to make sure that the search term must be case sensitive(mysql do case sensitive).
I have the following code block which explodes a string upon spaces.
$run = explode(" ",strtolower($q));
eg. "This is the string"
Array $run look like:
(This,is,the,string)
The problems im having are:
I only want to explode the string if it has a white, something equal as using php function str_word_count($q)>1.
Unsure on how to create a single query which will work with multiple words in string and search table using any of them.
$query = "SELECT name FROM `table1` WHERE name LIKE '%". mysql_real_escape_string($run[0]) ."%' OR name LIKE '%". mysql_real_escape_string($run[1]) ."%'";
Trying to simplyfy the above query making it smaller and variable in size based on word count. Is this also a good aproach to exploding the string then preparing the sql?
I've tried using IN as well on SQL query with no good luck.
You can use MySQL's MATCH . . . AGAINST . . . to perform this kind of search:
WHERE MATCH (name) AGAINST ('this is the string')
Consult the documentation for more information.
Original solution, not helpful in this situation:
You can check out the MySQL specific function FIND_IN_SET:
WHERE FIND_IN_SET(colname, 'This,is,the,string') > 0
The value in colname cannot contain a comma, however.