简体   繁体   中英

Exception in PL/pgSQL function

I have small issue about exception in PL/pgSQL. My task is to write a function to find reservoirs with a certain length.

My code:

create or replace function
 info_about_reservoir(num_of_letters int)
 returns int as
$$
 declare
  res_name varchar(50);
  res_type varchar(50);
  res_area decimal(10,0);
  counter int := 1;
 begin
  select r_name,t_name,r_area into strict res_name,res_type,res_area
  from 
   reservoirs right outer join reservoirs_types 
   on t_id=r_t_id
  where char_length(r_nazwa)=$1;
  raise notice 'Name: %, type: %, area: %',res_name,res_type,res_area;
  exception
   when no_data_found then
    raise notice 'No reservoir with name lenght %',$1;
   when too_many_rows then
    raise notice 'Too much reservoirs with name lenght %',$1;
  return counter;
 end;
$$ language plpgsql;

For num_of_letters must return exceptions: --SELECT info_about_reservoir(7) -- no_data_found --SELECT info_about_reservoir(8) -- too_many_rows --SELECT info_about_reservoir(9) -- Name: % ...

In previous versions of this script I have returned only exceptions and ERROR: query has no destination for result data. Now it returns for 7: Name: ... for 8: Name: first row from some rows query ... for 9: Name: row from one row query ...


Sorry for the confusion, I have an answer for this:

create or replace function
 info_about_reservoir(num_of_letters int)
 returns int as
$$
 declare
  res_name varchar(50);
  res_type varchar(50);
  res_area int;
  counter int := 1;
 begin
  select r_name,t_name,r_area into strict res_name,res_type,res_area
  from 
   reservoirs right outer join reservoirs_types 
   on t_id=a_t_id
  where char_length(r_name)=$1;
  raise notice 'Name: %, type: %, area: %',res_name,res_type,res_area;
  return counter;
  exception
   when no_data_found then
    raise notice 'No reservoir with name lenght %',$1;
    return counter;
   when too_many_rows then
    raise notice 'Too much reservoirs with name lenght %',$1;
    return counter;
 end;
$$ language plpgsql;

Now it works. :D

Building on assumptions about your missing table definitions.

The RIGHT [OUTER] JOIN in your latest version serves no purpose. Since the condition is on the left table, you could as well use [INNER] JOIN . Do you actually want a LEFT JOIN ? So that reservoirs without matching reservoirs_type are still returned?

The STRICT modifier in SELECT INTO only considers whether a single row is returned, it does not react to a missing row in a LEFT JOIN (or individual columns being assigned NULL values.

Could look like:

CREATE OR REPLACE FUNCTION info_about_reservoir(num_of_letters int)
  RETURNS int AS
$func$
DECLARE
  res_name text;
  res_type text;
  res_area int;
  counter  int := 1;
BEGIN
   SELECT r_name, t_name, r_area  -- no table-qualification for lack of info
   INTO   STRICT res_name, res_type, res_area
   FROM   reservoirs r
    reservoirs_types t ON t_id = a_t_id -- OR JOIN, not RIGHT JOIN
   WHERE  length(r_name) = $1;

   RAISE NOTICE 'Name: %, type: %, area: %', res_name, res_type, res_area;
   RETURN counter;

EXCEPTION
   WHEN no_data_found THEN
      RAISE NOTICE 'No reservoir with name length %.', $1;
      RETURN counter;
   WHEN too_many_rows THEN
      RAISE NOTICE 'Too many reservoirs with name length %.', $1;
      RETURN counter;
END
$func$ LANGUAGE plpgsql;
  • counter is always 1 . What's the purpose?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM