X-Original-To: pgsql-sql-postgresql.org@postgresql.org Received: from localhost (mx1.hub.org [200.46.208.251]) by postgresql.org (Postfix) with ESMTP id B70819FB319 for ; Thu, 17 Aug 2006 09:54:33 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.208.251]) (amavisd-new, port 10024) with ESMTP id 19017-10 for ; Thu, 17 Aug 2006 09:54:22 -0300 (ADT) X-Greylist: domain auto-whitelisted by SQLgrey- Received: from svr4.postgresql.org (svr4.postgresql.org [66.98.251.159]) by postgresql.org (Postfix) with ESMTP id 7B2429FA5FC for ; Thu, 17 Aug 2006 09:54:23 -0300 (ADT) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.3 Received: from outmx018.isp.belgacom.be (outmx018.isp.belgacom.be [195.238.4.117]) by svr4.postgresql.org (Postfix) with ESMTP id 7DB685AF883 for ; Thu, 17 Aug 2006 12:54:21 +0000 (GMT) Received: from outmx018.isp.belgacom.be (localhost [127.0.0.1]) by outmx018.isp.belgacom.be (8.12.11.20060308/8.12.11/Skynet-OUT-2.22) with ESMTP id k7HCsHFB019871 for ; Thu, 17 Aug 2006 14:54:17 +0200 (envelope-from ) Received: from [192.168.0.214] (153.32-244-81.adsl-dyn.isp.belgacom.be [81.244.32.153]) by outmx018.isp.belgacom.be (8.12.11.20060308/8.12.11/Skynet-OUT-2.22) with ESMTP id k7HCs84M019770; Thu, 17 Aug 2006 14:54:08 +0200 (envelope-from ) Message-ID: <44E466EF.5070308@skynet.be> Date: Thu, 17 Aug 2006 14:54:07 +0200 From: MaXX User-Agent: Thunderbird 1.5.0.5 (X11/20060802) MIME-Version: 1.0 To: Rob Tester , pgsql-sql@postgresql.org Subject: Re: Help with optional parameters References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0 tagged_above=0 required=5 tests= X-Spam-Level: X-Archive-Number: 200608/133 X-Sequence-Number: 26091 Rob Tester wrote: > I have the need to have optional values for a query in a stored procedure > that I am building. (using postgres 8.1.4). This particular query > executes > against a huge table (several million rows) and has six optional > parameters > that can be sent to the function. If one of the parameters is null > then the > parameter doesn't need to be included in the query. Also the values in > the > columns that are optional can contain NULL values. One way that will work > (although extremely cumbersome) is to have a switch on the parameters to > execute the correct query: > > --This is a sample > IF (a IS NULL AND b IS NULL) THEN > select * from my_table; > ELSEIF (a IS NOT NULL and b IS NULL) THEN > select * from my_table where a=parama; > ELSEIF (a IS NULL and b IS NOT NULL) THEN > select * from my_table where b=paramb; > ELSE > select * from my_table where a=parama AND b=paramb; > ENDIF; > > This is extremely bad when you have 6 parameters giving 64 possible > queries. > You can try something like this, it should show the basis, CREATE OR REPLACE FUNCTION test(int4, int4) RETURNS text AS $BODY$ DECLARE a ALIAS FOR $1; b ALIAS FOR $2; -- add as many as input param query_base text; has_param bool; query_where text; query_final text; BEGIN query_base := 'SELECT * FROM my_table '; has_param := FALSE; query_where := ''; IF (a IS NOT NULL) THEN IF (has_param IS FALSE)THEN -- there is no param yet add WHERE to the query query_where := ' WHERE '; ELSE -- there is already something in the WHERE clause, we need to add AND query_where := query_where || ' AND '; END IF; query_where := query_where || 'parama='||a; --beware if param quoting is required has_param := TRUE; -- now there is at least 1 param END IF; IF (b IS NOT NULL) THEN IF (has_param IS FALSE)THEN -- there is no param yet add WHERE to the query query_where := ' WHERE '; ELSE -- there is already something in the WHERE clause, we need to add AND query_where := query_where || ' AND '; END IF; query_where := query_where || 'paramb='||b; --beware if param quoting is required has_param := TRUE; -- now there is at least 1 param END IF; --copy/paste/edit this IF ENDIF block for each param query_final := query_base || query_where; RAISE NOTICE '%', query_final; RETURN query_final; -- EXECUTE query_final; -- END; $BODY$ LANGUAGE 'plpgsql' VOLATILE; test: select test(null,null) union select test(1,null) union select test(1,1) union select test(null,1); result: "SELECT * FROM my_table " "SELECT * FROM my_table WHERE parama=1" "SELECT * FROM my_table WHERE parama=1 AND paramb=1" "SELECT * FROM my_table WHERE paramb=1" HTH, -- MaXX