Search code examples
sqlpostgresqlpostgresql-9.1plpgsqlset-returning-functions

Postgres function returning one record while I have many records?


I have many records which my simple query returning but when i use function it just gives me first record,

firstly i create my own data type using,

CREATE TYPE my_type (usr_id integer , name varchar(30));

and my function is,

CREATE OR REPLACE function test() returns my_type as $$
    declare rd varchar := '21';
    declare personphone varchar := NULL;
    declare result my_type;
    declare SQL VARCHAR(300):=null; 
DECLARE
    radiophone_clause text = '';

BEGIN        
    IF rd IS NOT NULL then
        radiophone_clause = 'and pp.radio_phone = '|| quote_literal(rd);
    END IF;

    IF personphone IS NOT NULL then      
        radiophone_clause = radiophone_clause|| 'and pp.person_phone = '|| quote_literal(personphone);
    END IF;
    radiophone_clause = substr(radiophone_clause, 5, length(radiophone_clause)- 4);

     EXECUTE format('select pt.id,pt.name from product_template pt inner join product_product pp on pt.id=pp.id where %s ;', radiophone_clause) into result.id,result.name ;
    return result;
END;
$$ LANGUAGE plpgsql;

in this function i am returning my_type which return only first row how to return more then one row,


Solution

  • To return set of composite type from plpgsql function you should:

    • declare function's return type as setof composite_type,
    • use return query (or return next) instruction (documentation).

    I have edited your code only in context of changing return type (it is an example only):

    DROP function test();   -- to change the return type one must drop the function
    
    CREATE OR REPLACE function test() 
    -- returns my_type as $$
    returns setof my_type as $$                    -- (+)
        declare rd varchar := '21';
        declare personphone varchar := NULL;
    --    declare result my_type;
    --    declare SQL VARCHAR(300):=null; 
    DECLARE
        radiophone_clause text = '';
    
    BEGIN        
        IF rd IS NOT NULL then
            radiophone_clause = 'and pp.radio_phone = '|| quote_literal(rd);
        END IF;
    
        IF personphone IS NOT NULL then      
            radiophone_clause = radiophone_clause|| 'and pp.person_phone = '|| quote_literal(personphone);
        END IF;
        radiophone_clause = substr(radiophone_clause, 5, length(radiophone_clause)- 4);
    
        RETURN QUERY                               -- (+)
        EXECUTE format('select pt.id,pt.name from product_template pt inner join product_product pp on pt.id=pp.id where %s ;', radiophone_clause)
        ;                                          -- (+)
    --    into result.id,result.name;
    --    return result;
    END;
    $$ LANGUAGE plpgsql;