Exemple stupide mais simple: Supposons que j’ai un tableau ‘Item’ où je garde les totaux des articles reçus.
Item_Name Items_In_Stock
Le nom de l’article est la clé primaire ici. Comment est-ce que j’obtiens le suivant quand je reçois l’article A en quantité X.
Si l’élément n’existe pas, j’insère un nouvel enregistrement pour l’élément A et place les articles en stock à X et s’il existe un enregistrement où les articles en stock étaient Y, la nouvelle valeur des articles en stock est (X + Y)
INSERT INTO `item` (`item_name`, items_in_stock) VALUES( 'A', 27) ON DUPLICATE KEY UPDATE `new_items_count` = 27 + (SELECT items_in_stock where item_name = 'A' )
Mon problème est que j’ai plusieurs colonnes dans ma table réelle. Est-ce une bonne idée d’écrire plusieurs instructions select dans la partie mise à jour?
Bien sûr, je peux le faire en code, mais y a-t-il un meilleur moyen?
Comme mentionné dans mon commentaire, vous n’avez pas besoin de faire la sous-sélection pour faire référence à la ligne à l’origine de ON DUPLICATE KEY. Ainsi, dans votre exemple, vous pouvez utiliser les éléments suivants:
INSERT INTO `item` (`item_name`, items_in_stock) VALUES( 'A', 27) ON DUPLICATE KEY UPDATE `new_items_count` = `new_items_count` + 27
Rappelez-vous que la plupart des choses sont très simples, si vous vous surprenez à compliquer quelque chose qui devrait être simple, alors vous le faites probablement de la mauvaise façon 🙂
Vous pouvez avoir une idée de cet exemple:
Supposons que vous souhaitiez append des données sept jours par utilisateur
Il devrait avoir une valeur unique pour userid et day like
UNIQUE KEY `seven_day` (`userid`,`day`)
Voici la table
CREATE TABLE `table_name` ( `userid` char(4) NOT NULL, `day` char(3) NOT NULL, `open` char(5) NOT NULL, `close` char(5) NOT NULL, UNIQUE KEY `seven_day` (`userid`,`day`) );
Et votre requête sera
INSERT INTO table_name (userid,day,open,close) VALUES ('val1', 'val2','val3','val4') ON DUPLICATE KEY UPDATE open='val3', close='val4';
Exemple:
array("userid"=>"1001", "open"=>"01.01", "close"=>"11.01"), 'sun'=>array("userid"=>"1001", "open"=>"02.01", "close"=>"22.01"), 'sat'=>array("userid"=>"1001", "open"=>"03.01", "close"=>"33.01"), 'mon'=>array("userid"=>"1002", "open"=>"08.01", "close"=>"08.01"), 'mon'=>array("userid"=>"1002", "open"=>"07.01", "close"=>"07.01") ); //If you query this in a loop //$conn = mysql_connect("localhost","root",""); //mysql_select_db("test", $conn); foreach($data as $day=>$info) { $sql = "INSERT INTO table_name (userid,day,open,close) VALUES ('$info[userid]', '$day','$info[open]','$info[close]') ON DUPLICATE KEY UPDATE open='$info[open]', close='$info[close]'"; mysql_query($sql); } ?>
Vos données seront dans la table:
+--------+-----+-------+-------+ | userid | day | open | close | +--------+-----+-------+-------+ | 1001 | sat | 03.01 | 33.01 | | 1001 | sun | 02.01 | 22.01 | | 1002 | mon | 07.01 | 07.01 | +--------+-----+-------+-------+
Bien que la réponse de Michael soit la bonne, vous devez en savoir un peu plus pour faire le programme par programme:
Tout d’abord, créez votre table et spécifiez les colonnes sur lesquelles vous voulez un index unique:
CREATE TABLE IF NOT EXISTS Cell ( cellId BIGINT UNSIGNED, atsortingbuteId BIGINT UNSIGNED, entityRowId BIGINT UNSIGNED, value DECIMAL(25,5), UNIQUE KEY `id_ce` (`cellId`,`entityRowId`) )
Puis insérez des valeurs dans celui-ci:
INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );
Essayez de refaire la même chose et vous obtiendrez une erreur de clé en double, car cellId
et entityRowId
sont identiques:
INSERT INTO Cell VALUES( 1, 6, 199, 1.0 );
Entrée en double ‘1-199’ pour la clé ‘id_ce’
C’est pourquoi nous utilisons la commande upsert:
INSERT INTO Cell ( cellId, atsortingbuteId, entityRowId, value, s, l, p, t ) VALUES( 1, 6, 199, 300.0 ) ON DUPLICATE KEY UPDATE `value` = `value` + VALUES(`value`)
Cette commande prend la valeur 1.0
qui existe déjà comme valeur et fait une value = value + 300.0
.
Donc, même après l’exécution de la commande ci-dessus, il n’y aura qu’une seule ligne dans la table et la valeur sera 302.0
.
C’est la syntaxe pour un upert
INSERT INTO `{TABLE}` (`{PKCOLUMN}`, `{COLUMN}`) VALUES (:value) ON DUPLICATE KEY UPDATE `{COLUMN}` = :value_dup';