2014-06-12 3 views
2

함수의 시퀀스의 현재 값을 읽어야합니다. 그러나, 나는 CURRVAL()를 사용하려고 각 세션에 처음으로, 나는 다음과 같은 얻을 오류 : 당신의 순서를 초기화해야이 오류에 대한 인터넷 검색을하여이 문제를 찾을 수있는 사람들을위한이 세션에서 시퀀스가 ​​초기화되었는지 확인하는 방법은 무엇입니까?

currval of sequence "foo_seq" is not yet defined in this session 

힌트 각 세션은 nextval() or setval()입니다.

나는 lastval() 또는 심지어 setval('your_table_id_seq', (SELECT MAX(id) FROM your_table));과 같은 것을 사용할 수 있습니다. 그러나이 차이는 단순한 currval()보다 느리게 나타나는 경향이 있습니다. 내 목표는 간격과 불일치를 피하는 것입니다. (일부 값은 수동으로 추가됩니다.) 따라서 논리 처리 전에 논리 값 nextval()을 사용하는 것이 이상적이지 않습니다. 어쨌든 세션에 대한 순서를 초기화하는 데이 필요하지만, 나는 이런 일을 수행하는 것을 선호 :

--start of the function here 
IF is_not_initialized THEN 
    SELECT setval('foo_seq', (SELECT MAX(id) FROM bar_table)) INTO _current; 
ELSE 
    SELECT currval('foo_seq') INTO _current; 
END IF; 
--some magic with the _current variable and nextvalue() on the right position 

요점은 내가 같이 "is_not_initialized"하는 방법 아무 생각이 없다는 것입니다을하고 있는지 그것을이다 가능하다. 어떤 기능이나 다른 속임수가 있습니까?

EDIT : 사실 내 계획은 각 고객 그룹이 적절한 순서, 순서 없음, 이상한 "무언가와 같은 무언가"중에서 선택하도록하는 것입니다. 고객이 이러한 이상한 시퀀스를 원한다고해도, 필요한 아날로그 데이터가 있고 역 호환성을 위해 DB에 키를 저장해야하기 때문에 (일반적으로 거의 gapless 시퀀스가 ​​필요함) 일반적으로 필요한 열에 만 사용됩니다.

어쨌든,이 상황이 적절한 솔루션이 아니며 그러한 상황에서 이러한 난제를 해결할 수있는 방법이 없을 수도 있으므로 고객에게 정말로 필요한지 다시 생각해 보겠습니다.

+2

에 예외를 발생시킵니다. 시퀀스 *에는 간격이 생길 수 있으므로 **이를 피할 방법이 없습니다. 갭을 피하기위한 비즈니스 요구 사항이있는 경우 시퀀스를 사용할 수 없습니다. 그러나 일반적으로 시퀀스는 인위적 기본 키를 채우는 데 사용되므로 실제 값은 의미가 없습니다. 따라서 갭은 문제가되지 않습니다. gapless 시퀀스 값에 의존한다면 시퀀스에 대한 이해가 잘못되었습니다. –

+1

또한 * "시퀀스의 현재 값을 읽어야합니다."* - 일반적으로 그러한 것이 없습니다. 'currval()'은 정의에 의해'nextval()'*에서 가장 최근에 얻은 값을 반환합니다 * (setval()은 데이터 정의 문과 비슷합니다. 동의합니다. 일부 함수 이름은 오해의 소지가 있습니다. 이걸로 무엇을 이루려고합니까? – pozs

답변

3

크레이그, a_horse 및 pozs가 제공 한 정보를 제공합니다. 그것을 어떻게 사용할 것인지에 대한 의문과는 달리, 시퀀스가 ​​초기화 되었으면 현재 값을 반환하거나 그렇지 않으면 null을 반환하는 함수가 있습니다.그건 불가능 - 시퀀스 seq이 아직 초기화되지 않은 경우

currval(seq)는 "* 내 목표는 * 간격을 방지하는 것입니다"sqlstate 55000.

create or replace function current_seq_value(seq regclass) 
returns integer language plpgsql 
as $$ 
begin 
    begin 
     return (select currval(seq)); 
    exception 
     when sqlstate '55000' then return null; 
    end; 
end $$; 

select current_seq_value('my_table_id_seq') 
+0

그것은 꽤 산뜻합니다. 좀 더 조정하면 curr_or_next_seq_value 함수를 생성 할 수있는 것처럼 보입니다. curr_or_next_seq_value 함수가 있으면 currval을 반환하고, curr_or_next_seq_value 함수가 없으면 자동으로 nextval을 호출합니다. 그것은 어떤 상황에서는 정말 편리 할 것입니다. –

3

My aim is to avoid gaps and inconsistencies

간격을 피하려면 순서를 사용할 수 없습니다. 일부 값을 수동으로 지정하려면 시퀀스를 합리적으로 사용할 수도 없습니다.

당신이 취하는 접근법은 안전하지 않습니다. 이거 작동 안 할거야. 그것을 잊어 버리면, 당신이 생각하는대로 할 수 없을 것입니다.

며칠 전 누군가를위한 간단한 gapless 시퀀스 생성기의 샘플 구현을 작성했으며 더 완전한 하나의 in this question이 있습니다.

실제 시퀀스와 달리 gapless 시퀀스는 트랜잭션적임을 이해해야합니다. 결과적으로 실행중인 하나의 트랜잭션 만 커밋되지 않은 ID를 가질 수 있습니다. 100 개의 동시 트랜잭션이 ID를 얻으려고하면 그 중 하나만 실제로 ID를 얻습니다. 다른 사람들은 커밋되거나 롤백 될 때까지 기다려야합니다. 따라서 특히 장기 실행 트랜잭션과 함께 사용하는 경우 동시성이 끔찍합니다. 또한 서로 다른 gapless 시퀀스를 사용하고 서로 다른 트랜잭션이 서로 다른 순서로 액세스하는 경우 교착 상태가 발생할 수 있습니다.

정말 필요한지 신중하게 생각하십시오.

읽기 : 당신이 시퀀스를 사용의 원칙을 이해하는 데 도움이 될 수 PostgreSQL gapless sequences

관련 문제