2016-07-13 3 views
0

첫 번째 PLSQL 함수 작성이 끝났습니다. 여기 무슨 일이야.PL/pgSQL 함수 개선

SQL 함수는 중복 시간 소인을 NULL로 재설정하려고 시도합니다. 테이블 call_records 가입일

  1. 중복되는 모든 타임 스탬프를 찾기. 주어진 시간 만 1 레코드가되도록, 각 관통
  2. 루프가 동일한 타임 스탬프 (시간 -1 모든 기록을 timestamp.Find (그룹화를 사용) 2 단계 업데이트에있는 모든 기록에서
  3. 이 타임 스탬프는 SQL 함수처럼 보이는 방법은 다음과

을 NULL로) 존재.

CREATE OR REPLACE FUNCTION nullify() RETURNS INTEGER AS $$ 
DECLARE 
T call_records.timestamp%TYPE; 
-- Not sure why row_type does not work 
-- R call_records%ROWTYPE; 
S integer; 
CRNS bigint[]; 
TMPS bigint[]; 
sql_stmt varchar = ''; 
BEGIN 
FOR T,S IN (select timestamp,count(timestamp) as times from call_records where timestamp IS NOT NULL group by timestamp having count(timestamp) > 1) 
LOOP 
    sql_stmt := format('SELECT ARRAY(select plain_crn from call_records where timestamp=%s limit %s)',T,S-1); 
    EXECUTE sql_stmt INTO TMPS; 
    CRNS := array_cat(CRNS,TMPS); 
END LOOP; 

    sql_stmt = format('update call_records set timestamp=null where plain_crn in (%s)',array_to_string(CRNS,',')); 
    RAISE NOTICE '%',sql_stmt; 
    EXECUTE sql_stmt ; 
    RETURN 1; 
END 
$$ LANGUAGE plpgsql; 

PL/pgSQL 언어에 대해 더 잘 이해할 수 있도록 도와주세요.

@a_horse_with_no_name : DB 구조는 다음과 같습니다. \ d + call_records; 이제

id integer primary key 
plain_crn bigint 
timestamp bigint 
efd  integer default 0 




    id | efd  | plain_crn | timestamp 
----------+------------+------------+----------- 
    1  | 2016062936 | 8777444059 | 14688250050095   
    2  | 2016062940 | 8777444080 | 14688250050095 
    3  | 2016063012 | 8880000000 | 14688250050020  
    4  | 2016043011 | 8000000000 | 14688240012012 
    5  | 2016013011 | 8000000001 | 14688250050020 
    6  | 2016022011 | 8440000001 | 

,

select timestamp,count(timestamp) as times from call_records where timestamp IS NOT NULL group by timestamp having count(timestamp) > 1 

    timestamp  | count 
-----------------+----------- 
14688250050095 |  2 
14688250050020 |  2 

내가 원하는 모든 것은 그렇게 만 그들 중 하나 개 기록이 주어진 타임 스탬프를 가지고 null로 중복 타임 스탬프를 업데이트하는 것입니다. 짧은 위의 쿼리에서

이 같은 결과를 반환해야이

select timestamp,count(timestamp) as times from call_records where timestamp IS NOT NULL group by timestamp; 

     timestamp  | count 
    -----------------+----------- 
    14688250050095 |  1 
    14688250050020 |  1 
+2

여기에 동적 SQL이 필요하지 않습니다. 나는 함수가 필요 없다고 생각한다. 이것은 하나의 update 문을 사용하여 수행 할 수있는 것처럼 들린다. 그러나 전체 표 정의 및 일부 샘플 데이터가 없으면이를 알리기가 거의 불가능합니다. –

+0

@a_horse_with_no_name 질문을 업데이트했습니다. – Noobie

답변

0

직접 배열 변수를 사용할 수 있습니다 (술어 =ANY()와 필터 - 사용하여 동적 SQL은이 목적을 위해 잘못된 :

 
postgres=# DO $$ 
DECLARE x int[] = '{1,2,3}'; 
result int[]; 
BEGIN 
    SELECT array_agg(v) 
    FROM generate_series(1,10) g(v) 
    WHERE v = ANY(x) 
    INTO result; 
    RAISE NOTICE 'result is: %', result; 
END; 
$$; 
NOTICE: result is: {1,2,3} 
DO 

다음 - 이것은 일반적인 void 함수입니다. 흥미 롭지 않습니다. 일반적으로이 함수는 모두 정상이거나 예외가 발생하면 아무 것도 반환하지 않습니다. 1 RETURN 1을 반환하면 쓸모가 없습니다.

CREATE OR REPLACE FUNCTION foo(par int) 
RETURNS void AS $$ 
BEGIN 
    IF EXISTS(SELECT * FROM footab WHERE id = par) 
    THEN 
    ... 
    ELSE 
    RAISE EXCEPTION 'Missing data for parameter: %', par; 
    END IF; 
END; 
$$ LANGUAGE plpgsql; 
+0

당신은 어떤 배열 변수를 여기에서 가지고 다닙니 까? – Noobie

+0

x는 배열 변수입니다. –