I recently had put myself in a situation where I had to delete just about 10.000 posts in WordPress in a specific category. The reason for this was the design of the community link on tripwire magazine. At the time when I created it I thought it was an OK solution to add posts into a category only used for community submissions but as more and more people started using the feature I found that WordPress where literally becoming flooded with these posts and I spent too much time locating my own articles. I have been motivated to change this for month but lately I decided to migrate to the Headway theme (see review here) I thought the timing was good as I didn’t want to do too much tweaking in the theme to hide the community posts in all the post listings (front page, category lists etc.). My problem was how to actually get rid of all these posts and after trying different options I ended up coding my own SQL that I share with you in this post. Why is this even worth a post? Well I ran into a lot of requests from people trying to get this done in an efficient way but there where no solutions.
Advertisement
I considered and experimented with different options. The most obvious way to delete posts in WordPress is of cause to use the administration area but if you have many posts to delete if may take many hour. In my case 10.000 posts seamed to be overwhelming (close to 670 deletes of the 15 posts showed on one page in WordPress admin).
Bulk Delete WordPress Plugin
I decided to look for other and much easier solutions and I ran into Bulk Delete. Bulk Delete is a WordPress Plugin which can be used to delete posts in bulk from selected categories or tags. This Plugin can also delete all drafts, post revisions or pages.
So when there’s a plugin out there that seams to do the trick why didn’t I use it? Basically because I experienced some problems with it and never got it to work on my production site. The plugin rely (as far as I know) on the same functions that WordPress use when you delete a post through the admin. This sounds great right but it will put a lot of load on your server to process 10.000 posts and I ran into problems with memory and timeouts when I tested it.
SQL specifically designed to delete all posts in a WordPress Category.
OK so I had to look for other options. I normally find what I need for WordPress after a few minutes of searching Google but this time no solutions came up. I then decided to write a SQL script specifically targeted at deleting all posts in a Category in one efficient execution. I worked as a developer years ago but still it wasn’t that easy for me to crack the problem and I guess other can benefit from this.
WARNING USE THIS SCRIPT WITH CAUSION AND ONLY AFTER BACKING UP YOUR DATABASE! USE AT YOUR OWN RISK.
How to use it:
Step 1:
Log into your phpMyAdmin and locate your WordPress database
Step 2:
Press the SQL tab and fire off this SQL to make sure the right posts are selected. You need to add the target Category Id in stead of <category id> in the script. The script should select all the meta data WordPress collects for a post. You can check out the database ER diagram here that I used.
SELECT *
FROM wp_posts a
LEFT JOIN wp_term_relationships b ON ( a.ID = b.object_id )
LEFT JOIN wp_postmeta c ON ( a.ID = c.post_id )
LEFT JOIN wp_term_taxonomy d ON ( d.term_taxonomy_id = b.term_taxonomy_id )
LEFT JOIN wp_terms e ON ( e.term_id = d.term_id )
WHERE e.term_id =<category id>
This is how it should look:
OK so if you’re OK with the posts being selected you fire off this script. It deleted my 10.000 posts in less than a second. But be careful if you choose the wrong category you will not be able to get your posts back unless you restore from backup! The script will clean up all the metadata in the tables: wp_term_relationships, wp_postmeta, wp_term_taxonomy, wp_terms where I had hundreds of thousands of records. It is quite important to get this cleaned out
delete a,b,c,d
FROM wp_posts a
LEFT JOIN wp_term_relationships b ON ( a.ID = b.object_id )
LEFT JOIN wp_postmeta c ON ( a.ID = c.post_id )
LEFT JOIN wp_term_taxonomy d ON ( d.term_taxonomy_id = b.term_taxonomy_id )
LEFT JOIN wp_terms e ON ( e.term_id = d.term_id )
WHERE e.term_id =<category id>
Hope you will find this guide and the script useful and please leave a comment if you have any suggestions or comments on how to improve it.




