2012-02-03 3 views
1

답변을 검색했지만 찾지 못했습니다. postgres에서 테이블 이름으로 선택한 값을 사용합니다

는 그래서 난, 유형 이름을 보유하고 users 말을 할 수있는 테이블을 types

CREATE TABLE types 
(
    type_id serial NOT NULL, 
    type_name character varying, 
    CONSTRAINT un_type_name UNIQUE (type_name) 
) 

있어 - 이것은 해당 테이블 users의 이름입니다. 이 디자인은 약간 추한 일이지만 사용자가 자신의 유형을 만들 수 있도록 만들어졌습니다. (이 acheve 더 나은 방법은 무엇입니까?)

는 지금은이 같은 쿼리를 수행 할 :

select type_name, (select count(*) from ???) from types 

각 유형의 모든 개체 유형의 이름과 수의 목록을 얻을 수 있습니다.

이 작업을 수행 할 수 있습니까?

답변

3

PLpgSQL 기능과 동적 SQL을 사용할 수 있습니다,하지만 난 뭔가 당신의 디자인 꺼져 있는지 의심 할 . 모든 유형에 대해 추가 테이블이 필요하지 않습니다.

순수 SQL에서는 수행하려는 작업을 수행 할 수 없습니다. 그것은하지만, 동적 SQL을 실행하는 plpgsql 기능을 수행 할 수 있습니다

CREATE OR REPLACE FUNCTION f_type_ct() 
    RETURNS TABLE (type_name text, ct bigint) AS 
$BODY$ 
DECLARE 
    tbl  text; 
BEGIN 
    FOR tbl IN SELECT t.type_name FROM types t ORDER BY t.type_name 
    LOOP 
     RETURN QUERY EXECUTE 
     'SELECT $1, count(*) FROM ' || tbl::regclass 
     USING tbl; 
    END LOOP; 
END; 
$BODY$ 
    LANGUAGE plpgsql; 

전화 : 당신은 여기에 무슨 일이 일어나고 있는지 이해하기 위해 chapter about plpgsql in the manual의 대부분을 연구해야합니다

SELECT * FROM f_type_ct(); 

합니다.

하나의 특별한 힌트 : cast to regclass은 SQLi에 대한 보호 장치입니다. 더 일반적으로 적용 할 수있는 quote_ident()을 사용할 수도 있지만 regclass으로 캐스트하는 동안 스키마 규정 테이블 이름을 제대로 처리하지 못합니다. 또한 호출하는 사용자가 볼 수있는 테이블 이름 만 허용합니다.

+0

위대한! 나는이 함수에서 무슨 일이 일어나는지 이해한다 :) 나는 함수없이 이것을 할 수 있다고 생각했다. ** 모든 유형에 대한 여분의 테이블 **은 성능상의 이유로 필요합니다. 작은 테이블은 더 효과적으로 색인 될 수 있습니다. afaik – k102

+0

@ k102 : BTW, 인덱스는 큰 (또는 거대한) 테이블에서 잘 작동합니다. 그것이 그들이 구축 한 것입니다. 작은 테이블의 경우 순차적 읽기는 인덱스를 사용하는 것보다 빠르다. –

4

당신은 SQL에서 직접 할 수없는

당신은 내가 충분한 정보가없는

CREATE OR REPLACE FUNCTION tables_count(OUT type_name character varying, OUT rows bigint) 
RETURNS SETOF record AS $$ 
BEGIN 
    FOR tables_count.type_name IN SELECT types.type_name FROM types 
    LOOP 
    EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(tables_count.type_name) INTO tables_count.rows; 
    RETURN NEXT; 
    END LOOP; 
    RETURN; 
END; 
$$ LANGUAGE plpgsql; 

SELECT * FROM tables_count(); 
+0

하, 파벨, 내 천둥을 훔쳐 갔어! 너무 빨리 다른 사람이 대답 할 것이라고 기대하지 않았습니다. :) 분명히, 나는 당신의 해결책을 좋아한다. 당신은 내가 생각해내는 것과 그것을 말할 수 있습니다. 두개의 작은 것들 : 당신은 선언에서'OUT'을 놓치고'type_name'은'text varying'라고 선언 된 OUT 매개 변수로 예외를 발생시키는'character varying'로 선언됩니다. 나는 둘 다 고쳤다. –

+0

감사합니다! 내가 알고 (또는 내가 아는 줄 알았는데) plpgsql에서 할 수있는, 난 그냥 그것 없이는 어떻게 할 수 있다고 생각 – k102

+0

수정 어윈 주셔서 감사합니다 :) –

관련 문제