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'élément est la clé primaire ici. Comment obtenir les résultats suivants chaque fois que je reçois un article A en quantité X.
Si l'article n'existe pas, j'insère un nouveau stocké pour l'article A et mets les articles en stock à X. 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 mon tableau actuel. 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 existe-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 qui provoque le déclenchement de ON DUPLICATE KEY. Donc, dans votre exemple, vous pouvez utiliser ce qui suit:
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 vraiment simples, si vous vous trouvez trop compliqué avec 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 ajouter des données utilisateur sur sept jours
Il devrait avoir une valeur unique pour userid et day comme
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:
<?php
//If your data is
$data= array(
'sat'=>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 effectuer la programmation ascendante par programme:
Tout d’abord, créez votre table et spécifiez les colonnes sur lesquelles vous souhaitez un index unique:
CREATE TABLE IF NOT EXISTS Cell (
cellId BIGINT UNSIGNED,
attributeId BIGINT UNSIGNED,
entityRowId BIGINT UNSIGNED,
value DECIMAL(25,5),
UNIQUE KEY `id_ce` (`cellId`,`entityRowId`)
)
Puis insérez-y quelques valeurs:
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 );
Duplicata '1-199' pour la clé 'id_ce'
C'est pourquoi nous utilisons la commande upsert:
INSERT INTO Cell ( cellId, attributeId, 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
déjà présente en tant que valeur et effectue un value = value + 300.0
.
Ainsi, 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
.
Si vous avez une valeur pour Column PK ou Index unique sur une colonne qui satisfait à l'unicité, vous pouvez utiliser INSERT IGNORE
, INSERT INTO ... ON DUPLICATE
ou REPLACE
Exemple avec INSERT IGNORE
INSERT IGNORE INTO Table1
(ID, serverID, channelID, channelROLE)
VALUES
(....);
Exemple avec INSERT INTO .. ON DUPLICATE KEY UPDATE
SET @id = 1,
@serverId = 123545,
@channelId = 512580,
@channelRole = 'john';
INSERT INTO Table1
(ID, serverID, channelID, channelROLE)
VALUES
(@id, @serverId, @channelId, @channelRole)
ON DUPLICATE KEY UPDATE
serverId = @serverId,
channelId = @channelId,
channelRole = @channelRole;
Exemple avec Replace
REPLACE INTO table1
(ID, serverID, channelID, channelROLE)
VALUES
(...);
Ceci est la syntaxe pour un upsert
INSERT INTO `{TABLE}` (`{PKCOLUMN}`, `{COLUMN}`) VALUES (:value)
ON DUPLICATE KEY UPDATE `{COLUMN}` = :value_dup';