Regexp - back references, translating code from PHP to MySQL - mysql

I have a regular expression that works in PHP, but not the MySQL REGEXP function.
'(.)\1{2,}'
In PHP this matches any char that is repeated 2 or more times, how can I translate this to work with the MySQL function.

Sorry, you can't. MySQL uses POSIX regex, which doesn't support back-references. If you must perform such matches in MySQL, your only option is to install a UDF such as lib_mysqludf_preg.

Related

MySQL REGEXP_SUBSTR() escaping issue?

Please take the following example regex:
https://regexr.com/4ek7r
As you can see, the regex works great and matches the sizes (e.g. 3/16" etc) from the product descriptions.
I'm trying to implement this in MySQL 8.0.15 using REGEXP_SUBSTR()
As per the documentation I have doubled up the escape characters but the regex is not working.
Please see the following SQL fiddle:
https://www.db-fiddle.com/f/e6Ez3XCdU5Ahs91z6TQA8P/0
As you can see, REGEXP_SUBSTR() returns NULL
I'm presuming this is an escape issue - but i'm not 100% sure.
How can I ensure MySQL returns the 1st match per product (row) akin to the regexr.com example?
Cheers
Edit: 28/05/2019 - root cause
Wiktor's answer below solved my problem and his regex was much cleaner & well worth the upvote. That said, i didn't understand why my original version was not working after the port from SQL Server to MySQL. I finally noticed the problem this morning - it had nothing to do with the regex, it was a rookie error in string concatenation! Specifically, I was using UPPER(Description + ' ') (i.e. using +) - which works fine in SQL Server but obviously; MySQL forces numeric! So i was essentially running my regex against a 0! Replacing the + with CONCAT actually fixed my original query with original regex - just thought i'd share this in case it helps anyone else!
In MySQL v8.x that supports ICU regex, you may use
SELECT Description, REGEXP_SUBSTR(Description, '(?im)(?=\\b(?:[0-9/]+(?:\\.[0-9/]+)?\\s*(?:[X-]|$)|[0-9/\\s]+(?:\\.[0-9/]+)?(?:[CM]?M|["”TH])))[0-9/\\s.]+(?:[CM]?M|["”TH])?(?:\\s*[/X-]\\s*[0-9/\\s.]+(?:[CM]?M|["”TH])?)?(?=[.\\s()]|$)') AS Size FROM tbl_Example
The main points:
The flags can be used as inline options, (?mi), m will enable multiline mode when ^ and $ match start/end of a line and i will enable case insensitive mode
[$] matches a $ char, to match end of a line position, you need to move $ out of a character class, use alternations in this case ((?=[\.\s\(\)$]) -> (?=[.\s()]|$), yes, do not escape what does not have to be escaped, too)
Matching fractional number part, it is better to use a (?:\.[0-9/]+)? like pattern (it matches an optional sequence of . and then 1 or more digits or /s)
(C|M)? is better written as [CM]? (a character class is more efficient)

MySql arithmetic differs from Excel

I have plugged the same calculation into Excel and MySql and they are quite different.
Excel:
=(12^1.2299)/(12^1.16793+12^1.20053)*2.29761*11
MySql
select ((12^1.2299)/(12^1.16793+12^1.20053))*2.29761*11.0 AS Wrong
I believe Excel gives the correct answer of 14.14 while MySql gets 12.63.
I have put additional brackets and decimals in but it makes no difference,
Why is MySql so wrong?
You should be using the MySQL POWER() function instead of using the caret symbol. For example, instead of using 12^1.2299 you will want to use POWER(12,1.2299).
The ^ operator is a bitwise XOR in MySQL. You should use the POWER() function to calculate exponents instead of ^.
Example:
SELECT POWER(12,1.2299)/(POWER(12,1.16793)+POWER(12,1.20053))*2.29761*11.0 AS Correct
Returns 14.143896230490112

How to use regular expression in MySQL

I am using MySQL,I have table called constructions where there is a column called phone, phone numbers are in format 9876543210 but I want to clean the column wherever there are alphabets and symbols.
I was using:
select * from constructions where phone like '[a-Z]%';
but this is wrong, i guess it works in SQL-Server.
No to SQL Server unless you add a regular expression utility function. You have the built in find replace functions but those are very simple.
For MySQL look to the reference manual here >>> http://dev.mysql.com/doc/refman/5.0/en/regexp.html
Instead of LIKE use the RLIKE version that works with regular expressions.

MySQL find/replace with a unique string inside

not sure how far I'm going to get with this, but I'm going through a database removing certain bits and pieces in preparation for a conversion to different software.
I'm struggling with the image tags as on the site they currently look like
[img:<string>]<image url>[/img:<string>]
those strings are in another field called bbcode_uid
The query I'm running to make the changes so far is
UPDATE phpbb_posts SET post_text = REPLACE(post_text, '[img:]', '');
So my actual question, is there any way of pulling in each string from bbcode_uid inside of that SQL query so that I don't have to run the same command 10,000+ times, changing the unique string every time.
Alternatively could I include something inside [img:] to also include the next 8 characters, whatever they may be, as that is the length of the string that is used.
Hoping to save time with this, otherwise I might have to think of another way of doing it.
As requested.
The text I wish to replace would be
[img:1nynnywx]http://i.imgur.com/Tgfrd3x.jpg[/img:1nynnywx]
I want to end up with just
http://i.imgur.com/Tgfrd3x.jpg
Just removing the code around the URL, however each post_text has a different string which is contained inside bbcode_uid.
Method 1
LIB_MYSQLUDF_PREG
If you want more regular expression power in your database, you can consider using LIB_MYSQLUDF_PREG. This is an open source library of MySQL user functions that imports the PCRE library. LIB_MYSQLUDF_PREG is delivered in source code form only. To use it, you'll need to be able to compile it and install it into your MySQL server. Installing this library does not change MySQL's built-in regex support in any way. It merely makes the following additional functions available:
PREG_CAPTURE extracts a regex match from a string. PREG_POSITION returns the position at which a regular expression matches a string. PREG_REPLACE performs a search-and-replace on a string. PREG_RLIKE tests whether a regex matches a string.
All these functions take a regular expression as their first parameter. This regular expression must be formatted like a Perl regular expression operator. E.g. to test if regex matches the subject case insensitively, you'd use the MySQL code PREG_RLIKE('/regex/i', subject). This is similar to PHP's preg functions, which also require the extra // delimiters for regular expressions inside the PHP string
you can refer this link :github.com/hholzgra/mysql-udf-regexp
Method 2
Use php program, fetch records one by one , use php preg_replace
refer : www.php.net/preg_replace
reference:http://www.online-ebooks.info/article/MySql_Regular_Expression_Replace.html
You might be able to do this with substring_index().
The following will work on your example:
select substring_index(substring_index(post_text, '[/img:', 1), ']', -1)

MySQL: Find and Replace Between Certain Characters

In field post_content I have a string like this in nearly 800 rows:
http://somesite.com/">This is some site</a>
I need to remove everything from "> onwards so that it leaves just the URL. I can't do a straight find and replace because the text is unique.
Any clues? This is really my first foray into MySQL database modifications but I did do an extensive search before posting here.
Thanks,
~Kyle~
From this site: http://www.regular-expressions.info/mysql.html
LIB_MYSQLUDF_PREG
If you want more regular expression power in your database, you can consider using LIB_MYSQLUDF_PREG. This is an open source library of MySQL user functions that imports the PCRE library. LIB_MYSQLUDF_PREG is delivered in source code form only. To use it, you'll need to be able to compile it and install it into your MySQL server. Installing this library does not change MySQL's built-in regex support in any way. It merely makes the following additional functions available:
Here it comes...
PREG_CAPTURE extracts a regex match from a string. PREG_POSITION returns the position at which a regular expression matches a string. PREG_REPLACE performs a search-and-replace on a string. PREG_RLIKE tests whether a regex matches a string.
Sounds exactly what you're looking for.
All these functions take a regular expression as their first parameter. This regular expression must be formatted like a Perl regular expression operator. E.g. to test if regex matches the subject case insensitively, you'd use the MySQL code PREG_RLIKE('/regex/i', subject). This is similar to PHP's preg functions, which also require the extra // delimiters for regular expressions inside the PHP string.
See this post: How to do a regular expression replace in MySQL?
Either that or you could just write a script in any lanugage which goes through each record, does a regex replacement and then updates the field. For more info on regex, see here: http://www.regular-expressions.info/reference.html
There's a number of options. One might be to use SUBSTRING_INDEX():
UPDATE
table
SET field = SUBSTRING_INDEX( field, '">', 1 )
It's possible - there is a syntax for User Defined Functions which would let you pass in a regular expression pattern that matches the link and strips everything else.
However, this is quite complicated for somebody new to MySQL, and from your question, this sounds like a one-off. In which case - why not just use Excel and then reimport the data?
Great stuff!
All seems doable with a little bit of time and self education.
In the end, I exported that table as a CSV in Sequel Pro and did some nifty find and replace work in Coda. Not as sophisticated as your suggestions, but it worked.
Thanks again,
~Kyle~