MySQL INSERT SI (personnalisé si les déclarations)
Tout d'abord, voici le résumé succinct de la question:
Est-il possible de faire fonctionner un INSERT
instruction conditionnelle?
Quelque chose de semblable à ceci:
IF(expression) INSERT...
Maintenant, je sais que je peux le faire avec une procédure stockée.
Ma question est: puis-je faire dans ma requête?
Maintenant, pourquoi voudrais-je faire?
Supposons que nous avons les 2 tableaux:
products: id, qty_on_hand
orders: id, product_id, qty
Maintenant, disons une commande de 20 Poupées Vaudou (id de produit 2) vient en.
Nous vérifions d'abord si il y a assez de Quantité en Main:
SELECT IF(
( SELECT SUM(qty) FROM orders WHERE product_id = 2 ) + 20
<=
( SELECT qty_on_hand FROM products WHERE id = 2)
, 'true', 'false');
Puis, si elle est true, nous organisons un INSERT
requête.
So far So good.
Cependant, il y a un problème avec la concurrence d'accès.
Si 2 commandes viennent à la même temps exact, ils pourraient à la fois de lire la quantité-sur-le-main avant de l'un d'entre eux est entré dans l'ordre.
Ils vont alors à la fois le lieu de la commande, dépassant ainsi le qty_on_hand
.
Donc, revenons à la racine de la question:
Est-il possible de faire fonctionner un INSERT
déclaration sous certaines conditions, de sorte que nous pouvons combiner ces deux requêtes en une?
J'ai cherché autour d'un lot, et le seul type de liberté sous condition INSERT
déclaration que j'ai pu trouver était ON DUPLICATE KEY
, qui, évidemment, ne s'applique pas ici.
Vous devez vous connecter pour publier un commentaire.
Si aucune ligne n'est retournée à partir de la sélectionner (parce que votre condition spéciale est faux) pas d'insérer arrive.
À l'aide de votre schéma à partir de la question (en supposant que votre
id
colonne estauto_increment
):Cela permettra de ne pas insérer des lignes si il n'y a pas assez de stock sous la main, sinon il va créer la ligne de commande.
Belle idée btw!
SELECT
consolidés. Un seul suffira. Jetez un oeil à ma réponse. 🙂SELECT
états par rapport à la mienne, qui s'exécute avec une? (Rien contre votre réponse, ou vous, de la Bohême).INSERT
, siaffected rows = 1
, vous aurezUPDATE ... qty_on_hand = qty_on_hand - 20
. C'est la façon dont vous gardez une trace de stock. Toutefois, la façon dont je le fais (voir mes exemples de code ci-dessus), c'est queqty_on_hand
ne change jamais. Il est toujours fixé à la somme de stock dans l'entrepôt, indépendamment de la façon dont beaucoup ont été vendus. Puis, lorsque je veux vérifier si un produit est disponible, je compareSUM(qty) FROM orders
àqty_on_hand FROM products
. Ce n'est possible qu'avec une sous-requête (certes, @Bohème n'a pas vraiment le faire aussi, mais nous sommes sur la même page que la mesure nécessitant une sous-requête).orders
, et la dupliquer dansproducts
. Vous parlez de la surcharge de la DB de la prospective. Ce à propos de la mienne? Allez à votre façon, si une commande est annulée, je dois augmenter leqty_on_hand
. Il existe de nombreux autres scénarios qui pourraient affecter laqty_on_hand
. De nouveau, dupliquer l'information est toujours une mauvaise idée.SUM()
n'est pas si cher que ça (même si il y a 5000 commandes pour ce produit en particulier, nous sommes encore en ajoutant simplement des nombres; ce qui est le plus rapide de la chose pour n'importe quel programme).orders
pour l'id de produit1
avec le montant20
si et seulement si il existe une quantité suffisante pour satisfaire la commande. De toute façon, le faire à votre façon, puisque vous êtes tous en elle.Essayer:
Si un produit avec
id
égal à2
existe et leqty_on_hand
est supérieure ou égale à20
pour ce produit, puis une insertion se fera avec les valeursproduct_id = 2
, etqty = 20
. Sinon, pas d'insérer de se produire.Note: Si votre id de produit sont la note unique, vous voudrez peut-être ajouter un
LIMIT
clause à la fin de laSELECT
déclaration.Pas sûr au sujet de la concurrence, vous aurez besoin de lire sur le verrouillage de mysql, mais cela vous permettra d'être sûr que vous ne prenez 20 points, si 20 éléments sont disponibles:
Vous pouvez ensuite vérifier comment le nombre de lignes affectées. Si aucun n'a été affecté, vous n'avez pas assez de stock. Si 1 ligne a été affectée, que vous avez consommé le stock.
Vous êtes probablement résoudre le problème à l'envers.
Si vous avez peur de lire deux opérations vont se produire en même temps et donc on va travailler avec des données périmées, la solution est de utiliser des verrous ou des transactions.
Ont la requête ce faire: