Postgresql mise à Jour à l'intérieur De la Boucle
Je suis assez nouveau à postgresql, et je vais avoir des problèmes de mise à jour d'une colonne de valeurs null dans une table à l'aide d'une boucle for. La table, je suis en train de travailler sur est énorme donc, par souci de concision, je vais vous donner un petit exemple qui devrait obtenir le point à travers. Prendre le tableau suivant
+----+----------+----------+
| id | A | B | C |
+----+----------+----------+
| a | 1 | 0 | NULL |
| b | 1 | 1 | NULL |
| c | 2 | 4 | NULL |
| a | 3 | 2 | NULL |
| c | 2 | 3 | NULL |
| d | 4 | 2 | NULL |
+----+----------+----------+
Je veux écrire une boucle for qui parcourt toutes les lignes et fait de l'opération
sur les valeurs dans les colonnes a et b, puis insère une nouvelle valeur dans c.
Par exemple, where id = a , update table set C = A*B, ou where id = d set C = A + B etc. Ce serait alors donnez-moi une table comme
+----+----------+----------+
| id | A | B | C |
+----+----------+----------+
| a | 1 | 0 | 0 |
| b | 1 | 1 | NULL |
| c | 2 | 4 | NULL |
| a | 3 | 2 | 6 |
| c | 2 | 3 | NULL |
| d | 4 | 2 | 6 |
+----+----------+----------+
Si, finalement, j'aimerais faire une boucle par toutes les lignes de la table et de mettre à jour la colonne C, selon la valeur de la "id" de la colonne. La fonction que j'ai écrite (ce qui n'est pas de donner toutes les erreurs, mais aussi n'est-ce pas la mise à jour de rien) ressemble à ceci...
-- DROP FUNCTION some_function();
CREATE OR REPLACE FUNCTION some_function()
RETURNS void AS
$BODY$
DECLARE
--r integer; not too sure if this needs to be declared or not
result int;
BEGIN
FOR r IN select * from 'table_name'
LOOP
select(
case
when id = 'a' THEN B*C
when id = 'd' THEN B+C
end)
into result;
update table set C = result
WHERE id = '';
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql
Je suis sûr qu'il ya quelque chose de stupide, je suis absent, probablement autour de ce que je suis, le retour... nulle dans ce cas. Mais comme je veux seulement mettre à jour les lignes j'ai besoin de retourner quoi que ce soit? Il y a sans doute des moyens plus faciles de faire ce que l'utilisation d'une boucle, mais j'aimerais le faire fonctionner à l'aide de cette méthode.
Si quelqu'un pouvait me diriger dans la bonne direction ou un point à quelque chose de flagrant que je fais mal, j'avais beaucoup apprécier.
Merci à l'avance.
OriginalL'auteur tasslebear | 2014-08-26
Vous devez vous connecter pour publier un commentaire.
Pas besoin d'une boucle ou d'une fonction, ce qui peut être fait avec un seul
update
déclaration:SQLFiddle: http://sqlfiddle.com/#!15/b65cb/2
La raison de votre fonction n'est pas rien faire, est-ce:
Vous n'avez pas une ligne avec une chaîne vide dans la colonne
id
. Votre fonction semble aussi utiliser la formule incorrecte:when id = 'a' THEN B*C
je suppose que ça doit être:then a*b
. CommeC
estNULL
d'abord,b*c
permettra également d'obtenir la valeur null. Donc, même si votre mise à jour dans la boucle serait de trouver une ligne, il serait de la mettre à jour pourNULL
.Vous sont également récupérer les valeurs de façon incorrecte à l'aide du curseur.
Si vous avez vraiment, vraiment envie de le faire de façon inefficace dans une boucle, la fonction devrait ressembler à quelque chose comme ceci (pas testé!):
Mais encore une fois: si votre table est "énorme" comme vous le dites, la boucle est une très mauvaise solution. Bases de données relationnelles sont constituées pour faire face à des "ensembles" de données. Ligne par ligne de traitement est un anti-modèle qui aura presque toujours de mauvaise performance.
Ou de le mettre dans l'autre sens: faire des opérations à base d'ensemble (comme mon unique
update
exemple) est toujours le meilleur choix.Suis allé pour la couverture mise à jour pour votre première réponse. J'apprécie le temps que vous avez passé en passant par la boucle, mais votre droit, il n'aurait pas été la solution la plus efficace. Merci encore pour la rapidité de votre réponse.
OriginalL'auteur a_horse_with_no_name