SELECTing MySQL rows with unusual characters using PHP and querystrings - php

Table name Styles.
Referenced Column: Style
Coding with PHP 5.
Problem:
My SELECT query to MySQL returns 0 rows.
I'm using the column name in querystring as identifier (something like example.com.php?style=paper-pencils). For SEO purposes I've removed any odd characters and replaced spaces with '-'. Using url rewrite to end up with example.com/paper-pencils.
Working on a database I inherited which uses characters such as '&' or ':' in the Style column. On the database side, the Style column would contain a row with something like "Paper & Pencils" as compared to my slugged version of "paper-pencils".
Things I've Tried:
I de-slug the url so i end up with 'paper pencils' (see below in query example).
I tried
SELECT * ,REPLACE( 'Style', '&', ' ' ) AS Style, REPLACE( 'Style', ':', ' ' ) AS Style FROM Styles
WHERE Style = 'paper pencils'
to no avail. The query I have runs fine, it just comes back with 0 results.
My next step would be to do a PHP SWITCH statement. Something like
case: $_GET['style'] = 'paper-pencils'
$DBstyle = 'Paper & Pencils' but I feel like there has to be some other way around it. I have 30 different possibilities and would prefer something better.
Any suggestions on how I can account for these unusual characters with random occurrences?

Maybe you can add another column to this table called style_slug. This column will contain the slugged version that you use in your urls and will allow you to retrieve the Style column in your query.

Just like Gohn said or, a better one - use an approach which is used on this site - have both an unique identifier and a slug in the url.
example.com/2356356/paper-pencils
will cajole SEO and make your life easy.

Related

How to do case sensitive where() 'in' match in yii2 with mysql database

I've got a hashtags table in my mysql db, with a string(512) column called tag. I want to do a case sensitive search using Yii2's ActiveQuery, like this:
$expTags = ['one','two','three'];
Hashtag::find()->where(["IN","tag",$expTags])->select(["id"]);
In mysql, this usually means prefixing BINARY outside every value, or prefixing the column name. I tried both, I even tried "IN BINARY", nothing worked.
How to do this? I need case sensitive search, and I don't want to modify the table / column collation just to do this.
previous answer here got it pretty close:
$expTags = ['one','two','three'];
Hashtag::find()->where(["BINARY IN","tag",$expTags])->select(["id"]);
BINARY IN (used as operator) causes a syntax error (for mysql at least)
Hashtag::find()->where('BINARY tag in(:tag)', ['tag'=> $expTags])->select(["id"]);
and this hits the pdo problem of binding an array to a single param
this will work however:
Hashtag::find()->where(['BINARY(`tag`)' => $expTags])->select(["id"]);
you can try this:
$expTags = ['one','two','three'];
Hashtag::find()->where(["BINARY IN","tag",$expTags])->select(["id"]);
or
Hashtag::find()->where('BINARY tag in(:tag)', ['tag'=> $expTags])->select(["id"]);

SQLSRV Update Query to remove spaces

