改进PL / pgSQL函数

时间:2016-07-13 18:06:03

标签: postgresql plpgsql stored-functions

我刚写完第一个PLSQL函数。这就是它的作用。

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

  1. 从表call_records中找到所有重复的时间戳。(使用分组依据)
  2. 循环遍历每个时间戳。查找具有相同时间戳的所有记录(时间为1,因此在给定时间内仅存在1条记录)
  3. 从步骤2中找到的所有记录中将时间戳更新为NULL
  4. 这里是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
    

    我想要的只是将重复的时间戳更新为null,以便只有其中一个记录具有给定的时间戳。

    简而言之,上面的查询应该像这样返回结果

       select timestamp,count(timestamp) as times from call_records where timestamp IS NOT NULL group by timestamp;
    
          timestamp      |    count 
        -----------------+-----------
         14688250050095  |      1
         14688250050020  |      1
    

1 个答案:

答案 0 :(得分:0)

您可以直接使用数组变量(使用谓词<?xml version="1.0" encoding="UTF-8"?> <api context="/omdbapi" name="omdbapi" xmlns="http://ws.apache.org/ns/synapse"> <resource methods="GET" uri-template="/*"> <inSequence> <send> <endpoint> <address trace="disable" uri="http://www.omdbapi.com/"/> </endpoint> </send> </inSequence> <outSequence> <datamapper config="gov:datamapper/omdbapiConfig.dmc" inputSchema="gov:datamapper/omdbapiConfig_inputSchema.json" inputType="XML" outputSchema="gov:datamapper/omdbapiConfig_outputSchema.json" outputType="XML"/> <respond/> </outSequence> <faultSequence/> </resource> </api> 进行过滤 - 使用动态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 =ANY()是没用的。

RETURN 1