How to Bulk Update post titles wordpress through mySQL - mysql

All my post titles have a static word in front of them. I have over 9000 published posts with two different static words in my post titles. I am trying to remove this word from all my posts.
Essentially, I am looking for a way to remove that constant word. I tried using export through wordpress and editing the post titles that way, but the file was 100mb + and simply won't open.
I looked towards SQL/phpmyadmin but I am not very well versed with SQL queries and don't want to mess up my database.
The "Constant" is always the first word of the title. What could I do
to instead have mysql detect the first space and remove everything
before it as well as including the space. Essentially, removing the
first word. Basically I have more than one constant, so it would be
better if I could just find the first space in the string and then
remove it and everything before it. I'm assuming we'd use sub_string
or something.
This is the title structure
Constant other stuff here
so if there is a search query where it finds "Constant " and a space and replaces it with "" nothing, that way I could have it completely removed. It'd be great if it could be a search and replace query, so I could utilize it later.
Information on the Database / Table / Column
the table is called: wp_posts and it needs to be restricted to the value of the table post_type when it's value is post and the title is in the post_title column
Any help would be greatly appreciated.

MySQL doesn't have exactly what you're looking for -- yes, there is a REPLACE() string function, but you can't limit it to a single substitution. As such, you might inadvertently replace other occurrences of this constant that could conceivably appear in your title string.
IMHO, the easiest way is to find all titles starting with your constant, and just replace the first one (i.e. at the start of the string):
UPDATE wp_posts
SET post_title =
MID( post_title, LENGTH('Constant ')+1 )
WHERE post_title LIKE 'Constant %'
AND post_type = 'post';
You need the +1 because MySQL string offsets start at 1, not zero.
Personally, I always prefer to run the equivalent SELECT first, just to be certain (too many years of MyISAM without BEGIN WORK):
SELECT post_title,
MID( post_title, LENGTH('Constant ')+1 ) AS replacedTitle
FROM wp_posts
WHERE post_title LIKE 'Constant %'
AND post_type = 'post';
Alternatively, if you're certain that you always want to remove the first word (i.e. up to and including the first space), then the following statement should work:
UPDATE wp_posts
SET post_title =
MID( post_title, POSITION( ' ' IN post_title )+1 )
WHERE post_type = 'post';
Since POSITION() will return zero if no space is found, this statement will be a no-op (i.e. non-destructive) in the general case.

Search RegEx is a great plugin to be able to search and replace - with grep or plain text - through all post and page content, post titles, post meta, etc. Does not search custom post types.
Back up your DB before making any changes, either with this plugin or direct query in the database.
Docs: http://urbangiraffe.com/plugins/search-regex/

Related

MySQL find and update based on results from 2 tables

