2009-04-29 6 views
11

私は、PostgreSQLとの新たなんだ、と私はすでに私の最初の問題を抱えている。..PostgreSQLの構文エラー

「IF」私はトランザクションがステップによる手動ステップ以下、どのように機能するかを理解するためにいくつかのコードを書きました。

簡潔にするために、私は2つのテーブル、ユーザーとムーブメントを作成しました。最初のものには名前、電子メール、クレジットの列があり、2番目の列はfrom、to、importです。

ERROR: syntax error at or near "IF"

私が間違っています:私は常にエラーを取得

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; 

だから、私はこの方法を試したのですか?

PS:例の機能に焦点を当ててはいけない、それは...私が取引を理解するためだけの裁判だと今、IF句...

+0

ご要望により、サンプルコードを追加しました。これはあなたを助けるべきです。 :-) – pyrocumulus

+0

チェック制約を使用すると、この構造は必要ありません。 –

+0

@frank:私はホットトランザクションの仕事を学ぼうとしていました、それは単なる例です;) – Strae

答えて

6

Johannesはすでに言っているとおり、PL/pgSQL(ストアドプロシージャ言語)と通常のSQLを混在させています。 Johannesが提供するリンクは、ストアドプロシージャの概念について説明します。

私はこれをスクリプトとしてやっていますか? 1つのステートメントを次々に実行していますか?私は、あなたが呼び出すかもしれないように、あなたがストアドプロシージャまたは関数の中で何をしたいかだけを行うことができるのではないかと心配しています。これは、このように文を実行しているときには、すべての文が関係なく、または他の文に関する情報に基づいているためです。

さらに、IF ... THEN ... ELSE ... END IFを使用する方法の詳細については、次のリンクを参照してください。 plpgsql内の条件:link


EDIT:

(各ストアドプロシージャは、独自のトランザクション内にすでにあるので)ROLLBACKは、その時点で許可されている場合、私は知らないが、あなたがそれを把握することができなければなりません詳細な文書@http://www.postgresql.orgを使用してください。ここにもいくつかの他の構文を実証し、その中にあなたのコードとサンプル関数です:

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; 

をしかし、あなたは本当にこの道を行っている場合、私はGUI DBマネージャを使用することをお勧めします。これをすべて学習するのは簡単です。

+0

オハイオ州、私は理解して、私はジョハンズのリンクを読んでいる(私は答えを読んで初めて私は見たことがない)。 PL/pgSQLで書いたSQLをどのように見えるかの例を投稿できますか? ありがとう.. – Strae

+0

私はPostgresのドキュメントを非常によくよく書いています。ちょっと「大」ですが、大丈夫です。3巻のペーパーバージョンを購入しており、それらをすべて読むことを約束します。 私はちょっと理解できないのですが、mysqlで普通のSQLでif文を使うことができないのです。 – Strae

+0

ホー、最後のこと:私はグーグルでも、マニュアルのオペレータセクションでも私は ':='の意味を見つけることはできません。それは何のために使われていますか? – Strae

2

あなたは、プレーンSQLが、IFステートメントを使用するように見えますPostgreSQLの一部であるPL/pgSQL手続き型言語の一部です。

+1

はそれをよりよく説明できますか? – Strae

1

あなたがようにコードを書き換えることができれば避けたい場合は:はい、これは愚かな:)です

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; 

+0

私はあなたの例を理解していると思う;) – Strae

+0

これはひどい例です、本当に、それは単なる思考実験でした:)それをテストするために –

1

あなたはから、IFの一部を変更しようとすることができます:v_creditは、以前に定義された変数であると仮定すると、

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 

に。IMHO、PostgreSQLは、SELECTクエリーが複数の結果を返すものと仮定しています。だから私はあなたが事前に変数に値を割り当てることを試みることができると思います。

+0

、私はIF 2 = 2 THEN [...]を試しましたが、まだエラーを投げます。 – Strae

0

マイクロソフトのSQLとT/SQLに似ていますが、正しい順序であれば、通常のSQLとPL/pgSQLを混在させることができます。

条件文をカーソル内にラップすることはできません。条件文の中にカーソルを置く必要があります。あなたはシーケンスに他の方法で回避を行う場合は、あなたが見たいのと同じエラーが表示されますが、「ERROR:構文エラーまたはその付近 『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$ 

私はPostgresSQLの中に初心者です。この関数は単なる例にすぎません。

関連する問題