mysql wildcards % vs %% - mysql

What is the difference in '%' and '%%', when used in mysql where clause with 'LIKE' ?
select * from `wp_users` u where u.user_nicename like "%lastuser%"
VS
select * from `wp_users` u where u.user_nicename like "%%lastuser%%"

There is no difference between %% and % when it comes to pattern matching in mysql.
I've seen developers get confused over this when they try to match a literal % and therefor write %%. This is most often because of the fact that format-strings often use a double % to indicate that you'd like it to be treated as an exact literal.
MySQL documentation of LIKE
MySQL 5.0 Reference Manual :: 11.5.1 String Comparison Functions :: LIKE
What's the origin of the string, and where is it going?
If the string is passed to a function such as sprintf the format-string rule I mentioned earlier is present, though there is no confusion in that case.
The developer want it to be a single % in the string passed to mysql, and therefor wrote %%.
$query = sprintf (
"SELECT ... FROM ... WHERE id <> %d AND data LIKE '%%hello world%%'",
50
);
// $query => "SELECT ... FROM ... WHERE id <> 50 AND data LIKE '%hello world%'";
A few sample SELECTs using the LIKE operator
mysql> SELECT 'abc' LIKE 'ab%';
+------------------+
| 'abc' LIKE 'ab%' |
+------------------+
| 1 |
+------------------+
1 row in set (0.01 sec)
mysql> SELECT 'abc' LIKE 'ab%%';
+-------------------+
| 'abc' LIKE 'ab%%' |
+-------------------+
| 1 |
+-------------------+
1 row in set (0.00 sec)
mysql> SELECT 'abc' LIKE 'ab\%';
+-------------------+
| 'abc' LIKE 'ab\%' |
+-------------------+
| 0 |
+-------------------+
1 row in set (0.00 sec)
mysql> SELECT 'ab%' LIKE 'ab\%';
+-------------------+
| 'ab%' LIKE 'ab\%' |
+-------------------+
| 1 |
+-------------------+
1 row in set (0.00 sec)

Related

can a mysql select query in C language return a field with the special characters escaped?

1- string = a'b"c\d
2- escaped_string = a\'b\"c\\d
3- make an insert query that inserts escaped_string in some table field.
4- make a select query that returns the inserted value.
The returned value is: a'b"c\d
Is there a way to get the select query to return a\'b\"c\\d ?
(I understand that i can escape it again).
You can use the QUOTE() function of mysql:
mysql> select data from x;
+---------+
| data |
+---------+
| a'b"c\d |
+---------+
1 row in set (0.00 sec)
mysql> select quote(data) from x;
+-------------+
| quote(data) |
+-------------+
| 'a\'b"c\\d' |
+-------------+
1 row in set (0.00 sec)
This should exactly do what you are looking for. Note that the " doesn't need to be escaped here, so QUOTE() doesn't escape it, too.

How to troubleshoot when $wpdb-> update returns 0

I am running the following query on my wordpress website
$error = $wpdb->update( $table_name,
array( 'value' => $update_value ),
array( 'lead_id' => $lead_id,
'field_number' => 31.3 ),
array( '%s' ),
array( '%d', '%f' )
);
It is intended to update gravity form entries after the user has initially submitted the form. This query runs fine for 24 fields but returns 0 for 2.
I have so far tried the following troubleshooting steps:
Storing the result as $error and running var_dump($error); after the query, it returns 0.
Running var_dump( $wpdb->last_query ); immediately after the query to copy/paste the resulting SQL string into phpMyAdmin, which also reports 0 rows affected.
Manually selecting the row in phpMyAdmin using:
SELECT * FROM `table_name` WHERE `field_number` = 31.3
Which also returns no rows. However, I know that there are rows which match as I can se them in the table.
Manually selecting another field which updates as expected using the same query as above - this worked fine.
Changed the $where_format from float to string. No resulting change. Upon checking the db fields, the field_number field is stored as a float.
Used $wpdb->prepare to run a prepared query. Still no movement.
Prepare statement as follows:
$error = $wpdb->query(
$wpdb->prepare(
"
UPDATE %s
SET value = %s
WHERE lead_id = %d AND field_number = %f
",
$table_name, $update_value, $lead_id, 31.3
)
);
Which, when var_dumped gives the following result:
string '
UPDATE prefix_rg_lead_detail
SET `value` = 'a:3:{i:0;s:9:\"Liverpool\";i:1;s:10:\"Manchester\";i:2;s:5:\"Leeds\";}'
WHERE `lead_id` = 4 AND `field_number` = 31.300000
' (length=188)
I'm at my wits end now as I've tried everything I can possibly think of and still cant get 2 fields to update.
Your final problem is indeed with the FLOAT type. It is an imprecise value, which is leading you to your problem. Although the database is showing the value 31.3 it most likely internally in the database is something like 31.30000000000001 which is why the where condition is not working. Take a look at the documentation here: Problems with Floating-Point Values.
So down the road lets go to the tests:
create table test (
n float
);
insert into test values (31.3);
mysql> select * from test;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.17 sec)
Running a select statement on it with that value 31.3 will evaluate to nothing:
mysql> select * from test where n=31.3;
Empty set (0.00 sec)
There are a few ways you can solve it without changing the column type:
1- Using the ROUND(field,number_of_decimals) function
mysql> select * from test where round(n,2)=31.3;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.00 sec)
2- Casting it as DECIMAL type
mysql> select * from test where cast(n as decimal(5,2))=31.3;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.00 sec)
So in order to your update to work with this data you have to use one of those options in your update command like:
$wpdb->query( $wpdb->prepare("UPDATE %s
SET value = %s
WHERE lead_id = %d
AND round(field_number,2) = %f ",
$table_name,
$update_value,
$lead_id,
31.3 )
);
My recommendation is that you change the field type. AFAIK there is no situation where your plugin may break as of this change. What it may happens is a rounding value like you try to insert a value like 31.696 in a Decimal field of (6,2) it will became 31.67. Also the difference is that the value of the field will be formatted as the decimals number you chose so 31.3 will start to apear as 31.30 You can change it as:
alter table yourTableName modify field_name DECIMAL(6,2);
Here are some test on that explanation:
mysql> alter table test modify column n decimal(10,2);
Query OK, 1 row affected, 1 warning (0.90 sec)
Records: 1 Duplicates: 0 Warnings: 1
mysql> select * from test;
+-------+
| n |
+-------+
| 31.30 |
+-------+
1 row in set (0.00 sec)
mysql> select * from test where n=31.3;
+-------+
| n |
+-------+
| 31.30 |
+-------+
1 row in set (0.00 sec)
And to show the rounding:
mysql> insert into test values (31.696);
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> select * from test;
+-------+
| n |
+-------+
| 31.30 |
| 31.67 |
+-------+
2 rows in set (0.01 sec)