First off, please note that this is not answered in the question here:
MySQL update table based on another tables value
or indeed any other Stack question or answer that I could find!
I converted a forum on a website and now just need to repair the internal URL links on a few hundred of the posts.
Posts are found in the column post_content within the table xyz_posts
ID post_content
1467 This is great https://example.com/index.php?topic=1234 I really like it
1468 Hello world
1469 Take a look https://example.com/index.php?topic=5678.0
You can see the URLs are mostly buried in the post text.
Note that the example above can sometimes be written with topic=1234.0 at the end, although it is actually stored in the database as a value of 1234. I don't want to rewrite the url and accidentally keep the .0
Here's an example of how I need that table to look:
ID post_content
1467 This is great https://example.com/finished-page/ I really like it
1468 Hello world
1469 Take a look https://example.com/another-page/
So, the table xyz_converter maps the old topic number to the new post ID like this:
meta_key meta_value value_id
_bbp_old_topic_id 1234 15675
_bbp_old_reply_id 1234 17439
Caveat here, the number 1234 also exists in this table for forum replies which we don't want, but the meta_key and value_id are different for those as shown. This SQL query works to get to the right one:
SELECT * FROM `xyz_converter` WHERE meta_key LIKE '_bbp_old_topic_id' AND `meta_value` LIKE '1234'
Also in table xyz_posts we map the value_id mentioned above to the post's URL suffix like this:
ID post_name
15675 finished-page
15676 another-page
How do I construct a SQL query that will detect the meta_value in one table and then replace it with the correct final URL as mentioned?
PROCESS SUMMARY
Detect the URL in xyz_posts post_content
Extract the topic number from the URL (eg 1234). If it's 1234.0 then take just 1234
Convert it to a post number in found in xyz_converter value_id (eg 15675) ensuring it is found alongside _bbp_old_topic_id
Take the suffix of the URL in xyz_posts post_name (eg 'finished-page')
Rewrite the original URL to include the suffix (not forgetting the trailing slashes).
I'm using MySQL 5.7.29 and PHPMyAdmin.
I'm fairly new to SQL queries and a Regex noob, but willing to learn more!
A solution that uses only MySQL commands and works in MySQL 5.7 could be like this.
If .0 is present only in the urls you could use a query like this to remove all occurences of .0 from post_content in xyz_posts.
UPDATE `xyz_posts` SET post_content=REPLACE(post_content,'.0 ',' ') WHERE post_content LIKE '%topic=%.0 %';
Then you can use
CREATE TABLE temp_tbl
SELECT CONCAT('index.php?topic=',c.meta_value) as `find_value` ,p.post_name as `replace_value`
FROM `xyz_converter` c
INNER JOIN `xyz_posts` p ON c.value_id=p.id AND `meta_key`='_bbp_old_topic_id'
ORDER BY meta_value DESC;
UPDATE `xyz_posts` p
INNER JOIN `temp_tbl` t ON p.post_content LIKE CONCAT('%',t.find_value,'%')
SET p.`post_content`=REPLACE(p.`post_content`,t.find_value,t.replace_value);
The first command will create a temporary table where the first column will be the value that you want to find and replace like index.php?topic=1234 and the second column will be the value you want to be replace with like finished-page
The second command will replace posts_content in xyz_posts taking the first column from temp_tbl and replacing it with the second column.
Below an sql fiddle where you can see the solution in action
http://sqlfiddle.com/#!9/7bce8c
Of course you should first create a copy of your database and try these commands to ensure everything works fine before trying it in your production database.

MySQL Pattern matching to find specific text

My working database is from a webforum. In it, there's a table containing all the data of posts (I.e. the text a user submitted within a thread). These posts contain a column called message which is the actual content of the post. A post can contain any character, as well as smilies. Smilies are indicated by a colon, immediately followed by a short description of variable length and again a colon. I.e. :clap:. A single post can contain multiple smilies.
I am trying to come up with a way to pull out a list of all smilies within the posts table.
What I have working so far is a query that pulls a list of posts containing at least two colons:
SELECT
thread_id
, post_id
, SUBSTRING_INDEX(SUBSTRING_INDEX(message, ':', 2), ':', -1)
FROM
xf_post
WHERE
ROUND((CHAR_LENGTH(message) - CHAR_LENGTH(REPLACE(message, ':', ""))) / CHAR_LENGTH(':')) > 1
LIMIT 50
This works, but will also return messages where a user for whatever reason included multiple colons, like for instance random : text followed : by more text, or a timestamp: 00:00:12345.
What I'm hoping to achieve is to return all occurrences of alphanumeric characters enclosed between colons, without any spaces. (Yes, this will remove all smilies that are purely numeric, but ¯\_(ツ)_/¯).
I fiddled with REGEXP, and came up with the following: [:][a-zA-Z]+(?=:)[:] which according to regex101 yields exactly what I want.
How can I use this to capture the output, and only see the values between the semi-colons, and preferably in such a way it would show all occurrences of a smilie within a single post?
Thank you.
#SimonlucaLandi helped me at least figure out the way to display the results. My final query:
SELECT
thread_id
, post_id
, REGEXP_SUBSTR(message, '':[a-zA-Z]+:'')
FROM
xf_post
WHERE
message REGEXP '':[a-zA-Z]+:''
LIMIT 50

How to change multiple meta value in wordpress mysql database

