I want to query all strings that match the following pattern in mysql.
At least one non-empty character,
followed by a literal dash character -,
then followed by at least one non-empty character,
then followed by the literal string in ('true')
the substring of "and" can not appear in between - and in ('true').
For Example:
segment-123 in ('true')
matches the above pattern.
content-foo and segment in ('true')
does not match the above pattern because it has the substring "and" in between - and in ('true').
Is this achievable using REGEXP in mysql? Any help is greatly appreciated.
mysql> select 'segment-123 in (\'true\')'
regexp '[^[:space:]]+-[^[:space:]]+ in \\(\'true\'\\)' as matched;
+---------+
| matched |
+---------+
| 1 |
+---------+
mysql> select 'content-foo and segment in (\'true\')'
regexp '[^[:space:]]+-[^[:space:]]+ in \\(\'true\'\\)' as matched;
+---------+
| matched |
+---------+
| 0 |
+---------+
See https://dev.mysql.com/doc/refman/8.0/en/regexp.html#regexp-syntax for more documentation on the regular expression syntax in MySQL.
I have product tables in my database
Product table structure:
product_id | testid
------------------------------------
1 11,12,13
2 2,4
Below is my FIND_IN_SET query:
SELECT product_id FROM product
WHERE FIND_IN_SET(3, testid) > 0;
Output
0
Below is my LOCATE query:
SELECT product_id FROM product
WHERE LOCATE(3, testid) > 0;
output
1
My question
What is difference between FIND_IN_SET and LOCATE and what is the best way to find id in column
To put it in simple technical terms(PHP terminology), find_in_set is like substring function of PHP. It will accept a substring and a string as parameters, and return 1 if the substring is found within the string. It will return 0 if substring is not found.
On the contrary, LOCATE() returns the position of the first occurrence of a string within a string. It accepts, a substring and a string as parameters.
I think in your use case, find_in_set is the one you should go for. Because this is the one. find_in_set will return 1 if 3 is found in a row, where as locate will first occurance of 3 in the string even if it finds 31 or 300 as first element.
Difference between LOCATE() and FIND_IN_SET() Function
When using LOCATE() function for integers, suppose we need 1 to return from LOCATE() if integer 3 is in the set 1,2,3,4,5,.. the following MySQL commands can be written:
mysql> SELECT IF(LOCATE(3,'1,2,3,4,5,6,7,8,9')>0,1,0);
+-----------------------------------------+
| IF(LOCATE(3,'1,2,3,4,5,6,7,8,9')>0,1,0) |
+-----------------------------------------+
| 1 |
+-----------------------------------------+
1 row in set (0.06 sec)
The above command working rightly because the set contains the number 3 , but if we write the following commands, look what happened
mysql> SELECT IF(LOCATE(3,'11,12,13,14,15')>0,1,0);
+--------------------------------------+
| IF(LOCATE(3,'11,12,13,14,15')>0,1,0) |
+--------------------------------------+
| 1 |
+--------------------------------------+
1 row in set (0.02 sec)
Above the 3 is not present as a number three(3) in the given set, though the LOCATE() returns 1.
To avoid this type of situation you can use the FIND_IN_SET() function. Here is the example below:
mysql> SELECT IF(FIND_IN_SET(3,'11,12,13,4,5,6,7,8,9')>0,1,0);
+-------------------------------------------------+
| IF(FIND_IN_SET(3,'11,12,13,4,5,6,7,8,9')>0,1,0) |
+-------------------------------------------------+
| 0 |
+-------------------------------------------------+
1 row in set (0.05 sec)
So, LOCATE() function is very much suitable for string but not as much suitable for integer.
Examples, credits and some more information you can find here
So in your example FIND_IN_SET return 0 because there is no 3 in the given set, but LOCATE() returns 1 it treat the given set as a string but not a comma separated value, and the 3 present in the number 13
Hello i need a regular expression per my sql query to match to text
"SIP/(10 NUMBERS)"
equals
"SIP/1234567890"
"SIP" are text
and 10 number randoms 0-9
UPDATE
Final text are SIP/0123456789-000001cc
where
"SIP/" is text
"0123456789" Always 10 digits
"-" is character
"000001cc" is random alphanumeric
You can use this regex:
^SIP/[[:digit:]]{10}-
Examples:
mysql> select 'SIP/0123456789-000001cc' regexp '^SIP/[[:digit:]]{10}-';
+----------------------------------------------------------+
| 'SIP/0123456789-000001cc' regexp '^SIP/[[:digit:]]{10}-' |
+----------------------------------------------------------+
| 1 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select 'SIP/123456789-000001cc' regexp '^SIP/[[:digit:]]{10}-';
+----------------------------------------------------------+
| 'SIP/123456789-000001cc' regexp '^SIP/[[:digit:]]{10}-' |
+----------------------------------------------------------+
| 0 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
Use \ to escape /
The following RegEx targets SIP followed by /and then 10 digit characters:
SIP\/\d{10}
I have a query where one condition to check if a room number is odd/even. The issue is that the room number is stored with the building info as well in a string.
Here is the format of the data in the database:
ABC-0101A (Odd)
ABC-0112B (Even)
ZYX-123A1 (Odd)
ZYX-456B1 (Even)
For a room number to be considered even/odd, it is dependent on the last number before the first letter after the dash.
This would be quite a lot easier and more performant if you could separately store the numeric portion in another column. As a long term solution, I would recommend doing that.
But you can use a regular expression here to match the last digit before the first number, with a set of even [02468] and a set of odd [13579] with a CASE statement.
SELECT
CASE
WHEN room REGEXP '-[0-9]*[02468][A-Z]' THEN 'even'
WHEN room REGEXP '-[0-9]*[13579][A-Z]' THEN 'odd'
ELSE 'something else entirely'
END
FROM rooms
The pattern -[0-9]* matches a literal hyphen followed by zero or more digits. Then the significant part is the [02468] or [13579] set to match an even or odd digit that must be present immediately preceding [A-Z] matching the next letter.
Here's a demonstration: http://sqlfiddle.com/#!9/464d1d/3
Exmaple matching an even room:
SELECT 'ABC-0112B' REGEXP '-[0-9]*[02468][A-Z]';
+------------------------------------------+
| 'ABC-0112B' REGEXP '-[0-9]*[02468][A-Z]' |
+------------------------------------------+
| 1 |
+------------------------------------------+
Example matching an odd room:
SELECT 'ABC-0101A' REGEXP '-[0-9]*[13579][A-Z]';
+------------------------------------------+
| 'ABC-0101A' REGEXP '-[0-9]*[13579][A-Z]' |
+------------------------------------------+
| 1 |
+------------------------------------------+
Example matching an odd room that doesn't end with a letter:
SELECT 'ABC-0101A11' REGEXP '-[0-9]*[13579][A-Z]';
+--------------------------------------------+
| 'ABC-0101A11' REGEXP '-[0-9]*[13579][A-Z]' |
+--------------------------------------------+
| 1 |
+--------------------------------------------+
First create a function IsNumeric which returns 1 if number is integer otherwise 0:
CREATE FUNCTION IsNumeric (input varchar(1024)) RETURNS int
RETURN input REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
Then use following query to check room number:
select IF (IsNumeric(right(room,1))>0,
IF(right(room,1)%2=0,'Even','ODD'),
IF(left(right(room,2),1)%2=0,'Even','ODD')
) as room_number
from rooms;
Here in above query first check if last digit is integer, If so then check for even/Odd number. If digit is not integer pick the 2nd last digit and apply the same check.
I am trying to fetch rows from my database by checking if the json in one of their fields contains a specific id.
Example: col(kats): [2,4,7,9]
I am trying to do so by using the following query
SELECT column FROM table WHERE column REGEXP '(\[|\,)1(\]|\,)'
The Problem: MySQL returns 1 for every row in the table.
MySQL requires that any literal backslash \ characters (which are literal in the REGEXP string as escape characters to the following []) be escaped themselves. Thus, you must double-escape [] as \\[ and \\].
From the docs:
Because MySQL uses the C escape syntax in strings (for example, ā\nā to represent the newline character), you must double any ā\ā that you use in your REGEXP strings.
The rest of your pattern is basically correct, except that the comma , does not require escaping.
1 does not match:
> SELECT '[2,4,7,9]' REGEXP '(\\[|,)1(\\]|,)';
+--------------------------------------+
| '[2,4,7,9]' REGEXP '(\\[|,)1(\\]|,)' |
+--------------------------------------+
| 0 |
+--------------------------------------+
1 row in set (0.00 sec)
But 2 does match
> SELECT '[2,4,7,9]' REGEXP '(\\[|,)2(\\]|,)';
+--------------------------------------+
| '[2,4,7,9]' REGEXP '(\\[|,)2(\\]|,)' |
+--------------------------------------+
| 1 |
+--------------------------------------+
1 row in set (0.00 sec)