Select special characteres mysql - mysql

I need to make selects from fields that can contain special characteres for example
+--------------+
| code |
+--------------+
| **4058947"_\ |
| **4123/"_\ |
| sew'-8947"_\ |
+--------------+
i try this
select code from table where code REGEXP '[(|**4058947"_\|)]';
select code from table where code REGEXP '[(**4058947"_\)]';
select code from table where code REGEXP '^[(**4058947"_\)]';
but the querys return all rows and this query return empty
select code from table where code REGEXP '^[(**4058947"_\)]$';
and i need that only return the first one or the specified

To select only one row, you could just do this if it doesn't matter which one.
SELECT code FROM table LIMIT 1
If it does matter, drop the regex.
SELECT code FROM table WHERE code = "**4058947\"_\\"
To match those special characters (in this case, " and \), you need to "escape" them. (That's how it's called. I didn't make that up.) In most mainstream languages this is done by putting a backslash in front of it (MySQL does it this way too). The backslash is the escape character, a backslash with another character behind it is called an escape sequence. As you see, I escaped the quote and the backslash in the code value I want to match, so it should work now.
If you need to keep the regexes (which I hope is not the case, since you have the literal string you want to match against) same thing applies. Escape quotes and backslashes and you'll be fine, if you drop the parentheses and brackets. Note that in a regex, you need to escape far more characters. This is because some characters (for example: | [] () * + have a special function in a regex. This is very handy, but becomes a bit of a problem when you need to match a string with that character in it. In that case, you need to escape it, but with a double backslash! This is because MySQL first parses the query and will throw an error if it encounters an invalid escape sequence (that is, if you escape a character you needn't escape according to MySQL). Only then is the result parsed as a regex, with the double backslashes replaced by single backslashes. This gets ugly very quickly, since this means matching a backslash with a MySQL regex requires 4 backslashes! Two in the regex, but this needs to be doubled, since MySQL parses it as a string first!

Related

Escape single backslash in MySQL JSON INSERT

I'm trying to encode a regex in a JSON data field in a MySQL database.
The regex is as follows: ^\d*[13579]$ and should look the same, if I try to read it afterwards.
AFAIK, for single backslash escaping in SQL I need double backslashes.
However, when is replace the single backslash with two like this:
^\\d*[13579]$, I get an error stating:
Invalid JSON text: "Invalid escape character in string." and my IDE also shows it as an error. When I use another set of two backslashes, the error disappears, but I also get two backslashes in the final string.
Any idea, what the problem might be?
Thanks!
The double-backslash is correct for JSON.
JSON has its own escape sequences, similar to the escape sequences in regular expressions. In JSON, \b means backspace, \n means newline, \t means tab, and so on. If you want to store a literal backslash character, use \\. Otherwise the backslash must be followed by one of the recognized escape sequences.
If you store a literal backslash character in a JSON value, it must be a double backslash. If you extract that JSON value and "unquote" it, it will be returned as a single backslash as you intended.
Demo:
mysql> create table t ( j json );
mysql> insert into t set j = '["^\\\\d*[13579]$"]';
mysql> select j from t;
+-------------------+
| j |
+-------------------+
| ["^\\d*[13579]$"] |
+-------------------+
mysql> select j->>'$[0]' from t;
+--------------+
| j->>'$[0]' |
+--------------+
| ^\d*[13579]$ |
+--------------+

SQL Regex last character search not working

I'm using regex to find specific search but the last separator getting ignore.
Must search for |49213[A-Z]| but searches for |49213[A-Z]
SELECT * FROM table WHERE (data REGEXP '/\|49213[A-Z]+\|/')
Why are you using | in the pattern? Why the +?
SELECT * FROM table WHERE (data REGEXP '\|49213[A-Z]\|')
If you want multiple:
SELECT * FROM table WHERE (data REGEXP '\|49213[A-Z]+\|')
or:
SELECT * FROM table WHERE (data REGEXP '[|]49213[A-Z][|]')
Aha. That is rather subtle.
\ escapes certain characters that have special meaning.
But it does not seem to do so for | ("or") or . ("any byte"), etc.
So, \| is the same as |.
But the regexp parser does not like having either side of "or" being empty. (I suspect this is a "bug"). Hence the error message.
https://dev.mysql.com/doc/refman/5.7/en/regexp.html says
To use a literal instance of a special character in a regular expression, precede it by two backslash () characters. The MySQL parser interprets one of the backslashes, and the regular expression library interprets the other. For example, to match the string 1+2 that contains the special + character, only the last of the following regular expressions is the correct one:
The best fix seems to be [|] or \\| instead of \| when you want the pipe character.
Someday, the REGEXP parser in MySQL will be upgraded to PCRE as in MariaDB. Then a lot more features will come, and this 'bug' may go away.

