Étant donné le tableau suivant:
id | value
--------------
1 6
2 70
Est-il possible d'ajouter une colonne automatiquement calculée en fonction d'une autre colonne de la même table? Comme une vue, mais une partie de la même table. Par exemple, calculated
serait la moitié de value
. Calculated
devrait être automatiquement mis à jour lorsque value
change, comme le serait une vue.
Le résultat serait:
id | value | calculated
-----------------------
1 6 3
2 70 35
La colonne générée est l’une des bonnes approches pour la version MySql qui est 5.7.6 et plus.
Il existe deux types de colonnes générées:
Les deux types peuvent avoir des restrictions NOT NULL, mais seule une colonne générée stockée peut faire partie d'un index.
Pour le cas actuel, nous allons utiliser la colonne générée stockée. Pour mettre en œuvre, j’ai considéré que les deux valeurs requises pour le calcul sont présentes dans le tableau
CREATE TABLE order_details (price DOUBLE, quantity INT, amount DOUBLE AS (price * quantity));
INSERT INTO order_details (price, quantity) VALUES(100,1),(300,4),(60,8);
montant apparaîtra automatiquement dans le tableau et vous pourrez y accéder directement. Notez également que chaque fois que vous mettrez à jour une colonne, le montant sera également mis à jour.
Si c'est une sélection, vous pouvez le faire comme:
SELECT id, value, (value/2) AS calculated FROM mytable
Sinon, vous pouvez également modifier la table pour ajouter la colonne manquante, puis effectuer une requête UPDATE pour calculer les valeurs de la nouvelle colonne comme suit:
UPDATE mytable SET calculated = value/2;
Si cela doit être automatique et que votre version de MySQL le permet, vous pouvez essayer avec triggers
MySQL 5.7 supporte les colonnes calculées. Ils l'appellent "colonnes générées" et la syntaxe est un peu étrange, mais elle supporte les mêmes options que celles que je vois dans d'autres bases de données.
https://dev.mysql.com/doc/refman/5.7/fr/create-table.html#create-table-generated-columns
La réponse de @ krtek va dans la bonne direction, mais présente quelques problèmes.
La mauvaise nouvelle est que l’utilisation de UPDATE dans un déclencheur de la même table ne fonctionnera pas. La bonne nouvelle est que ce n'est pas nécessaire. vous pouvez opérer sur un NOUVEAU objet avant même que la table ne soit touchée.
La gâchette devient:
CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table
FOR EACH ROW BEGIN
SET NEW.calculated = NEW.value/2;
END;
Notez également que BEGIN ... END; La syntaxe doit être analysée avec un délimiteur différent. Le Shebang entier devient:
DELIMITER |
CREATE TRIGGER halfcolumn_insert BEFORE INSERT ON my_table
FOR EACH ROW BEGIN
SET NEW.calculated = NEW.value/2;
END;
|
CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table
FOR EACH ROW BEGIN
SET NEW.calculated = NEW.value/2;
END;
|
DELIMITER ;
Si vous souhaitez ajouter une colonne à votre table qui est automatiquement mise à jour à la moitié d'une autre colonne, vous pouvez le faire avec un déclencheur.
Mais je pense que la réponse déjà proposée est un meilleur moyen de le faire.
Déclencheur à code sec:
CREATE TRIGGER halfcolumn_insert AFTER INSERT ON table
FOR EACH ROW BEGIN
UPDATE table SET calculated = value / 2 WHERE id = NEW.id;
END;
CREATE TRIGGER halfcolumn_update AFTER UPDATE ON table
FOR EACH ROW BEGIN
UPDATE table SET calculated = value / 2 WHERE id = NEW.id;
END;
Je ne pense pas que vous puissiez déclencher un seul déclencheur, car les événements auxquels nous devons répondre sont différents.
J'espère que cela aide toujours quelqu'un comme beaucoup de gens pourraient arriver à cet article. Si vous avez besoin d'une colonne calculée, pourquoi ne pas simplement exposer vos colonnes souhaitées dans une vue? Ne vous contentez pas de sauvegarder des données ou de surcharger les performances avec des déclencheurs… exposez simplement les données dont vous avez besoin déjà formatées/calculées dans une vue.
J'espère que cela t'aides...
Vous pouvez utiliser les colonnes générées à partir de MYSQL 5.7.
Exemple d'utilisation:
ALTER TABLE tbl_test
ADD COLUMN calc_val INT
GENERATED ALWAYS AS (((`column1` - 1) * 16) + `column2`) STORED;
VIRTUEL/ENREGISTRÉ