Question

Je suis nouveau chez PostgreSQL et j’ai déjà mon premier problème ..

J'ai écrit du code pour comprendre le fonctionnement des transactions, en suivant pas à pas le manuel.

Pour faire court, j'ai créé 2 tables, utilisateur et mouvements: la première contient les colonnes nom, email et crédit, la seconde les colonnes de, à, import.

J'essayais donc de cette façon:

BEGIN;
INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
UPDATE users SET credit = credit - 600 WHERE name = 'mary';
UPDATE users SET credit = credit + 600 WHERE name = 'steve';
--here comes the problem!
IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
 ROLLBACK;
END IF
COMMIT;

Je reçois toujours l'erreur:

  

ERREUR: erreur de syntaxe proche de "SI"

.

Où est-ce que je me trompe?

P.S .: Ne vous concentrez pas sur l’exemple de fonctionnalité, c’est un essai pour moi de comprendre les transactions .. et maintenant, la clause IF ...

Était-ce utile?

La solution

Comme Johannes le dit déjà: vous mélangez du SQL normal avec PL / pgSQL, le langage de procédure stockée. Le lien fourni par Johannes devrait vous expliquer le concept de procédures stockées.

Je suppose que vous faites cela comme un script? Exécuter une déclaration après l'autre? Je crains que vous ne puissiez faire que ce que vous voulez faire dans une procédure stockée, ou une fonction, comme vous pourriez l'appeler. En effet, lorsque vous exécutez des instructions de cette manière, chaque instruction est autonome, sans relation ni information concernant les autres instructions.

De plus, vous pouvez consulter le lien suivant pour plus d'informations sur l'utilisation de IF ... THEN ... ELSE ... END IF; conditions à l'intérieur de plpgsql: lien . / p>

EDIT:

Je ne sais pas si ROLLBACK est autorisé à ce stade (car chaque procédure stockée est déjà dans sa propre transaction), mais vous devez être en mesure de le découvrir vous-même à l'aide de la documentation détaillée @ http://www.postgresql.org . Voici un exemple de fonction contenant votre code, illustrant également une autre syntaxe:

CREATE OR REPLACE FUNCTION public.test()
RETURNS integer AS
$
DECLARE
tempvar integer;

BEGIN    
     tempvar := 1;

     INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
     UPDATE users SET credit = credit - 600 WHERE name = 'mary';
     UPDATE users SET credit = credit + 600 WHERE name = 'steve';

     --here comes the problem!
     IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
        ROLLBACK;
     END IF;

     RETURN tempvar;
END
$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;

Cependant, si vous vous dirigez vraiment dans cette direction, je vous recommande d’utiliser un gestionnaire de base de données GUI. C'est plus facile d'apprendre tout cela.

Autres conseils

Vous semblez utiliser du SQL clair, mais l'instruction IF fait partie du PL / pgSQL langage procédural faisant partie de PostgreSQL.

Vous pouvez essayer de modifier la partie IF à partir de:

IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
 ROLLBACK;
END IF

à

SELECT SUM(credit) INTO v_credit FROM users WHERE name = 'mary';
IF (v_credit) < 0 THEN
 ROLLBACK;
END IF

En supposant que v_credit est une variable que vous avez définie précédemment. IMHO, Postgre suppose que la requête SELECT renvoie plus d'un résultat, même si vous êtes certain de son caractère unique. Je pense donc que vous pouvez essayer d’attribuer d’abord la valeur à une variable.

Si vous souhaitez éviter le problème, vous pouvez réécrire votre code comme suit:

BEGIN;

    INSERT INTO movements (from, to, import)    
    SELECT 'mary', 'steve', CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END;

    UPDATE users SET credit = credit - CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END    
    WHERE name = 'mary';

    UPDATE users u SET u.credit = u.credit + CASE v.credit < 600 WHEN TRUE THEN 0 ELSE 600 END    
    FROM users v    
    WHERE u.name = 'steve' and v.name = 'mary'

COMMIT;

Oui, c'est stupide :).

Semblable à SQL et T / SQL de Microsoft, vous devriez pouvoir mélanger du SQL normal avec PL / pgSQL s’ils se trouvent dans le bon ordre. Voici un exemple où la séquence est importante dans une procédure mixte SQL / PL stockée:

Vous ne pouvez pas insérer d'instructions conditionnelles à l'intérieur du curseur. Vous devez placer le curseur à l'intérieur de l'instruction conditionnelle. Si vous effectuez la séquence dans le sens inverse, vous obtiendrez la même erreur que celle que vous aviez vue, "ERREUR: erreur de syntaxe égale ou proche de" SI ":

.
CREATE OR REPLACE FUNCTION getSubsystemFaultListCount(_bunoid integer, _subsystem text, _starttime timestamp without time zone, _stoptime timestamp without time zone)
      RETURNS refcursor AS
    $BODY$
    DECLARE mycurs refcursor;
    BEGIN 
        IF _subsystem = 'ALL' THEN
            OPEN mycurs FOR
            SELECT  count(*), fs_fault.faultcode, fs_fault.downloadtime
            FROM    fs_fault
            WHERE   fs_fault.bunoid = _bunoid
                AND fs_fault.statusid IN(2, 4)
                AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
            GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
            RETURN mycurs;
        ELSE
            OPEN mycurs FOR
            SELECT  count(*), fs_fault.faultcode, fs_fault.downloadtime
            FROM    fs_fault
            WHERE   fs_fault.bunoid = _bunoid
                AND fs_fault.subsystemid 
                    IN(SELECT id FROM fs_subsystem WHERE type = _subsystem)
                AND fs_fault.statusid IN(2, 4)
                AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
            GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
            RETURN mycurs;
        END IF;

    END;
    $BODY$

Je suis un débutant dans PostGresSQL; cette fonction est juste un exemple.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top