MySQL regex matching at least 2 dots

Consider the following regex
#(.*\..*){2,}
Expected behaviour:
a#b doesnt match
a#b.c doesnt match
a#b.c.d matches
a#b.c.d.e matches
and so on
Testing in regexpal it works as expected.
Using it it in a mysql select doesn't work as expected. Query:
SELECT * FROM `users` where mail regexp '#(.*\..*){2,}'
is returning lines like
foo#example.com
that should not match the given regex. Why?
I think the answer to your question is here.
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.
MYSQL Reference
Because your middle dot wasn't properly escaped it was treated as just another wildcard and in the end your expression was effectively collapsed to #.{2,} or #..+
#anubhava's answer is probably a better substitute for what you tried to do though I would note #dasblinkenlight's comment about using the character class [.] which will make it easy to drop in a regex you've already tested in at RegexPal.
You can use:
SELECT * FROM `users` where mail REGEXP '([^.]*\\.){2}'
to enforce at least 2 dots in mail column.
I would match two dots in MySQL using like:
where col like '%#.%.%'
The problem with your code is that .* (match-everything dot) matches dot '.' character. Replacing it with [^.]* fixes the problem:
SELECT *
FROM `users`
where mail regexp '#([^.]*[.]){2,}'
Note the use of [.] in place of the equivalent \.. This syntax makes it easier to embed the regex into programming languages that use backslash as escape character in their string literals.
Demo.

How to filter for a specific set of characters ending with any digit?

I have a column containing values as strings. I need to keep only those that contain one of the following substrings: |MB1, |MB2, |MB3, |MB4, |MB5 and |MB6.
My starting point is:
select * from table
where column like '%|MB_%';
However, this would keep any other row with values such as |MBa or others. How do I get rid of them?
P.S. I am using MySQL
You can use MySQL's regular expression pattern matching;
WHERE `column` REGEXP '\\|MB[1-6]'
The pattern '\\|[1-6]' can be analysed as follows:
\\ is the string-encoding of a literal backslash, which is the regular expression escape character, so that
| is given no special meaning (if not escaped by backslash it would signify alternation, which would lead to an invalid pattern in this case)
MB are literal characters
[1-6] represents a single character within the range 1 through to 6

Mysql query returns no data with escaped \

I'm attempting to query our MSSQL database but I'm getting no data when there clearly is data there.
First I query
SELECT id, instruction_link FROM work_instructions WHERE instruction_link LIKE "%\\\\cots-sbs%";
Which returns 100+ lines.
http://tinypic.com/r/ief8td/8
(sorry couldn't post as actual picture, don't have enough rep :(
However if I query
SELECT id, instruction_link FROM work_instructions WHERE instruction_link LIKE "%\\\\cots-sbs\\%";
http://tinypic.com/r/33ksw3q/8
I get no results with the 2nd query. I have no idea what I'm doing wrong here. Seems pretty simple but I can't make any sense of it..
Thanks in advance.
As documented under LIKE:
Note
Because MySQL uses C escape syntax in strings (for example, “\n” to represent a newline character), you must double any “\” that you use in LIKE strings. For example, to search for “\n”, specify it as “\\n”. To search for “\”, specify it as “\\\\”; this is because the backslashes are stripped once by the parser and again when the pattern match is made, leaving a single backslash to be matched against.
\\% is parsed as a string containing a literal backslash followed by a percentage character, which is then interpreted as a pattern containing only a literal percentage sign.