My existing data in the termmeta table:

meta_id term_id meta_key meta_value
27374 546 1C_id 9095b4cf-969d-11e9-a601-5cf3706390c8
27918 546 tax_position 1

My code:

$found_id = $wpdb->get_var("SELECT term_id FROM `{$wpdb->prefix}termmeta` WHERE meta_value='{$group['1C_id']}'");

if(!empty($found_id)) $wpdb->update($wpdb->prefix.'termmeta', array('meta_key' => '1C_id', 'meta_value' => $group['1C_id']), array('term_id'=>$found_id));

This deletes the tax_position meta and duplicates the 1C_id meta row, can't figure out why. No other piece of my code deals with this meta field.

  • I'd try update_term_meta instead if you haven't already. But I can't see what's wrong with that at first glance though.
    – Rup
    Commented Jul 13, 2021 at 8:42
  • I'd also try the Query Monitor plugin to see what SQL WordPress is running for that update, and why it's going wrong. But I'd guess something else is doing it, not this code.
    – Rup
    Commented Jul 13, 2021 at 8:44
  • I don't use update_term_meta because I deal with terms in bulk, and with WPDB I can turn autocommit off;
    – Artem
    Commented Jul 13, 2021 at 10:33
  • I wrote my own query, and it still duplicates my meta: $wpdb->query("INSERT INTO {$wpdb->prefix}termmeta (term_id,meta_key,meta_value) VALUES('{$check_term_name}','1C_id','{$group['1C_id']}') ON DUPLICATE KEY UPDATE meta_value = '{$group['1C_id']}'");
    – Artem
    Commented Jul 13, 2021 at 10:34
  • Hold on. I guess what I need in the first place is a unique term_id+meta_key key, right?
    – Artem
    Commented Jul 13, 2021 at 10:34

1 Answer 1


Your UPDATE command would look like so after all variables are substituted — and in this example, the table prefix is wp_ (the default one), $group['1C_id'] is 9095b4cf-969d-11e9-a601-5cf3706390c8, and $found_id (the term ID) is 123.

UPDATE `wp_termmeta`
SET `meta_key` = '1C_id', `meta_value` = '9095b4cf-969d-11e9-a601-5cf3706390c8'
WHERE `term_id` = 123

So that means, all existing meta where the term ID is 123 and regardless what the meta key is, will be changed:

  • First, the meta key is set to 1C_id, so the tax_position meta was renamed to 1C_id.

  • Secondly, the meta value is set to 9095b4cf-969d-11e9-a601-5cf3706390c8, which became the tax_position's new value.

So that explains this: "This deletes the tax_position meta and duplicates the 1C_id meta row".

I.e. The tax_position meta was not deleted, but only its key and value that were changed, and that they're set to the same ones for the existing 1C_id meta.

Therefore, $wpdb->update() did not actually delete or add any metadata. It's your query which isn't done correctly.

So maybe you're trying to do something like this?

Note that I used $wpdb->prepare() to prepare the query for safe execution, and you should do the same.

// Select meta IDs by meta value.
$meta_ids = $wpdb->get_col( $wpdb->prepare( "
    SELECT meta_id FROM $wpdb->termmeta
    WHERE meta_value = %s
", $group['1C_id'] ) );

// Then update all the above meta by the meta ID.
if ( ! empty( $meta_ids ) ) {
    $wpdb->query( $wpdb->prepare( "
        UPDATE $wpdb->termmeta
        SET meta_key = '1C_id', meta_value = %s
        WHERE meta_id IN (" . implode( ',', $meta_ids ) . ")
    ", $group['1C_id'] ) );

    /* Or you can use update_metadata_by_mid():
    foreach ( $meta_ids as $meta_id ) {
        update_metadata_by_mid( 'term', $meta_id, $group['1C_id'], '1C_id' );

But then, why are you UPDATE-ing the meta value with the same value ($group['1C_id']) used when SELECT-ing the meta? Was that a typo? (Maybe you just wanted to update the meta key..?)

  • 1
    Sally, you're my angel. Reading all your answers is on my to-do list. I can see I misused the $wpdb->update(), like the 1st key-value pair was a WHERE clause, and didn't notice my meta_id wasn't changing.
    – Artem
    Commented Jul 14, 2021 at 2:59
  • As for your question, I tried to make my example as simple as possible, so that, when I saw any changes in my table, I'd know something's wrong. My actual code finds the term by name, and then, if the 1C_id is different, decides what to do according to site options: replace its 1C_id with the current one or create a new term with the same name
    – Artem
    Commented Jul 14, 2021 at 3:02
  • I see. But actually, I also wanted to suggest you to use the term meta API (except maybe for selecting the meta IDs), and you could setup a cron (or background) job to process the bulk term updates, and there's also the wp term meta command in WP-CLI which I believe could help you (see kinsta.com/blog/wp-cli/#using-bash-scripts). Anyway, thanks for the upvotes :)
    – Sally CJ
    Commented Jul 14, 2021 at 3:55
  • Sally, thank you for your advice. In my current project I achieved good results using wpdb, as opposed to wp APIs. It takes only a few MYSQL requests to import tens of thousands of items, each one with multiple images, and hundreds of terms. The program I deal with sends me an xml file over http, I convert it into a temp DB (with a php generator), then use single requests to deal with all items in bulk (like 10 requests total), it gives me very reasonable server loads and my php script never runs out of memory and time.
    – Artem
    Commented Jul 14, 2021 at 6:35
  • 1
    Thank you Sally. Great point on plugin actions. DB input, wilco. )
    – Artem
    Commented Jul 16, 2021 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.