Using a combination of MS-SQL, PHP, and JSON, I have a column in my page called VendorAddress that outputs to the browser like this:
1111 THAT WAY DRIVE �TORRANCE
That strange black diamond with the questionmark.
I have narrowed it down to the fact that some users are copying and pasting from Excel, and there is an extra space between the street and city. I can prevent this from happening in the future. It's the ones that already been saved to the table that is causing a problem for me.
I have found there are over 300 records in the MS-SQL database that have this extra space.
What I need to do is write a query that would update the column by removing this extra space.
UPDATE [main].[dbo].[suppliers] SET [VendorAddress] = '1111 THAT WAY DRIVE TORRANCE' WHERE [PartnerCode] = '00011144';
This is the query I was using, going record for record for each PartnerCode that has the black diamond (336 total). I refuse to go record for record on this. I need to write a query that will do it for me.
I am not sure how to go about doing this. Everything I find online tells me to use TRIM, but it's only for trailing spaces. These are not trailing spaces. They are within the string.
I wish to write a query that would look at the whole table and remove the unnecessary spaces from within the string.
Edit
The special character cannot be seen in the database itself. The only time you see it is when PHP outputs it to the browser.
Basically, within the table, the field contains an extra space. The black diamond cannot be seen within the table.
It seems like you should be able to just employe the REPLACE function:
UPDATE [main].[dbo].[suppliers]
SET [VendorAddress] = REPLACE(VendorAddress, '�', '')
This command seems to work:
SELECT REPLACE('1111 THAT WAY DRIVE �TORRANCE', '�', '')
Have you tried updating it away? Here's some code for capturing the glyph if copy/paste won't work.
DECLARE #Glyph CHAR(1);
SELECT #Glyph = SUBSTRING([VendorAddress]
, -- Put numberic position of Glyph in string here
,1)
FROM [main].[dbo].[suppliers]
WHERE [PartnerCode] = '00011144'; -- Record with erroneous Glyph
SELECT #Glyph AS [Questionable Character]
, [VendorAddress] AS [Before]
, REPLACE([VendorAddress],#Glyph,'') AS [After]
WHERE [PartnerCode] = '00011144'; -- Use same record as above.
/* Uncomment out this bit when you know it works...
UPDATE [main].[dbo].[suppliers]
SET [VendorAddress] = REPLACE([VendorAddress],#Glyph,'')
WHERE [VendorAddress] LIKE '%' + #Glyph + '%';
*/
To replace double spaces with a single space use the following:
UPDATE [main].[dbo].[suppliers]
SET [VendorAddress] = replace([VendorAddress], ' ',' ')
WHERE [VendorAddress] LIKE '% %'
Repeat it until you get 0 rows affected.
* EDIT *
Otherwise can you execute this query to find out the code of that character?
select distinct cast([VendorAddress] AS varbinary) FROM [main].[dbo].[suppliers] WHERE [VendorAddress] LIKE '1111 THAT WAY DRIVE%TORRANCE'

%LIKE% retrieves eg. WOMEN DATA when calling MEN

$itemList = DB::table('items')
->orderBy('id', 'desc')
->where('item_status', 2)
->where(function($query) use($queryArr)
{
foreach($queryArr as $uID){
$query->whereRaw("tags LIKE '%$uID%'");
}
})->paginate(21);
I have been facing this issue since a long time. Problem when you do a LIKE search is it grabs the data of WOMEN when it's just eg MEN
Mainly because MEN is inside Women
I also tried the following but failed(This sort of grab a word) men without women data
$query->where('tags', 'LIKE', '%'.$uID.'%');
SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]';
How do i use that Word boundary query in laravel query builder
Tried this and still failed $query->whereRaw("tags LIKE REGEXP '[[:<:]]Men[[:>:]]'");
SQLSTATE[42000]: Syntax error or access violation: 1064 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 'REGEXP '[[:<:]]Men[[:>:]]')' at line 1 (SQL: select count(*) as aggregate from items where item_status = ? and (tags LIKE REGEXP '[[:<:]]Men[[:>:]]')) (Bindings: array ( 0 => 2, ))
I also understand some asked why not just created a proper way of handling these item's category. Well i think for now using Full Text Search is fine for me at most when it come to scaling i will use elastic search. true?
UPDATE
Apologies for not giving an example of tags
Bag,Shoes,Men,Wedges
Bag,Shoes,Men
Men,Shoes,Bag
If values are separated by commas, try to use following
WHERE `tags` REGEXP "(^|,)men(,|$)"
This will require to have comma or end of string around the word men.
Your REGEXP solution is throwing the syntax error because of the extra LIKE keyword. The correct syntax is simply WHERE column REGEXP 'pattern'.
If you find this hard to remember, try using RLIKE instead, which is a synonym for MySQL's REGEXP. There is less chance you will accidentally write WHERE column LIKE RLIKE ... in your query because it is more obviously redundant.
The pattern itself should work fine. Personally, I dislike using those word boundary classes in MySQL; since you know your tags are comma delimited and space padded, [ ,]Man[ ,] would function just as well. The word boundary class breaks at punctuation other than underscores, so you could run into trouble if you have tags that are hyphenated, for instance.
If you want to use multiple word tags with spaces, either of the previous patterns is buggy. In that case I would try to stick with commas as your delimiter, get rid of the whitespace padding and use anchors instead, as suggested in one of the other answers: (^|,)Man($|,)
In your query you said : Find anything that contains the tag 'MEN' => '%MEN%', that's why it shows: WOMEN AND MEN, so to answer to your question you should use starts with instead of contains, like this :
$query->where('tags', 'LIKE', $uID.'%');

Mysql query keyword changes to unknown character set in php in case of Mobile devices

I am using a search query for selecting names in my DB by giving a keyword.
My query is
SELECT `engine4_core_search`.* FROM `engine4_core_search` WHERE ((`engine4_core_search`.`title` LIKE "%".$text."%"))
When give " cardiff " (cardiff comes in place of $text ) as my keyword and checking the query ..it displays like
SELECT `engine4_core_search`.* FROM `engine4_core_search` WHERE ((`engine4_core_search`.`title` LIKE 'Êrdiff%'))
Is there any method to solve this.
Thanks in advance.
It seems to be you have included jQuery-mobile (because tagged in it)
In some cases jQuery-mobile replaces some strings when they attached with different patterns like " %cardiff " . It may considers to be different string set
Just remove jQuery-mobile and try for your output......

LIKE Condition in PHP Not Work correctly

i have a row in my database with name "active_sizes" and i want filter my website items by size, for this, i use LIKE Condition in php :
AND active_sizes LIKE '%" . $_GET['size'] . "%'
but by using this code i have problem
for example when $_GET['size']=7.0 this code shows items that active_sizes=17.0
my active_sizes value looks like 17.0,5.0,6.5,7.5,,
thanks
Using comma-separated values in a single field in a database is indicative of bad design. You should normalize things, and have a seperate "item_sizes" table. As it stands now, you need a VERY ugly where clause to handle such sub-string mismatches:
$s = (intval)$_GET['size'];
... WHERE (active_sizes = $s) // the only value in the field
OR (active_sizes LIKE '$s%,') // at the beginning of the field
OR (active_sizes LIKE '%,$s,%') // in the middle of the field
OR (active_sizes LIKE '%,$s') // at the end of the field
Or, if you normalized things properly and had these individual values in their own child table:
WHERE (active_sizes_child.size = $s)
I know which one I'd choose to go with...
You don't state which DB you're using, but if you're in MySQL, you can temporarily accomplish the same thing with
WHERE find_in_set($s, active_sizes)
at the cost of losing portability. Relevant docs here: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
You Have % signs around your $_GET value. Combined with LIKE, this means that any string that simply contains your get value will be retuned. If you want an exact match, use the = operator instead, without the percentage signs.
This will solve your immediate issue:
AND active_sizes LIKE '" . mysql_real_escape_string($_GET['size']) . "%'
If you are using the database other than MySQL, use corresponding escape function. Never trust input data.
Besides, I'd suggest using numeric field (DECIMAL or NUMERIC) for active_sizes field. This will accelerate your queries, will let you consume less memory, create queries like active_sizes BETWEEN 16.5 AND 17.5, and generally this is more correct data type for a shoe size.

Categories