WPDB Insertar o Actualizar si existe
No estoy muy familiarizado con WPDB o SQL en general, pero tengo una tabla personalizada para mi proyecto y estoy tratando de asignarle algunos metadatos. Lo que me "gustaría" que sucediera es que si existe una fila, se actualice y si no, se inserte. He leído tanto Insert como Update en el Codex de WPDB, pero ninguno profundizó realmente en una situación de "uno u otro". Pensé que podría trabajar con update, así que mi código hasta ahora se ve así:
$wpdb->update(
$wpdb->prepare(
$wpdb->prefix.'item_info',
array(
'post_id' => $post_id,
'item_stock' => $item_stock
),
array('post_id' => $post_id)
)
);
¿WordPress tiene algo como "SI existe Actualizar, SI NO Insertar", o necesito ejecutar SQL personalizado para lograr esto, o necesito consultar primero la base de datos para ver si existe un ID en mi tabla y LUEGO decidir si actualizarlo o insertarlo?

¿Has probado $wpdb->replace
? Según el WP Codex:
Reemplaza una fila en una tabla si existe o inserta una nueva fila si la fila no existía previamente.
Lo he probado yo mismo en algunos plugins y funciona cuando intentas evitar errores de duplicación de IDs únicos, etc.

Esto funcionó para mí mientras que la consulta personalizada no lo hizo - gracias por mencionar replace()

vale la pena mencionar que $wpdb->replace
es una sobrescritura destructiva de todo el registro, mientras que $wpdb->update
solo actualiza los campos específicos incluidos en el arreglo $data

Esta función no está haciendo el reemplazo por mí en este momento. Duplica las mismas filas. ¿Puede ser que un campo PRIMARY KEY (id) sea la causa que impide que ocurra el reemplazo? No encuentro información sobre esto en el Codex.

Lo resolví: Para mitigar este problema de reemplazo, también es necesario aplicar la restricción UNIQUE a columnas específicas al crear la tabla, haciendo así posibles filas únicas.

Primero, estás usando prepare
incorrectamente. Parece que tienes los argumentos de $wpdb->update
envueltos en $wpdb->prepare
de esa manera. Eso no funcionará. En efecto, le estás pasando a update
un solo argumento: la salida de prepare
. Prueba algo simple como lo siguiente y verás por qué no funcionará:
$post_id = 123;
$item_stock = 567;
var_dump(
$wpdb->prepare(
$wpdb->prefix.'item_info',
array(
'post_id' => $post_id,
'item_stock' => $item_stock
),
array('post_id' => $post_id)
)
);
Y $wpdb->update()
ejecuta prepare
por ti.
Segundo, si fuera yo, omitiría las funciones auxiliares redundantes y escribiría una consulta adecuada con ON DUPLICATE KEY UPDATE
:
$sql = "INSERT INTO {$wpdb->prefix}item_info (post_id,item_stock) VALUES (%d,%s) ON DUPLICATE KEY UPDATE item_stock = %s";
// var_dump($sql); // depuración
$sql = $wpdb->prepare($sql,$post_id,$item_stock,$item_stock);
// var_dump($sql); // depuración
$wpdb->query($sql);
Esto asume que post_id
es un UNIQUE
index o PRIMARY KEY
. Si la estructura de tu tabla es lo que creo que es, deja que la base de datos lo maneje.

Prepare me devuelve false - sin otros errores de base de datos. Si ejecuto la consulta manualmente en phpmyadmin, funciona como se espera. También verifiqué que las variables son lo que deberían ser... ¿Alguna idea?

Puedes intentar actualizar la tabla usando $wpdb->update
, estoy usando el id en el siguiente código, pero puedes usar cualquier criterio.
$result = $wpdb->update($tableName, $info, array('id' => $info["id"]));
//Si no encuentra nada para actualizar, intentará crear el registro.
if ($result === FALSE || $result < 1) {
$wpdb->insert($tableName, $info);
}
Resultados posibles de Update()
$result === FALSE
: Fallo$result === 0
: Éxito, pero no se actualizó nada$result > 1
: Éxito y se actualizó
