2012-11-22 12 views
16

devo aggiornare una tabella con la seguente struttura:MySQL 5.5.24 - voce duplicata su UPDATE, quando non c'è alcuna reale duplicato

CREATE TABLE `eav_entity_attribute` (
    `entity_attribute_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Entity Attribute Id', 
    `entity_type_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Entity Type Id', 
    `attribute_set_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Set Id', 
    `attribute_group_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Group Id', 
    `attribute_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Id', 
    `sort_order` smallint(6) NOT NULL DEFAULT '0' COMMENT 'Sort Order', 
    PRIMARY KEY (`entity_attribute_id`), 
    UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_ATTRIBUTE_ID` (`attribute_set_id`,`attribute_id`), 
    UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID` (`attribute_group_id`,`attribute_id`), 
    KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_SORT_ORDER` (`attribute_set_id`,`sort_order`), 
    KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_ID` (`attribute_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Eav Entity Attributes' 

Sopra tabella contiene una singola riga:

INSERT INTO `eav_entity_attribute` 
(`entity_attribute_id`, `entity_type_id`, `attribute_set_id`, `attribute_group_id`, `attribute_id`, `sort_order`) 
VALUES 
(32758, 4, 224, 3423, 5171, 12) 

Sto eseguendo una procedura di importazione automatica, che leggerà una fonte esterna di dati e scriverò in questa tabella.

Questa importazione viene eseguita più volte e, pertanto, a volte gli stessi dati vengono importati più volte. In tal caso, la procedura semplicemente sovrascrive i vecchi dati con quello nuovo, anche quando il nuovo è identico al vecchio. La condizione in cui esiste lo stesso dato viene gestita con una clausola ON DUPLICATE KEY UPDATE. Funziona quasi perfettamente, tranne su questo specifico tavolo.

Su questa tabella, quando la procedura tenta un AGGIORNAMENTO, ricevo un messaggio "Duplica chiave", che non riesco a spiegare. Ho il debug del codice, e questa è la query che fallisce (estratto dal INSERT..ON DUPLICATE KEY):

UPDATE eav_entity_attribute 
SET 
    `attribute_group_id` = 3423 
    ,`attribute_id` = 5171 
    ,`attribute_set_id` = 223 
    ,`entity_type_id` = 4 
    ,`sort_order` = 320 
WHERE 
    (`attribute_group_id` = 3423) AND 
    (`attribute_id` = 5171) 

L'errore è la seguente:

Error Code: 1062. Duplicate entry '3423-5171' for key 'UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID' 

So che la coppia 3423 -5171 esiste già, ma l'UPDATE sostituirà questi valori con se stessi, non crea una nuova voce. Sono abbastanza confuso riguardo alla causa di questo problema, ogni suggerimento sarebbe molto gradito. Grazie.

Aggiornamento - Nuova trovare

ho avuto una sorta di "ispirazione" e ho fatto un esperimento. Ho rimosso il vincolo Unique relativo a (attribute_set_id, attribute_id) (nota, questo non è quello nell'errore) e ho eseguito la query INSERT..ON DUPLICATE. Ha funzionato perfettamente.

mio è una congettura, ma questo è quello che penso: i dati che sto cercando di scrivere agli scontri tavolo con due vincoli:

  • unici (attribute_set_id, attribute_id)
  • UNICHE (attribute_group_id , attribute_id)

l'inserimento non riesce, presumibilmente a causa dell'errore di duplicazione sollevata dal primo vincolo . Ciò attiva l'UPDATE, che utilizza il primo vincolo come clausola WHERE implicita. La mia ipotesi è che, in tal caso, il primo vincolo viene in qualche modo ignorato, ma l'UPDATE scatta oltre il secondo, che non è stato coinvolto prima.

Questo non mi sembra, ancora, un motivo valido per un UPDATE che sostituisce qualcosa con se stesso per generare un errore di immissione duplicato, ma potrebbe far luce sulla logica alla base.

secondo aggiornamento

ho scoperto che la tabella stavo testando contro in realtà contiene un sacco di righe (ho dimenticato di disattivare la visualizzazione filtrata) derivante dall'importazione di successo di altri dati.Tuttavia, il "candidato duplicato" è ancora univoco nel set.

Confermo ciò che è stato postato nei commenti, quando la tabella contiene solo quelle righe, l'INSERT..ON DUPLICATE funziona, così come l'UPDATE da solo. Ora mi chiedo perché la tabella si incasina quando ci sono più dati in essa, dal momento che stiamo ancora parlando di una singola riga unica che viene aggiornata con gli stessi dati.

terzo aggiornamento - Trovato la causa principale

ho finalmente scoperto il motivo per cui l'aggiornamento non riesce, ora devo scoprire come faccio ad avere in tale condizione.

L'indizio era la mia congettura nel primo aggiornamento. Semplicemente, ho due file molto simili (si noti che sto usando valori diversi come ho iniziato da un database pulito).

row,entity_attribute_id,entity_type_id,attribute_set_id,attribute_group_id,attribute_id,sort_order 
1,16919, 4, 120, 1746, 80, 1 
2,16649, 4, 119, 1744, 80, 210 

Ecco cosa succede:

  • L'INSERTO tenta di inserire una riga con i seguenti valori: 120, 4, 1744, 80, 54.
  • Questo attiva la "chiave duplicata", poiché i valori 120, 80 sono duplicati per i campi attribute_set_id, attribute_id (riga 1).
  • MySQL tenta quindi l'UPDATE, che diventa la seguente:

    UPDATE tabella entity_type_id = 4 , attribute_group_id = 1744 , sort_order = 54 WHERE (attribute_set_id = 120) AND (attribute_id = 80)

  • Questa volta, l'aggiornamento non riesce perché i valori sono 1744,80 violano il vincolo sulla coppia attribute_group_id, attribute_id, trovato in fila 2.

In sintesi

  • L'inserimento non riesce perché riga 1 ha gli stessi valori per la chiave attribute_set_id, attribute_id.
  • L'UPDATE non riesce perché la riga 2 ha gli stessi valori per la chiave attribute_group_id, attribute_id.

Soluzione

dovrò rivedere l'intera procedura di importazione, come, in teoria, nessuno di tali duplicati dovrebbe sorgere. MySQL sta facendo bene il suo lavoro, è il database che è complicato.

Grazie per tutti i suggerimenti.

+0

MySQL 5.5.24. L'ho aggiunto al titolo. – Diego

+3

Strano, funziona in 5.5.28. http://sqlfiddle.com/#!2/81569 –

+1

Funziona in 5.5.20 con le domande della domanda; le dimensioni del tavolo sono importanti, suppongo. – raina77ow

risposta

2

Cercare di non aggiornare i valori della chiave all'interno della clausola UPDATE di INSERT ... ON DUPLICATE KEY UPDATE. È strano chiedere a MySQL di modificare i valori chiave se esiste già un record con questi valori chiave, quindi il comportamento inaspettato di MySQL non è sorprendente.

+0

L'uso di "ON DUPLICATE KEY UPDATE" non comporta alcun comportamento strano, il problema è dovuto a una serie di circostanze ed è ora risolto. Sto preparando una risposta completa che la documenta. – Diego

+0

Sembra che questa risposta sia abbastanza vicina! Un aggiornamento a un valore chiave all'interno dell'aggiornamento chiave duplicato era sicuramente il colpevole. (Solo un avvertimento credo che MySQL si sia comportato in modo prevedibile anche in queste circostanze) –

Problemi correlati