I have a meta value "XXxSAZTm-dU" in table wp postmeta. Its same meta value for many posts like 50 posts use it becasuse its a part of video url. Now I want to update this meta value to new url so I need to change that "XXxSAZTm-dU" to "CCjddjXX-mY" in all that 50 posts. Can you please tell me how can I do that with mysql?
MySQL has a REPLACE function exactly for this purpose. It performs case-sensitive search and replace within strings (so, not only exact value in column, the haystack may be an URL or a full text, the needle will be found within the string and replaced with new value:
UPDATE wp_postmeta
SET meta_value = REPLACE(
meta_value,
'XXxSAZTm-dU',
'CCjddjXX-mY'
);

mysql to update a database using UPDATE SET and TRIM(LEADING wildcard prefix in record

In my database I have a table called 'content' and a field called 'link' and there are almost 300,000 records in that table.
In the field called 'link' there are a number of records that look like this :
http://www.example.com/blah/blah/123456789/url=http://www.destination.com
Unfortunately the prefix part of the records are individually unique where the numbered portion is constant changing from 90 to 150 alpha-numeric characters
I would like to remove the prefix up to and/or including the url=
So that the only thing left in the record is :
http://www.destination.com OR
I could even work with
url=http://www.destination.com
and simply do a replace command against the "url=" part as a second mysql command.
If there was a wildcard command, this job would be much easier and I would just wildcard everything showing up in the link record between :
http://www.example.com/blah/blah/ wildcard url=
But as everyone knows... there is no such wildcard available
So it had me looking at the UPDATE, SET and TRIM(LEADING commands
UPDATE content
SET link =
TRIM(LEADING 'url=' FROM link)
But this DID NOT generate the changes I wanted
And so I took the labor intensive method of downloading the database and using a Search and Replace program to make the changes to the 44 thousand records that contained these parameters.
But I would love to find a command that I could simply pass to the database to make this simpler in the future.
Any thoughts on how to accomplish this change in the future would be greatly appreciated.
Thanks in advance ;
You can use the SUBSTRING_INDEX function:
UPDATE content SET link=SUBSTRING_INDEX( `link` , 'url=', -1 )
I have not tested it, so I would recommend you check that substring_index returns the desired string first.
Assuming that the part you want to keep always begins with 'http://' you could get the desired result string with the help of the SUBSTRING_INDEX function:
SELECT CONCAT('http://', SUBSTRING_INDEX(link, 'http://', -1)) FROM content;
and fix your table with the simple statement
UPDATE
content
SET
link = CONCAT('http://', SUBSTRING_INDEX(link, 'http://', -1));
Explanation:
SUBSTRING_INDEX with third parameter negative returns the substring from the last occurence of the needle in the second parameter to the end. Because 'http://' isn't included in the return value, we add it again.
Remark:
If you've got https:// urls too, you should be able to adapt my solution.

using REPLACE in MySQL Query just isn't working

Quick background, I have a small database with a table named 'songs'. This table holds the title, artist and URL of music I have on my machine. Several of the single quotes have been dropped from the track title (for example, the don't is stored as dont) and I'm attempting to replace them. I just cannot get this query to affect any rows:
UPDATE Songs
SET Title = REPLACE (Title, 'dont', 'don\'t')
No love. Isn't this correct syntax? It tells me that 0 rows were updated.
If it helps, I'm running version 5.5.27. I know there are a couple hundred rows with improper donts in there... I'm about to dump the results into Notepad and do a find/replace on don't and just run an update statement that way, but it's kinda hacky. Any ideas friends?
A couple of sample rows:
"51","Dont Stay Home","311","311 Greatest Hits","Rap","E:\Music\311\311GreatestHits\dontstayhome.mp3"
"229","Dont Turn Around","Ace Of Base","The Very Best Of","Dance","E:\Music\AceofBase\VeryBestOf\03-ace_of_base-dont_turn_around.mp3"
The Fields in order are id, title, artist, album, genre, path
You have to do it like this
UPDATE Songs
SET Title = REPLACE(Title, 'Dont', 'Don\'t');
^ ^
The reason for that is
REPLACE(str,from_str,to_str)
Returns the string str with all occurrences of the string from_str
replaced by the string to_str. REPLACE() performs a case-sensitive
match when searching for from_str.
If you want to replace either case you can do
UPDATE Songs
SET Title = REPLACE(REPLACE(Title, 'Dont', 'Don\'t'), 'dont', 'don\'t')
WHERE Title LIKE '%dont%' -- it makes sense to limit update to only those rows that have dont in it no matter case
Here is SQLFiddle demo
The first thought is that there might be some invisible characters. What does the following return?
select *
from songs
where title like '%dont%';
EDIT:
I didn't notice this at first. The problem is the space after the function name. Try this:
UPDATE Songs
SET Title = REPLACE(Title, 'dont', 'don\'t');
This is explained in the documentation:
Note
By default, there must be no whitespace between a function name and
the parenthesis following it. This helps the MySQL parser distinguish
between function calls and references to tables or columns that happen
to have the same name as a function. However, spaces around function
arguments are permitted.
EDIT II:
I don't know if the collation has an effect. But you can also try using double quotes as the string delimiter:
UPDATE Songs
SET Title = REPLACE(Title, 'dont', "don't");