WPDB Insert o Update se esiste
Non ho molta familiarità con WPDB o SQL in generale, ma ho una tabella personalizzata per il mio progetto e sto cercando di assegnarvi dei metadati. Quello che vorrei ottenere è che se una riga esiste, venga aggiornata e se non esiste venga inserita. Ho letto sia Insert che Update nel Codex di WPDB ma nessuno dei due approfondisce una situazione del tipo "o uno o l'altro". Pensavo di poter lavorare con update, quindi il mio codice finora appare così:
$wpdb->update(
$wpdb->prepare(
$wpdb->prefix.'item_info',
array(
'post_id' => $post_id,
'item_stock' => $item_stock
),
array('post_id' => $post_id)
)
);
WordPress ha qualcosa del tipo "SE esiste Update, ALTRIMENTI Insert", o devo eseguire SQL personalizzato per ottenere questo, oppure devo prima interrogare il database per vedere se un ID esiste nella mia tabella e POI decidere se aggiornarlo o inserirlo?
Hai provato $wpdb->replace
. Secondo il WP Codex:
Sostituisce una riga in una tabella se esiste o inserisce una nuova riga se non esiste già.
L'ho provato personalmente in alcuni plugin e funziona bene quando si cerca di evitare errori di duplicazione di ID univoci, ecc.

Questo ha funzionato per me mentre una query personalizzata no - grazie per aver menzionato replace()

vale la pena notare che $wpdb->replace
è una sovrascrittura distruttiva dell'intero record, mentre $wpdb->update
aggiorna solo i campi specifici inclusi nell'array $data

Al momento questa funzione non effettua la sostituzione per me. Duplica le stesse righe. Può essere un campo PRIMARY KEY (id) la causa che impedisce la sostituzione? Non trovo informazioni al riguardo nel Codex.

Ho capito: Per mitigare questo problema di sostituzione, è anche necessario applicare il vincolo UNIQUE a colonne specifiche durante la creazione della tabella, rendendo così possibili righe univoche.

Innanzitutto, stai usando prepare
in modo errato. Sembra che tu abbia racchiuso gli argomenti di $wpdb->update
in $wpdb->prepare
in questo modo. Non funzionerà. In pratica, stai passando a update
un singolo argomento - l'output di prepare
. Prova qualcosa di semplice come il seguente e capirai perché non funziona:
$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)
)
);
E $wpdb->update()
esegue prepare
per te.
In secondo luogo, se fossi in te, eviterei l'inutile complicazione delle funzioni helper e scriverei una corretta query 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); // debug
$sql = $wpdb->prepare($sql,$post_id,$item_stock,$item_stock);
// var_dump($sql); // debug
$wpdb->query($sql);
Questo presuppone che post_id
sia un UNIQUE
index o PRIMARY KEY
. Se la struttura della tua tabella è quella che penso, lascia che sia il database a gestirla.

Prepare restituisce false per me - nessun altro errore del database. Se eseguo la query manualmente in phpmyadmin funziona come previsto. Ho anche verificato che le variabili siano quelle che dovrebbero essere... Hai qualche idea?

Puoi provare ad aggiornare la tabella utilizzando $wpdb->update
, nel seguente codice sto usando l'id, ma puoi utilizzare qualsiasi criterio.
$result = $wpdb->update($tableName, $info, array('id' => $info["id"]));
// Se non trova nulla da aggiornare, proverà a creare il record.
if ($result === FALSE || $result < 1) {
$wpdb->insert($tableName, $info);
}
Risultato dell'output di Update()
$result === FALSE
: Fallimento$result === 0
: Successo, ma nulla è stato aggiornato$result > 1
: Successo e aggiornato
