문제

저는 PostgreSQL을 처음 사용하는데 이미 첫 번째 문제가 있습니다.

수동으로 단계별로 진행하면서 트랜잭션이 어떻게 작동하는지 이해하기 위해 몇 가지 코드를 작성했습니다.

간단히 말해서 사용자와 이동이라는 2개의 테이블을 만들었습니다.첫 번째 열에는 이름, 이메일 및 신용 열이 있고 두 번째 열에는 from, to, import 열이 있습니다.

그래서 저는 이런 식으로 노력하고 있었습니다.

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;

항상 오류가 발생합니다.

오류:"IF" 또는 그 근처에 구문 오류가 있습니다.

내가 어디에서 착각하고 있습니까?

추신.:예제 기능에 집중하지 마세요. 트랜잭션을 이해하기 위한 시험일 뿐입니다.이제 IF 절은...

도움이 되었습니까?

해결책

Johannes가 이미 말했듯이 : 정기적 인 SQL을 저장된 절차 언어 인 PL/PGSQL과 혼합하고 있습니다. Johannes가 제공하는 링크는 저장 절차의 개념을 설명해야합니다.

나는 당신이 이것을 대본으로하고 있습니까? 하나의 진술을 상대적으로 실행합니까? 저장된 절차 내에서하고 싶은 일만 할 수 있거나 기능을 할 수 있습니다. 이런 식으로 진술을 실행할 때 모든 진술은 다른 진술에 관한 관계 나 정보가 없어서 자체적으로 나타나기 때문입니다.

또한 사용 방법에 대한 자세한 내용은 ... 다음 ... ELSE ... END IF; PLPGSQL 내부 조건부 : 링크.


편집하다:

그 시점에서 롤백이 허용되는지 모르겠지만 (각 저장 절차가 이미 자체 거래에 있기 때문에) 광범위한 문서 @를 사용하여 직접 알아낼 수 있어야합니다. 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 관리자를 사용하는 것이 좋습니다. 이 모든 것을 배우기가 더 쉽습니다.

다른 팁

당신은 평원을 사용하는 것 같습니다 SQL 하지만 IF 진술은 PL/pgSQL PostgreSQL의 일부인 절차 언어.

if part를 수정하려고 시도 할 수 있습니다.

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이 이전에 정의한 변수라고 가정합니다. IMHO, PostGRE는 SELECT Query가 독특하다는 것을 확실히 확신하더라도 하나 이상의 결과를 반환한다고 가정합니다. 그래서 나는 당신이 값을 먼저 변수에 미리 할당하려고 시도 할 수 있다고 생각합니다.

코드를 다시 작성할 수있는 경우를 피하려면 :

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;

예, 이것은 바보입니다 :).

Microsoft의 SQL 및 T/SQL과 유사하게 올바른 순서로 되어 있는 경우 일반 SQL과 PL/pgSQL을 혼합할 수 있어야 합니다.다음은 혼합된 SQL/PL 저장 프로세스에서 시퀀스가 ​​중요한 예입니다.

커서 안에 조건문을 포함할 수 없습니다. 커서를 조건문 안에 넣어야 합니다.반대 방향으로 시퀀스를 수행하면 본 것과 동일한 오류 '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의 초보자입니다.이 기능은 단지 예일 뿐입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top