2016-07-13 24 views
0

我刚写完我的第一个PLSQL函数。在这里它做了什么。改进PL/pgSQL函数

SQL函数尝试将重复时间戳重置为NULL。

  1. 从表call_records发现是重复的所有时间戳。(使用组由)
  2. 循环通过每个timestamp.Find与同一时间戳(倍-1中的所有记录,使得仅1对于给定的时间记录是本)
  3. 从所有在步骤2中找到更新的记录的时戳为NULL

这里的SQL函数的样子。

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 

所有我想要的是更新复制时间戳为空,这样只有一个记录具有给定的时间戳。

总之上面的查询应返回结果这样

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。我不认为你需要一个函数,这听起来好像这可以用一个更新语句来完成。但是,如果没有完整的表格定义和一些示例数据,这几乎是不可能告诉我的@a_horse_with_no_name –

+0

我已经更新了这个问题。 – 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 

下一页 - 这是典型的无效函数 - 它不会返回任何有趣的结果,通常这些函数在一切正常或者引发异常时不会返回任何内容,返回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是数组变量 –