{ 34 comments… read them below or add one }
It is too good work.here it consider time so it really useful to establishments great Thanks for sharing…
Thanks for sharing, This will come in handy for Wp-o-matic posts that aren’t worth posting
How do I delete posts posted before a certain date or number of days?
You need to use a where clause something like this: WHERE post_date < [certain date]
Great post, thanks…
The bulk delete plugin does not work
Excellent post guys, I was a bit reluctant to just delete from the wp_posts table and this was exactly what I was looking for.. thanks for sharing..
your welcome Peter, the right script for the job at the right time….;)
I’ve got a slightly different issue and could use some help. I’m willing to pay if you accept bribes
.
I have a category that has hundreds of subcategories (and sub-sub categories). I want a script that can mass reassign all the subcategories to the main category.
Please let me know if you can help!
Regards,
Marshall
Marshall, I don’t think it is that difficult, but I don’t have the time right now to do it for you. You can use this ER-diagram to understand how the database is structured.
Is there a way to delete post content older that 90 days but leave the title and exceprt in tact?
Wow, thank you! Total lifesaver.
Thanks Any! I also checked out your site. I’m sure it is a lifesaver for many people that are new to blogging. Good job you are doing there.
How about 57,000 posts in approximately 15,000 categories?
How about over 200,000 posts in over 45,000 categories…it works fine. Wouldn’t matter if it was a billion posts in a million categories. SQL doesn’t care about your numbers, all you need is patience
Very useful. I’ve been hacking at my SQL joins for two days now trying to figure this out. Thanks much!
You are welcome Dan… SQL can be tricky sometimes I know
Yup, you just helped me tremendously. I use feedwordpress to bring in hockey related news to a CPT, and it freaked out recently. I had 25000+ matching posts show up. Everything I tried would completely crash my WP install. Your bit of code above wiped everything out in seconds, with no trouble. I’ll be using your post over on VoodooPress for my followers, it is very helpful. I hope that’s cool? I will credit you as the source of course!
Great to hear that I helped you out here Voodoo!
Great work? it is helping me understand sql better. Question for you though this script also deleted the category. any way to keep categories and sub categories intact?
The reason why I ask is I am using a feed to populate a car dealers site. But on cron I would like all posts to be deleted then reloaded. that way when they sell a car it doesn’t stay on the site…. Also why checking for duplicates doesn’t work.
I have tried may different variations of your code and nothing seems to get it right so far. (without deleting everything)
Any help would be greatly appreciated.
I liked your article is an interesting technology thanks to google I found you
Thanks for the post, it really help me to solve my WordPress mass delete issue.
Great help but do you have a suggestion for also deleting all the comments attached to the posts being deleted? Those will be left behind in the db.
Great site you have got here.. It’s hard to find high-quality writing like yours nowadays. I really appreciate individuals like you! Take care!!
This is very very useful. Is it possible to delete multiple category id’s with this code? So instead of changing the code for each ID, just list them one after the other?
Thanks for this! Saved me a lot of time. I have been struggling with even very good/fast servers trying to delete a few hundred records at a time… now 1000 custom post-type records with 1/2 million child records gone in about a second. What on earth do the WordPress bulk delete routines do and how can they be that inefficient?!
Simon
This is undoubtedly an important post for me, but I stuck at one point.
I implement the code on the sql server and the same screen appear before me too, but I didn’t catch up your words. What did you mean by fire off the script? Can you please explain this.
I got this error for first Query!
#1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘ LIMIT 0, 30′ at line 7
Very useful LARS.
Thanks for sharing this nice tutorial I saved my lot of time after reading this.
1 more thing, I want to delete my all post WHERE post_status=’drafts’. But the problem is I am not able to delete other meta information’s.
Can you please help me to write this SQL query.
thanks in advance
Thanks a bunch. I’m trying to figure out how to edit this so that the category is not deleted along with everything else.
Thanks, I will keep this one handy for my development production dbs!
Thank you for the great post! It’s saved a lot of my time.
Hi, I have been looking for this piece of code for a long while now. So glad I found it. I have tried it out on an unimportant category on my website and found that when searching for the posts with the select query and a date criteria that it did indeed find all of the posts in that category posted before that date.
HOWEVER, when I ran the delete query, using the last line
WHERE e.term_id =122 AND post_date <'2013-01-01'it deleted everything posted in that category, and th category itself. Any ideas?Is there anybody out there who can help me out with this issue?
{ 4 trackbacks }