Обсуждение: CASE statement and SETOF values

Поиск
Список
Период
Сортировка

CASE statement and SETOF values

От
Christian Schoenebeck
Дата:
HI!

Consider the following server side function:

CREATE FUNCTION my_function(int4) RETURNS SETOF int8 AS
$BODY$
SELECT
CASE WHEN (some_condition)
     THEN (
         SELECT ... -- arbitrary select (returning row(s) of int8 values)
     )
     ELSE (
         SELECT ... -- arbitrary select (returning row(s) of int8 values)
     )
END
$BODY$
LANGUAGE 'sql' VOLATILE;

This function works fine if one of the two inner SELECT statements returns
exactly one result (one row), but fails whenever one of them returns more
than one result / rows.

What is the reason? I mean the function is declared as returning "SETOF int8",
so why does it expect a scalar?

CU
Christian

Re: CASE statement and SETOF values

От
Stephan Szabo
Дата:
On Mon, 24 Jul 2006, Christian Schoenebeck wrote:

> Consider the following server side function:
>
> CREATE FUNCTION my_function(int4) RETURNS SETOF int8 AS
> $BODY$
> SELECT
> CASE WHEN (some_condition)
>      THEN (
>          SELECT ... -- arbitrary select (returning row(s) of int8 values)
>      )
>      ELSE (
>          SELECT ... -- arbitrary select (returning row(s) of int8 values)
>      )
> END
> $BODY$
> LANGUAGE 'sql' VOLATILE;
>
> This function works fine if one of the two inner SELECT statements returns
> exactly one result (one row), but fails whenever one of them returns more
> than one result / rows.
>
> What is the reason? I mean the function is declared as returning "SETOF int8",
> so why does it expect a scalar?

The above basically looks like:
CASE WHEN <search condition> THEN <value expression> ELSE
<value expression> END.

In SQL92 at least, the form of <value expression> which looks like (SELECT
...) is <scalar subquery> which is limited to 1 column and 1 row.  The
other subquery forms don't look legal in that position unless they changed
that in a later version of the spec.

Re: CASE statement and SETOF values

От
Christian Schoenebeck
Дата:
Am Dienstag, 25. Juli 2006 00:01 schrieb Stephan Szabo:
> The above basically looks like:
> CASE WHEN <search condition> THEN <value expression> ELSE
> <value expression> END.
>
> In SQL92 at least, the form of <value expression> which looks like (SELECT
> ...) is <scalar subquery> which is limited to 1 column and 1 row.  The
> other subquery forms don't look legal in that position unless they changed
> that in a later version of the spec.

Ok, and is there any way to circumvent this problem?

CU
Christian

Re: CASE statement and SETOF values

От
Stephan Szabo
Дата:
On Tue, 25 Jul 2006, Christian Schoenebeck wrote:

> Am Dienstag, 25. Juli 2006 00:01 schrieb Stephan Szabo:
> > The above basically looks like:
> > CASE WHEN <search condition> THEN <value expression> ELSE
> > <value expression> END.
> >
> > In SQL92 at least, the form of <value expression> which looks like (SELECT
> > ...) is <scalar subquery> which is limited to 1 column and 1 row.  The
> > other subquery forms don't look legal in that position unless they changed
> > that in a later version of the spec.
>
> Ok, and is there any way to circumvent this problem?

Well, the easiest one is to use a procedural language to get conditional
statements. For example, something like the following (untested) plpgsql
body:

DECLARE
 r record
BEGIN
 IF (some_condition) THEN
  FOR r IN SELECT ... LOOP
   RETURN NEXT r;
  END LOOP;
 ELSE
  FOR r IN SELECT ... LOOP
   RETURN NEXT r;
  END LOOP;
 END IF;
 RETURN;
END;

Re: CASE statement and SETOF values

От
Christian Schoenebeck
Дата:
Am Dienstag, 25. Juli 2006 17:56 schrieben Sie:
> You could use a procedural language like plpgsql.

Ok, using the plpgsql approach I tried this:

CREATE FUNCTION my_function(int4) RETURNS SETOF int8 AS
$BODY$
DECLARE
    myrow RECORD;
BEGIN
    IF (some_condition) THEN
            FOR myrow IN SELECT ... -- some select statement
            LOOP
                RETURN NEXT myrow."foocolumn";
            END LOOP;
        ELSE
            FOR myrow IN SELECT ... -- some select statement
            LOOP
                RETURN NEXT myrow."foocolumn";
            END LOOP;
    END IF;
    RETURN;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

But creating this function fails, because it's "missing a LOOP" statement.
What am I missing?

CU
Christian