Postgresql LIKE wildcards escape for php - php

The user has a search box.
I need to give him flexibility so he ca do a search like client and the sql for this will be
name like '%client%'
The problem is I don't want to give the user the possibility to search with % or _ wildcards.
I know I can escape them .. but is there a function to do this for any wildcard/ or other solution ?

create or replace function escape_like(text)
returns text language sql immutable strict as
$q$
select regexp_replace($1, $$([\\%_])$$, $$\\\1$$, 'g')
$q$;
Try it:
=> select escape_like($$foo%bar\foo__bar$$);
quote_like
----------------------
foo\%bar\\foo\_\_bar
(1 row)
So your query should look similar to:
select * from tablename where columnname like '%' || escape_like(?) || '%';

In MySQL you can do it with PHP:
$text_escaped = addcslashes($text, '%\\_');
I guess the same applies to PostgreSQL, but I remeber reading something on their mailing list that you need to double escape the backward slashes in order for it to work properly, I'm not sure though...

Why don't you use full text search?

Related

Search using REPLACE in a SELECT with PDO and .MDB ACCESS, with PHP

I'm trying to write a mysql query that will match names from a table and the name in the database can contain dots or no dots. So, for example I would like my query string fast to match all of these: fast, f.ast, f.a.s.t etc.
I use PHP, with PDO connecting to a .MDB database.
I tried what I found here, with no success (I get error):
SELECT * FROM table WHERE replace(col_name, '.', '') LIKE "%fast%"
I think PDO for MDB databases is missing some functions :(
Any solution?
Thanks to Doug, I solved with:
$variable = implode("[.]", str_split($variable)) . "[.]";
and:
SELECT * FROM table
WHERE
col_name LIKE "%" . $variable ."%";
You cannot run the replace() function unless you are running the query through Access itself. You do however have a possible alternative, try the following:
SELECT * FROM table
WHERE
col_name LIKE "%fast%"
OR col_name LIKE "%f[.]a[.]s[.]t%";
The square brackets define an optional .
Or alternatively do it at PHP level with:
str_replace('.','',$var);

mySql regular expression in WHERE statement

I have a database where I store a code which is an implode("|", $array) of various codes. So the results will be something like:
100|5100|510
100|5200|510
410|5200|520
100|790|5100|320
I want to write a regular expression to search mySQL for matches from PHP ... I might have something like 100|*|510 to show me both 100|5100|510 and 100|5200|510. This RegEx works in PHP:
/100\|(?:.*)\|510/
But it does not work in mySQL. I found answers that ?: does not work, so if I remove that and use
/100\|.*\|510/
i.e. Query is:
SELECT * FROM tra_amounts WHERE coa_codes REGEXP "/100\|.*\|510/"
It shows all results from the table.
How do I write a RegEx to match some parts of the code, while leaving other parts of the code as a wildcard?
Thanks!
Have you heard of MySQL's LIKE operator? Something like this might be what you have in mind:
SELECT *
FROM yourTable
WHERE someCol LIKE '100|%|510;
Assuming that someCol had 100|5100|510 and 100|5200|510 as data, this query would return both of these records.
Use RLIKE instead of LIKE or =.

How to find a needle in database sql

I have query which search for database, that is
$linkcdb = $wpdb->query($wpdb->prepare("SELECT wp_link_factor WHERE wp_link_chk = %s", $u));
where $u = is nay link;
for example;
$u = www.kaka.com
$u = popopo.com
$u = http://jajaja.com
I have a data base in which www, http and .com is in the column of table and the column name is wp_link_chk
Now the problem I am facing is the user input is a complete link like www.example.com while in database I had only .com, http and www
What I want is that how I compare my complete sentence and see if the sentence have needle http, or www or .com in it ?
The function that do this is stristr($u,'http') so how I am going to use this functionality in data base, I mean how i am going to check the column of wp_link_chk as a needle against my sentence ?
Using the MySQL function LOCATE you could use something like
... WHERE LOCATE( wp_link_chk, :userInput ) > 0
Edit: Note that this approach may of course return multiple records, for instance if "http://www.example.com" is matched against "http", "www", and ".com".
Well, the closest way to match these is to use the mysql LIKE function.
The actual statement would be something like
SELECT wp_link_factor WHERE wp_link_chk LIKE %www.example.com%
But since you are using wordpress prepared statements, use it like this:
$linkcdb = $wpdb->query($wpdb->prepare("SELECT wp_link_factor WHERE wp_link_chk LIKE %s", '%' . $u . '%'));
-- UPDATE --
For the sake of completion, you can use REGEXP matching to select rows that contains either http, www or .com in the wp_link_chk column using the following query.
SELECT wp_link_factor WHERE wp_link_chk REGEXP '(http)|(www)|(\.com)'

MySQL query String contains opposite

MySQL query String contains
Hello, I am trying to make an mysql query that looks for a column value that contains a string from a master string I set. So if my master string is '1234567', I would like it to return any results with column values that have '1','2', etc... The above link was as close as to what I can find but I need it comparing in the opposite direction.
eg.:
WHERE '%{$needle}%' LIKE `column`
You are a little vague about where the various values are being stored (your text uses terms like "master string" but the sample code uses different names).
You can do what you want using regexp. Here is an example:
select 'abcd6efg' regexp concat('.*[', '1234567', '].*')
To be honest, regex is different from like in one important respect. regex returns true if any part of the left string matches, whereas for like the entire string has to match. So, the following also works:
select 'abcd6efg' regexp concat('[', '1234567', ']')
I like to put the explicit wildcards in to avoid mistakes when switching between the two.
You can look up the documentation for regular expressions here.
How about
WHERE ? LIKE CONCAT('%', `column`, '%')
where ? is a placeholder having a bound parameter with your master value (1234567) because you are using the PDO or MySQLi extension, right?
You're most certainly not using the deprecated MySQL extension, surely.

MySQL: How to search for spelling variants? ("murrays", "murray's" etc)

I want to search like this: the user inputs e.g. "murrays", and the search result will show both records containing "murrays" and records containing "murray's". What should I do in my query.pl?
What do you think about using the SOUNDEX function and the SOUNDS LIKE operator ?
That way, you can simply do:
SELECT * from USERS WHERE name SOUNDS LIKE 'murrays'
I'm pretty sure it doesn't work for every case, and perhaps it is not the most efficient way to solve the problem, but it could fit your needs.
This won't help if you absolutely need to do these queries in SQL, but if you can set up a Lucene search index for it, you gain a lot of this kind of "fuzzy search" functionality. Note though that Lucene is quite a complex topic by itself.
What you could do is create an extra field in the database, which contains the data with all special characters stripped from it, and search there. A bit lame, I know. Looking forward to see smarter answers ;)
Quick and dirty:
SELECT * FROM myTable WHERE REPLACE(name, '\'', '') = 'murrays'
I would first build a search column which has the text without punctuation and then search on that. Otherwise you'll have have to have a series of regular expressions to search against or check individual records in PHP for matching: both of which are computational intensive operations.
Maybe something like this: (untested!)
SELECT * FROM users WHERE REPLACE(user_name, '\'', '') = "murrays"
If this is for single word searching, you could try using Soundex or Metaphone functions? These would handle sounds-like as well as spelling
Not sure if MySQL has these, but PHP does (which would require separate columns to hold these values).
Otherwise, Richy's no-punctuation extra column seems best.
You could try adding a replace to your query like this
replace(name, '''','')
to temporarily get rid of the apostrophes for the match.
select name from nametable where name = replace(name,'''','');
This query should be able to pick up "murrays" or "murray's".
var inputStr = "murrays";
inputStr = String.Replace("'", "\'", inputStr);
SELECT * FROM ATable WHERE Replace(AField, '\'', '') = inputStr OR AField = inputStr
strip user input and names in database from all non-letter characters.
Use levenstein distance or soundex to find murrays with murray or marrays. This is optional but your users would love that.

Categories