2014-09-03 2 views
0

다음은 필드 id, id_user, order_id가있는 테이블입니다. 마지막 사용자 수를 찾기 위해 레코드를 생성하고 다음을 순서대로 삽입 할 때 필요합니다. 사용자에게 다음 주문 번호를 사용하는 저장 프로 시저를 작성했지만 고유 주문 번호도 제공하지 않습니다.0 번 순서로 고유 번호 필드를 지정하는 방법

CREATE OR REPLACE FUNCTION get_next_order() 
RETURNS TRIGGER 
LANGUAGE plpgsql 
AS $function$ 
DECLARE 
    next_order_num bigint; 
BEGIN 
    select order_id + 1 INTO next_order_num 
    from payment_out 
    where payment_out.id_usr = NEW.id_usr 
    and payment_out.order_id is not null 
order by payment_out.order_id desc 
    limit 1; 

-- if payments does't exist, return 1 
    NEW.order_id = coalesce(next_order_num, 1); 
    return NEW; 
END; 
$function$ 

CREATE TRIGGER get_next_order 
BEFORE INSERT 
    ON payment_out 
FOR EACH ROW EXECUTE 
PROCEDURE get_next_order() 

중복 주문 번호는 어떻게 피할 수 있습니까?

+0

http://www.postgresql.org/docs/current/static/sql-createsequence.html에 대한 사용자 정의 '시퀀스'를 만들 수 있습니다. 또는 (더 간단하게) 해당 필드를 '직렬'로 정의 할 수 있습니다. ('create table'에서만 작동하고'alter table'에서는 작동하지 않습니다.) – pozs

+0

나는 composite "sequence"를 한번도 해 보지 않았습니다. 예를 들어 주시면 감사하겠습니다. – gregman

+0

* 복합 *되지 않습니다. 모든 테이블은 모든 수의 시퀀스를 소유 할 수 있습니다. 실제로는 해당 시퀀스를 소유 할 필요가 없습니다. 즉, 해당 열의 '기본'표현으로 충분할 수 있습니다. 당신이 알고 있어야하는 유일한 점은, 이러한 시퀀스는 * hole *을 가질 수 있지만, 그 열을 순서 지정에만 사용한다면 그것은 중요하지 않을 것입니다. – pozs

답변

0

동일한 사용자에 대한 주문을 삽입하는 여러 개의 동시 트랜잭션이있는 경우이 기능을 사용하려면 특정 레코드를 잠 그어 연속적으로 실행하도록 잠금을 설정해야합니다. 첫 번째 선택하기 전에, 당신은 수도

예를 들어

:

당신이 주문을 소유하고 "사용자"레코드 부모를 잠글
PERFORM 1 FROM "users" where id_user = NEW.id_user FOR UPDATE; 

.

그렇지 않으면 여러 동시 트랜잭션이 동시에 프로 시저를 실행할 수 있지만 서로의 삽입 된 값을 볼 수 없어 동일한 숫자를 선택합니다.

그러나 외래 키 제약 조건으로 인해 SHARE 항목이 users 항목에 이미 적용될 수 있습니다. 귀하의 방아쇠는 그것을 UPDATE 자물쇠로 업그레이 드하려고 시도하지만, 여러 거래가 이미 SHARE 자물쇠를 보유하고있을 수 있으므로 차단됩니다. PostgreSQL이 모두 교착 상태가되어 교착 상태 중단 오류가 발생할 때까지 서로 대기하는 트랜잭션을 수행합니다. 이를 피하는 유일한 방법은 응용 프로그램의 경우에서 SELECT 1 FROM users WHERE id_user = blahblah FOR UPDATE까지이며 전에 주문을 만듭니다.

변형은 next_order_id 필드를 users에 유지하고 UPDATE users SET next_order_id = next_order_id + 1 RETURNING next_order_id을 수행하고 그 결과를 사용하여 주문 ID를 설정하는 것입니다. 동일한 잠금 업그레이드 문제가 적용됩니다.