2017-03-23 2 views
0

저는 지난 수년 동안 PostgreSQL에서 일해 왔지만, 배열 개념과 PostgreSQL에서 배열을 처리하는 방법에 대해서는 전혀 몰랐습니다. 여러 테이블에서 열을 선택하기위한 동적 쿼리가 필요하며 결과는 커서에 표시되고 열 이름은 동적으로 변경되어야합니다. (여러 테이블에 완전히 30 열은 사용자가 COL1, COL5, col6, col25이 필요한 경우가있다) 예에 대한문자열 배열을 매개 변수로 사용하지 않고 PostgreSQL에서 동적 쿼리를 사용합니다.

, 그래서 select 문 쿼리는 동적됩니다 같이 변경됩니다 :

select col1, col5,col6,col25 from table .... 

다른 사용자

가 COL2 필요 , COL5는 col7는 col29는 col26는 SELECT 문 어레이를

create or replace function func_my_method(check_in character varying, sel character varying[])... 
,745,151 것이다

select col2,col5,col7,col29,col26 from table .... and so on. 

프로 시저 통과 파라미터로서 동적으로 변화 할 것이다

이 SEL은 []를 처음 우리가 별도의 변수에 배열 값을 분할하고 이들 변수가 마지막으로하고 싶은 말

'select'||col1, col5,col6,col25||'from......' 

됩니다 select 문에 가정한다이

  sel[0]:='col1_name' 
      sel[1]:='col5_name' 
      sel[2]:='col6_name' 
      sel[3]:='col25_name' 

같이 포함 간단히 말해서 매개 변수에 배열을 전달해야하며 배열 값을 분리해야하며 별도의 변수에 할당합니다. 이 변수는 동적 방식으로 명령문을 선택하는 데 사용됩니다.

+0

그래서 동적 문을 만듭니다. 니가 그걸로 무엇을하고 있니? 세트? 표? 행 수? –

+0

@ VaoTsun 나는 당신의 참고를 위해 언급 한이 문장이나 절차를 만들지 않습니다. 위의 기준에 대한 절차가 필요하고 커서로 반환됩니다. 친절하게 도와주세요. –

+1

그래서 ['refcursor'] (https://www.postgresql.org/docs/current/static/plpgsql-cursors.html)와 같은 것이 필요합니까? http://rextester.com/FMCUW60860 - SQL 삽입 가능성을 최소화하기 위해'format()'또는'quote_ident() '로 열 이름을 인용하는 것을 잊지 마십시오. – pozs

답변

1

베어 refcursor은 임의의 수의 열을 포함 할 수 있습니다. 당신이 읽을 수있는 특별한 문을해야합니다 있지만 : FETCH ...

CREATE OR REPLACE FUNCTION func_my_method(check_in text, sel text[], ref refcursor) 
    RETURNS refcursor 
    LANGUAGE plpgsql 
AS $func$ 
BEGIN 
    OPEN ref FOR EXECUTE 'SELECT ' || (SELECT string_agg(quote_ident(c), ', ') 
            FROM unnest(sel) c) || ' FROM ...'; 
    RETURN ref; 
END; 
$func$; 

SELECT func_my_method('check_in', ARRAY['col1', 'col2'], 'sample_name'); 
FETCH ALL IN sample_name; 

http://rextester.com/ZCZT84224

을 : 당신은는 함수 본문에 refcursor 매개 변수를 & DECLARE 하나를 생략 할 수 . 이 방법으로 PostgreSQL은 refcursor에 대한 (충돌하지 않는) 이름을 생성합니다.이 이름은 SELECT func_my_method(...)을 호출 할 때 반환됩니다. FETCH ... 성명에 그 이름이 필요합니다.

업데이트 : 완전히 자격을하려는 경우 (일부) 열 (즉, 쓰기 테이블 이름 & 열이 너무), 당신이 중 하나를해야합니다 :

CREATE OR REPLACE FUNCTION func_my_method2(check_in text, sel text[], ref refcursor) 
    RETURNS refcursor 
    LANGUAGE plpgsql 
AS $func$ 
BEGIN 
    OPEN ref FOR EXECUTE 'SELECT ' || (SELECT string_agg((SELECT string_agg(quote_ident(c), '.') 
                 FROM unnest(string_to_array(fq, '.')) c), ', ') 
            FROM unnest(sel) fq) || ' FROM ...'; 
    RETURN ref; 
END; 
$func$; 

SELECT func_my_method2('check_in', ARRAY['col1', 'check_in.col2'], 'sample_name2'); 
FETCH ALL IN sample_name2; 

(이에 sel 매개 변수를 분할합니다 "

: 테이블 & 열 이름)

또는 .을 포함 할 수 없습니다 : - .에 완전한 이름의 일부 "하지만 단점을 가지고

CREATE OR REPLACE FUNCTION func_my_method3(check_in text, sel text[][], ref refcursor) 
    RETURNS refcursor 
    LANGUAGE plpgsql 
AS $func$ 
BEGIN 
    OPEN ref FOR EXECUTE 'SELECT ' || (SELECT string_agg((SELECT string_agg(quote_ident(sel[i][j]), '.') 
                 FROM generate_subscripts(sel, 2) j), ', ') 
            FROM generate_subscripts(sel, 1) i) || ' FROM ...'; 
    RETURN ref; 
END; 
$func$; 

SELECT func_my_method3('check_in', ARRAY[ARRAY['check_in', 'col1'], ARRAY['check_in', 'col2']], 'sample_name3'); 
FETCH ALL IN sample_name3; 

(그러나 배열에 직사각형이 있어야하므로 모든 열 하위 배열은 동일한 정확한 크기 여야합니다. 따라서 모든 열에 대해 테이블 ​​이름을 제공하거나 둘 중 하나에 테이블 이름을 제공해야합니다.)

http://rextester.com/JNI24740

+0

이 방금 완성 된 코드를 반환합니다. http://rextester.com/IFNLM12119 –

+0

@dineshdanny 예, 정규화 된 이름은'format()'또는'quote_ident()'와 함께 직접 사용할 수 없습니다. 1 개의 테이블 만 선택하려면, 매개 변수에서 제외하고 &''SELECT mm_items ''를 사용하십시오. || ...) ... – pozs

+0

@dineshdanny ... 여러 테이블을 사용하려면 함수에서 따옴표를 사용하지 말고 (* * 항상 ** 신뢰할 수있는 소스에서 그 함수를 호출하고, 아마도 그것을 얻기위한'REVOKE' 권한) - 또는'sel' 매개 변수를 "구문 분석"해야합니다 ('.) – pozs