Newsgroup: it.comp.www.php
Titolo: update -> Duplicate entry

Ciao ng.
Su questa tabella:
CREATE TABLE `prova` (
  `Gruppo` int(11) NOT NULL default '0',
  `Prog` int(11) NOT NULL default '0',
  `Descrizione` varchar(100) default '',
  PRIMARY KEY  (`Gruppo`, `Prog`)
) TYPE=MyISAM;
Eseguo questa query:
UPDATE Prog SET Prog=Prog+1 WHERE Gruppo=16 AND Prog>=1
E ottengo un errore di tipo Duplicate entry!
Com'è possibile?
Grazie, ciao.
PS:
    Apache 1.3.26
    PHP 4.3.1
    MySql 4.0.12-nt

Scusate: ho commesso un errore di copia&incolla!
mysql_query('UPDATE Prova SET Prog=Prog+1 WHERE Gruppo=16 AND Prog>=1');
Questa è l'istruzione sql che mi genera l'errore di tipo "Duplicate entry!".

 Questa è l'istruzione sql che mi genera l'errore di tipo "Duplicate entry!".
Credo che tu abbia diversi record con Gruppo=16 e Prog che assume 
diversi valori in sequenza, diciamo da 1 a 10.
Quando MySql esegue la query, va ad aggiornare il record con Prog=1 
tentando di assegnare a Prog il valore 2, ma esiste gia' un altro record 
con Prog=2 e Gruppo=16, da cui l'errore di "Duplicate entry".
-- 
Jagui


probabilmente è perchè le PRIMARY KEY non posono avere duplicati: mentre
aggiorni
1
2
3
diventano, alla prima UPDATE
2 <- forse è qui che dà l'errore
2
3
Vado a dare una letta al manuale...
http://www.mysql.com/doc/en/CREATE_TABLE.html
- A PRIMARY KEY is a unique KEY where all key columns must be defined as NOT
NULL. If they are not explicitly declared as NOT NULL, it will be done
implicitly (and quietly). In MySQL the key is named PRIMARY. A table can
have only one PRIMARY KEY. If you don't have a PRIMARY KEY and some
applications ask for the PRIMARY KEY in your tables, MySQL will return the
first UNIQUE key, which doesn't have any NULL columns, as the PRIMARY KEY.
- A PRIMARY KEY can be a multiple-column index. However, you cannot create a
multiple-column index using the PRIMARY KEY key attibute in a column
specification. Doing so will mark only that single column as primary. You
must use a separate PRIMARY KEY(index_col_name, ...) clause.
Beh, dovrebbe essere giusto quello che ho detto...
Ludovico

 con Prog=2 e Gruppo=16, da cui l'errore di "Duplicate entry".
Avevo intuito che è questo il funzionamento di MySql ma... non è errato???
Insomma mi aspetterei che MySql effettuasse le modifiche su tutti i record
interessati e solo alla fine andasse a verificare le regole del db (PK, IC,
...)
Sarà che ho lavorato per anni con MS SQLServer (che permette questo genere
di operazioni) ma il comportamento di MySql non mi sembra corretto!

 di operazioni) ma il comportamento di MySql non mi sembra corretto!
Se e' corretto non lo so, ma ti posso dire per averlo provato che anche 
PostgreSql e PointBase (2 database importanti) si comportano come MySql.
Si possono immaginare situazioni in cui gli aggiornamenti dei record 
dipendono in qualche modo dagli aggiornamenti dei record precedenti, 
ecco che la scelta di MySql appare sensata.
-- 
Jagui

 ecco che la scelta di MySql appare sensata.
Sarà però MS SQLServer e Oracle (anche questi decisamente importanti!)
implementano il concetto di "constraint deferred" (quello di cui stiamo
parlando!), nel caso delle situazioni di cui accenni tu basta fare un update
dei singoli record!
Insomma secondo me una singola istruzione SQL di base (UPDATE, INSERT,
CREATE, ...) dovrebbe essere considerata atomica e appunto per questo le
regole dovrebbero essere considerate dopo la sua completa esecuzione
eventualmente facendo fallire tutte le modifiche apportate se anche una sola
regola non è rispettata (lo stesso concetto di atomicità utilizzato per le
transazioni).
Il top sarebbe che si potesse settare il DBMS in modo da eseguire una
determinata istruzione seconda una o l'altra modalità (non sò se MS
SQLServer e Oracle arrivino a tanto).
PS: posto anche il workaround che ho escogitato per aggirare il problema:
UPDATE Prova SET Prog=Prog*-1 WHERE Gruppo=16 AND Prog>=1;
UPDATE Prova SET Prog=ABS(Prog)+1 WHERE Gruppo=16 AND ABS(Prog)>=1;

 > ecco che la scelta di MySql appare sensata.
Inoltre che dovrebbe fare? cambiarli tutti e se c'è un problema
ripristinarli?
Ad un click di distanza ho trovato
http://www.mysql.com/doc/en/constraint_primary_key.html
Normally you will get an error when you try to INSERT / UPDATE a row that
causes a primary key, unique key or foreign key violation. If you are using
a transactional storage engine, like InnoDB, MySQL will automatically roll
back the transaction. If you are using a non-transactional storage engine
MySQL will stop at the wrong row and leave the rest of the rows unprocessed.
To make life easier MySQL has added support for the IGNORE directive to most
commands that can cause a key violation (like INSERT IGNORE ...). In this
case MySQL will ignore any key violation and continue with processing the
next row. You can get information of what MySQL did with the mysql_info()
API function and in later MySQL 4.1 version with the SHOW WARNINGS command.
Ludovico Grossi

 API function and in later MySQL 4.1 version with the SHOW WARNINGS
command.
"IGNORE" preferisco ignorarlo!
Non mi piace assolutamente perchč:
 1. non č codice SQL standard
 2. porta a credere che sia andata a buon fine l'operazione anche se non č
cosě; obbliga di conseguenza ad implementare altro codice (in php nel mio
caso) per verifica l'effettivo o meno buon esito
Grazie della segnalazione!
Ciao

 Uhm... Ok, lo verifico e ti faccio sapere!  ;-)
Ecco... ho effettuato il test...
Segnalandomi quel link mi avevi dato una carica morale eccezionale...
Ci ho messo un paio di minuti a smorzarmi, il tempo di:
 - creare la tabella ma di tipo InnoDB
 - riempirla con qualche dato
 - eseguire la query di update
 - e verificare che si comporta esattamente come prima, "Duplicate entry"!!!