How to extract the rows that contain only 1 "=" by using REGEXP in MySQL?

Suppose I have a table named "t1" which contains a column named "ID" which has the following records
abcde=1=2
qwert=3
hhhhj=9
zxcv=5=8
How can I extract the records that contain only 1 "=" sign by using REGEXP in MySQL?
I've tried
SELECT * FROM t1 WHERE ID REGEXP '\\w*=\\w*=\\w*'; -- returns no records
SELECT * FROM t1 WHERE ID REGEXP '\\w*=\\w*'; -- returns all 4 records
I expected the first query to return the records which contains 2 "=", and the second query to return the records which contains only 1 "=".
What's wrong with my queries?
A pretty simple solution without REGEXP would be
select * from table
where
length(ID) - length(replace(ID,'=','')) = 1 ;
Some test cases
mysql> select length('qwert=3') - length(replace('qwert=3','=','')) as diff;
+------+
| diff |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select length('zxcv=5=8') - length(replace('zxcv=5=8','=','')) as diff;
+------+
| diff |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
SELECT * FROM t1 WHERE ID REGEXP '^[^=]*=[^=]*$';
Guess this should do it.See fiddle http://www.sqlfiddle.com/#!9/b2ead/2/0

MySQL Escape Character Issue

While I was trying to solve This Question. I created the dummy records in a table
create table mytable(data CHAR(30));
INSERT INTO mytable VALUES('d\\one'),('d\\two'),('d\\three');
SELECT * FROM mytable;
+---------+
| data |
+---------+
| d\one |
| d\two |
| d\three |
+---------+
3 rows in set (0.00 sec)
Now when i am selecting records, I am getting no result, I have tried many combination with like but no luck.
Ex :
SELECT * FROM mytable WHERE data LIKE "d\\%";
Empty set (0.00 sec)
SELECT * FROM mytable WHERE data LIKE 'd\\%';
Empty set (0.00 sec)
Use triple slash:
SELECT * FROM mytable WHERE data LIKE "d\\\%"
Or use INSTR() instead
SELECT * FROM mytable WHERE instr(data, 'd\\') = 1

Getting last 5 char of string with mysql query

I have to get last 5 numbers using mysql.
My values are like YOT-A78514,LOP-C4521 ...
I have to get only last five char . How can I do this in query?
You can do this with RIGHT(str,len) function. Returns the rightmost len characters from the string str,
Like below:
SELECT RIGHT(columnname,5) as yourvalue FROM tablename
"Right"-function is the way to, using the substring may lead to an problem that is not so easy to notice:
mysql> select right('hello', 6);
+-------------------+
| right('hello', 6) |
+-------------------+
| hello |
+-------------------+
1 row in set (0.00 sec)
mysql> select substring('hello', -6);
+------------------------+
| substring('hello', -6) |
+------------------------+
| |
+------------------------+
1 row in set (0.00 sec)
But if you don't try to go past the start of the string, then substring of course works fine:
mysql> select substring('hello', -5);
+------------------------+
| substring('hello', -5) |
+------------------------+
| hello |
+------------------------+
1 row in set (0.00 sec)
Right is a good choice but you can also use substring like this-
SELECT Substring(columnname,-5) as value FROM table_name
SELECT row_id
FROM column_name
WHERE column_value LIKE '%12345';
This will return the "row_id" when "12345" is found to be the tailing suffix of the "column_value" within the "column_name".
And if you want to get a dinamic number of right characters after a character:
SELECT TRIM(
RIGHT(
database.table.field,
(LENGTH(database.table.field) - LOCATE('-',database.table.field))
)
)
FROM database.table;
SELECT SUBSTR('Stringname', -5) AS Extractstring;