2012-01-27 2 views
0

NULL을 반환한다. 기본적으로 상태 열은 각 order_id에 대해 1부터 시작하는 자동 증가 값입니다. 따라서 order_id 2에 이미 두 개의 행이있는 경우 시퀀스는 1과 2가되고 새 행의 경우 시퀀스는 3이어야합니다. 삽입 전에이 동작을 구현하기 위해 트리거를 사용하려고하지만 시도 할 때 새 order_id에 대한 첫 번째 행을 삽입하려면 (즉, 트리거는 삽입하기 전에 행을 변경하지 않아도됩니다.) PG에 오류가 발생합니다. 시퀀스에 NULL을 삽입 할 수 없다고 말합니다. 내 방아쇠 함수가 NULL을 반환하는 방법을 볼 수 없지만 내 pl/sql 정말 좋지 않아 그래서 뭔가 간단한 ... Trigger function below, thanks. max(sequence)POSTGRESQL PL/pgSQL의 트리거 기능은 I이 같은 페이지 테이블이 삽입

DECLARE 
    seq_no INTEGER; 

BEGIN 
    SELECT INTO seq_no MAX(sequence) FROM rar.order_status_history WHERE order_id = NEW.order_id; 
    IF FOUND THEN 
     NEW.sequence := seq_no + 1; 
    END IF; 

    RETURN NEW; 
END; 
+1

새 ID를 얻기 위해'SELECT max()'를 사용하는 것은 매우 나쁜 생각입니다. 트랜잭션 안전이 아니므로 솔루션은 다중 사용자 환경에서 잘못된 일련 번호를 생성합니다. –

+0

@a_horse_with_no_name, 좋은 지적은 이것을 달성하는 더 좋은 방법입니까? – Alpaus

+0

해당 트랜잭션을 안전하게하려면 테이블을 독점적으로 잠 가야합니다. –

답변

2

해당 order_id에 대해 order_status_history에 아무 것도없는 경우 MAX(sequence)은 null입니다. 이 1.

을 기본값으로 만들 COALESCE(MAX(sequence),0)를 사용하여 간단히 쓸 수있다 :이 여러 작업을 할 수 있도록뿐만 아니라,이 작업을 수행하기 전에

NEW.sequence := (SELECT COALESCE(MAX(sequence),0) FROM /* etc.. */) + 1; 

당신은 정말 독점 모드에서 주문 행을 고정한다 동일한 주문에 대한 기록을 동시에 기록에 삽입합니다. 즉 :

SELECT 1 FROM orders WHERE orders.order_id = NEW.order_id FOR UPDATE; 
+0

감사합니다. 잠금 기능을 해제해야합니까, 아니면 일단 트리거 기능이 끝나면 암시 적입니까? 이러한 기능을 작성하는 데있어 더 좋은 웹 리소스를 얻을 수있는 좋은 웹 리소스가 있습니까? 나는 찾기 힘든 포괄적 인 튜토리얼을 찾기가 쉽다. – Alpaus

+0

잠금은 트랜잭션이 끝날 때 자동으로 해제됩니다. 다른 거래가 아직 잠금 장치에 의해 보호 된 변경 사항을 볼 수 없기 때문에 더 빨리 해제하는 것은 의미가 없습니다. – araqnid

1

항상 FOUND하지만, 데이터가없는 경우는 NULL 수 있습니다. 이 경우 귀하의 NEW.sequence := seq_no + 1은 여전히 ​​NULL이됩니다. IF seq_no IS NOT NULL은 더 적절한 조건처럼 들립니다.