Frage

Ich bin neu mit PostgreSQL, und ich habe schon mein erstes Problem ..

Ich schrieb einig Code zu verstehen, wie Transaktionen arbeiten, nach dem manuellen Schritt für Schritt.

Um es kurz zu machen, ich habe 2 Tabellen, Benutzer und Bewegungen erstellt: in dem ersten dort die Namen sind, E-Mail und Kredit Spalten, in den zweiten die Spalten aus, zu, Import

.

Also, ich habe versucht, auf diese Weise:

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;

ich den Fehler immer erhalten:

  

ERROR: Syntaxfehler bei oder in der Nähe von "IF"

Wo bin ich falsch?

P. S .: Sie nicht auf das Beispiel Funktionalität konzentrieren, es ist nur eine Prüfung für mich die Transaktionen zu verstehen .. und jetzt, die IF-Klausel ...

War es hilfreich?

Lösung

Wie Johannes schon sagt: Sie mischen regelmäßig SQL mit PL / pgSQL, die gespeicherte Prozedur Sprache. Der Link, der Johannes liefert sollte das Konzept der gespeicherten Prozeduren erklären.

Ich nehme an, Sie dies als ein Skript tun? Das Ausführen einer Anweisung nach dem anderen? Ich fürchte, Sie können nur das tun, was Sie in einer gespeicherten Prozedur tun wollen, oder Funktion, wie Sie es nennen könnte. Dies liegt daran, wenn Sie Aussagen in dieser Art und Weise ausgeführt werden, jede Aussage steht auf eigenem ohne Bezug oder Informationen in Bezug auf den anderen Aussagen.

Darüber hinaus können Sie unter folgendem Link zu sehen, um weitere Informationen darüber, wie IF verwenden ... THEN ... ELSE ... END IF; conditionals innen plpgsql. Link


EDIT:

Ich weiß nicht, ob ROLLBACK an diesem Punkt erlaubt ist (weil jede gespeicherte Prozedur bereits in einer eigenen Transaktion ist), aber Sie müssen das für sich selbst Abbildung der Lage sein, um die umfangreiche Dokumentation @ mit http://www.postgresql.org . Hier ist eine Beispielfunktion mit Ihrem Code in ihm, auch eine andere Syntax demonstriert:

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;

Wenn Sie jedoch wirklich diesen Weg gehen, empfehle ich einen GUI-DB-Manager. Es ist einfacher, für all dies zu lernen.

Andere Tipps

Sie scheinen schlicht SQL zu verwenden, aber die IF Anweisung ist Teil der PL/pgSQL prozedurale Sprache, die ein Teil von PostgreSQL ist.

Sie könnten versuchen, den IF-Teil zu ändern, ab:

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

v_credit Unter der Annahme ist eine Variable, die Sie vorher definiert sind. IMHO nimmt Postgre SELECT-Abfrage mehr als ein Ergebnis zurückgibt, obwohl Sie sehr sicher sind, dass es einzigartig ist. Also ich denke, Sie könnten versuchen, den Wert einer Variablen zuerst vorher zuzuweisen.

Wenn Sie das vermeiden, wenn Sie Ihren Code so umschreiben könnte:

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;

Ja, das ist dumm :).

Ähnlich wie Microsoft SQL und T / SQL, sollten Sie regelmäßig SQL mit PL / pgSQL mischen können, wenn sie in der richtigen Reihenfolge sind. Hier ist ein Beispiel, wo die Sequenz zählt, in einer gemischten SQL / PL gespeicherte Prozedur:

Sie können nicht wickeln bedingte Anweisungen innerhalb der Cursor - Sie den Cursor in die bedingte Anweisung setzen müssen. Wenn Sie die Reihenfolge umgekehrt tun, werden Sie die gleichen Fehler wie Sie gesehen haben, ‚Fehler: Syntaxfehler bei oder in der Nähe von‚IF‘‘:

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$

Ich bin ein Anfänger in PostgresSQL; Diese Funktion ist nur ein Beispiel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top