MySQL for replace with wildcard - mysql

I'm trying to write a SQL update to replace a specific xml node with a new string:
UPDATE table
SET Configuration = REPLACE(Configuration,
"<tag>%%ANY_VALUE%%</tag>"
"<tag>NEW_DATA</tag>");
So that
<root><tag>SDADAS</tag></root>
becomes
<root><tag>NEW_DATA</tag></root>
Is there a syntax im missing for this type of request?

Update: MySQL 8.0 has a function REGEX_REPLACE().
Below is my answer from 2014, which still applies to any version of MySQL before 8.0:
REPLACE() does not have any support for wildcards, patterns, regular expressions, etc. REPLACE() only replaces one constant string for another constant string.
You could try something complex, to pick out the leading part of the string and the trailing part of the string:
UPDATE table
SET Configuration = CONCAT(
SUBSTR(Configuration, 1, LOCATE('<tag>', Configuration)+4),
NEW_DATA,
SUBSTR(Configuration, LOCATE('</tag>', Configuration)
)
But this doesn't work for cases when you have multiple occurrences of <tag>.
You may have to fetch the row back into an application, perform string replacement using your favorite language, and post the row back. In other words, a three-step process for each row.

Related

MYSQL REGEXP with JSON array

I have an JSON string stored in the database and I need to SQL COUNT based on the WHERE condition that is in the JSON string. I need it to work on the MYSQL 5.5.
The only solution that I found and could work is to use the REGEXP function in the SQL query.
Here is my JSON string stored in the custom_data column:
{"language_display":["1","2","3"],"quantity":1500,"meta_display:":["1","2","3"]}
https://regex101.com/r/G8gfzj/1
I now need to create a SQL sentence:
SELECT COUNT(..) WHERE custom_data REGEXP '[HELP_HERE]'
The condition that I look for is that the language_display has to be either 1, 2 or 3... or whatever value I will define when I create the SQL sentence.
So far I came here with the REGEX expression, but it does not work:
(?:\"language_display\":\[(?:"1")\])
Where 1 is replaced with the value that I look for. I could in general look also for "1" (with quotes), but it will also be found in the meta_display array, that will have different values.
I am not good with REGEX! Any suggestions?
I used the following regex to get matches on your test string
\"language_display\":\[(:?\"[0-9]\"\,)*?\"3\"(:?\,\"[0-9]\")*?\]
https://regex101.com/ is a free online regex tester, it seems to work great. Start small and work big.
Sorry it doesn't work for you. It must be failing on the non greedy '*?' perhaps try without the '?'
Have a look at how to serialize this data, with an eye to serializing the language display fields.
How to store a list in a column of a database table
Even if you were to get your idea working it will be slow as fvck. Better off to process through each row once and generate something more easily searched via sql. Even a field containing the comma separated list would be better.

How to escape a whole sql string instead of escaping each argument?

I use https://github.com/mysqljs/mysql.git library.
I have a mysql db query architecture in which I can not modify the SQL query file one by one to escape each argument for there are too many files, but all the SQL queries will call the query method of a same base mysql instance, so I wonder if I can escape the eventual SQL string in the base mysql query method.
I want to escape the whole SQL string like
select * from tableA where name = 'foo'bar
to
select * from tableA where name = 'foo\'bar'
with some function like mysql_escape("select * from tableA where name = 'foo'bar'") instead of doing this using preparing queries or concating escaped strings.
There isn't a way to do this that wont result in a really inefficient function or some bad hack. Just use parameterized queries, Its basically what they are there for. If you cant use those you use concat strings.
Running mysql_escape on a whole query will require the function to know what characters are part of your query and what characters are part of the input values. You could write some kind of stupid regex to try pull the values from the query and then escape them but its just a bad idea.

Search and replace JSON in Mysql with regex

Is it possible to search and replace with a regex expression in MySQL?
I have a thousand values on a column containing a JSON string, somewhere inside each JSON are several occurrences of a string that I have to change.
I've already made a PHP script that do the job, but it is a little slow.
Is there a nicer way to do that using only MySQL?
Something like:
UPDATE mytable SET value = "disabled" WHERE data REGEXP '{"field": "(.+)"}'
MariaDB has REGEXP_REPLACE(), which might provide the tool you need.

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)

Is there a mySQL equivalent to Postgresql's "Dollar-Quoted String Constants"?

In postgresql, it's possible to use "Dollar-Quoted String Constants" to avoid escaping single quotes in constant strings:
Without Dollar-Quoted String Constants:
'Jeff''s table'
With Dollar-Quoted String Constants:
$$Jeff's table$$
Is there a MySQL equivalent?
On edit: I'm not looking for a way to sanitize inputs, I'm looking for a way to make queries that generate sql easier to read.
No, because it doesn't really work. An attacker just addes a pair of dollar signs to their injection attempt instead.
The correct way to handle this is a system that uses real query parameters, such that the parameter values are never substituted directly into a query string. This is also generally better for performance because the db can do a better job caching the execution plan you don't end up building string dynamically, which tends to be slow in modern languages.
Not having excess concatenation statements greatly improves the readability of the code, as well. Instead of this:
sql = "SELECT * FROM MyTable WHERE Column1=$$" + somevarialbe + "$$ AND Column2=$$" + OtherVariable";
it's just this:
sql = "SELECT * FROM MyTable wHERE Column1=#Value1 AND Column2=#Value2";
Hmm... Okay, I can see some limited utility for this feature now.
Imagine a ticket tracking system with a stored procedure to get open tickets. You might actually hard-code the literal 'open' into the where clause of the query. Not that this would be a good design — ticket status should be in a table with it's own key, so that you'd hardcode the key rather than the text. But it plants the seed for something valid and more-complicated.
You can enclose your string in double quotes instead, e.g.
"Jeff's table"
Note: If this doesn't work, it means that you've got ANSI_QUOTES SQL mode turned on. The MySQL docs say:
If the ANSI_QUOTES SQL mode is enabled, string literals can be quoted only within single quotation marks because a string quoted within double quotation marks is interpreted as an identifier.