이것저것 정리하는 블로그

Open source RDBMS인 PostgreSQL은 현재 9.1.3버전까지 나온 잘 만들어진 DBMS이지만 아주 큰 약점들이 있다. 오늘은 그중 하나인 계층형 쿼리 기능에 대한 해법을 말해보고자한다.
계층형 쿼리, Hierachical Query는 보통 조직도나 다단계 분류표 등의 구조를 나타내는데 쓰는 구문으로 Oracle RDBMS에서 "start with ~ connect by~"의 형태로 쓰며, 보통 "connect by"로 불리운다. 그런데 PostgreSQL에서는 계층형 쿼리를 쓰려면 추가 모듈을 설치해야 하는데, 이 모듈을 설치하면 쓸 수 있는 connectby라는 함수는 속도가 아주 느리다. 그래서 "connect by"를 따로 구현해 보았다.

입력받은 테이블과 컬럼 이름으로 "with recursive" 구문을 문자열로 만들어서 PL/pgSQL의 dynamic query를 이용해서 실행하고, 결과를 result set 형식으로 반환하는 방식이다.


create or replace udf_connect_by (tab_name varchar, key_name varchar, parent_key_name varchar, start_with varchar)
return SETOF record
as $$
declare
v_rowcnt integer;
v_query varchar;
begin
select count(*) into v_rowcnt
from pg_tables
where tablename = tab_name;

if v_rowcnt = 0 then
raise exception 'Invalid table name';
end if;

v_query := 'with recursive T1(select *, 1 as r_level, array[' || key_name || '::varchar] as r_path, false r_flag
from ' || tab_name || '
where ' || start_with || '
union all
select B.*, T1.r_level + 1 as r_level, array_append(T1.r_path, ' || key_name || '::varchar) as r_path, B.' || key_name || '::varchar = any(T1.r_path) as r_flag
from ' || tab_name || ' B, T1
where not r_flag
and B.' || parent_key_name || ' = T1.' || key_name || ')
select * from T1 order by T1.r_path ';

return query execute v_query;



end;
$$
language pl/pgsql
;



iPhone 에서 작성된 글입니다.


Comment +0

오라클을 주로 사용하던 이들은 다른 DBMS에서 아쉬운 것들이 몇가지 있죠. 현재 사용중인 PostgreSQL의 경우, 오라클의 자유로운 db link와 merge 등이 아주 그립습니다. 그래서 이 merge 기능을 대신하는 방법을 찾아봤습니다.

수정 가능한 WITH CTE 구문을 이용한 merge 기능 구현

WITH TEST AS (
UPDATE world_human A
SET cel_phone = B.cel_phone, email_addr = B.email_addr
FROM servay B
WHERE A.human_id = B.human_id
RETURNING A.*)
INSERT INTO world_human(human_id, cel_phone, email_addr)
SELECT C.human_id, C.cel_phone, C.email_addr
FROM servay C
WHERE C.human_id NOT IN (SELECT human_id FROM TEST)
;

이렇게하면 MERGE와 동일하게 입력 및 수정을 하나의 쿼리로 실행할 수 있습니다.

아 조건이 하나있는데, PostgreSQL 버전이 9.1.3이어야합니다. 9.0 버전에서는 안되는걸 테스트와 메뉴얼로 확인 했습니다. 9.1.2나 9.1.1에서도 잘 되는지는 확인을 못 했습니다.

iPhone 에서 작성된 글입니다.

Comment +0

약 3주일 정도 PostgreSQL을 써본 감상.

뭐랄까 이것 저것 다 되는듯하면서 안 되거나 모양새가 묘하네요.
디비 링크가 좀 불편하고요. 뭐 아직 방법을 못 찾은거닐수도 있지만요...
음 열심히 공부 중 입니다.

iPhone 에서 작성된 글입니다.

Comment +0