By doing a `SHOW CREATE TABLE` on `wp_postmeta`, I got the structure of that table which included this: PRIMARY KEY (`meta_id`), So the key that MySQL can do the 'insert or update' on is the meta_id, which you're not providing. Therefore in your query, it will always be added as a new row. EDIT: The docs for `INSERT ON DUPLICATE UPDATE` say that it looks at either the PRIMARY KEY or any UNIQUE index, so you could possibly get around this by creating a new UNIQUE index on the combination of `post_id` and `meta_key` which might solve your problem. If this is a big table for you that could be a bad idea because it might slow down some read or write operations. I'm not sure if this will work, and please be careful with database performance, but this is worth a go: `ALTER TABLE 'wp_postmeta' ADD UNIQUE 'post_metakey_index' ('post_id', 'meta_key');`