When a syntax error occurs in the declaration declare postgresql - postgresql

CREATE OR REPLACE FUNCTION fn_SplitArrayStr( anyelement , anyelement )
RETURNS anyarray
LANGUAGE SQL
AS $$
DECLARE f1 text , f2 text ;
BEGIN
f1 := $1::text ;
f2 := $2::text ;
SELECT * FROM UNNEST( string_to_array(f1, f2) ) as c1 ;
END ;
$$;
ERROR : Syntax error at or near "text"
LINE 2 : DECLARE f1 text , f2 text ;
How do I change?

I see two issues:
wrong language specification - PostgreSQL native procedural language is plpgsql.
DECLARE statement uses semicolon for separation between individual variable declarations.
postgres=# create or replace function foo()
returns int as $$
declare a int; b int;
begin
a := 10; b := 20;
return a + b;
end;
$$ language plpgsql;
CREATE FUNCTION
postgres=# select foo();
┌─────┐
│ foo │
╞═════╡
│ 30 │
└─────┘
(1 row)

You can try to specify the language at the end of the procedure
$$
LANGUAGE plpgsql;

You've written PL/PgSQL code but marked it LANGUAGE SQL. Use LANGUAGE plpgsql if you're writing pl/pgsql functions.

Related

Postgresql howto dynamically change parameter value

Is it possible to dynamically set param of numeric() ? eg:
CREATE OR REPLACE somefunction() RETURNS numeric AS
DECLARE
f numeric;
x integer;
BEGIN
x := 2;
SELECT INTO f CAST(something AS numeric(12, x));
RETURN f;
END;
So, I don't need to use CASE inside my plpgsql function if possible :) Tried everything, but it does not work, cast expects constant. Thanks:)
Using Dynamic query:
CREATE OR REPLACE FUNCTION public.somefunction(something numeric)
RETURNS numeric
LANGUAGE plpgsql
AS $function$
DECLARE
f numeric;
x integer;
BEGIN
x := 2;
EXECUTE 'SELECT CAST($1 AS numeric(12, ' || x ||'))' INTO f USING something;
RETURN f;
END;
$function$
;
select somefunction(126.787);
somefunction
--------------
126.79
Alternate where you pass in the scale:
CREATE OR REPLACE FUNCTION public.somefunction(something numeric, scale integer)
RETURNS numeric
LANGUAGE plpgsql
AS $function$
DECLARE
f numeric;
BEGIN
EXECUTE 'SELECT CAST($1 AS numeric(12, ' || scale ||'))' INTO f USING something;
RETURN f;
END;
$function$
;
select somefunction(126.787,2);
somefunction
--------------
126.79
(1 row)
select somefunction(126.787,1);
somefunction
--------------
126.8

Postgres session variables not working inside a function

I am setting a session variable inside a postgres function and the values are not getting set.
Any help is most appreciated. Thanks in advance.
I am using "PostgreSQL 10.6, compiled by Visual C++ build 1800, 64-bit"
My code is as follows:
The function:
CREATE FUNCTION set_rp_vals(iv_rp_company varchar, iv_rp_portfolio varchar)
RETURNS integer
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
DECLARE
l_retval integer;
BEGIN
l_retval := 1;
RAISE NOTICE '1.iv_rp_company: >>> %', iv_rp_company;
RAISE NOTICE '2.iv_rp_portfolio: >>> %', iv_rp_portfolio;
--set the session variable
set rp.company = iv_rp_company;
set rp.portfolio = iv_rp_portfolio;
RETURN l_retval;
EXCEPTION
WHEN OTHERS THEN
RETURN 9;
END;
$function$
;
The function call:
SELECT set_rp_vals(iv_rp_company := 'COMPAN',iv_rp_portfolio := 'PORTOF');
--Retrieving the session variables:
select
current_setting('rp.company') as company,
current_setting('rp.portfolio') as portfolio;
The value returned by the above query:
I would use the set_config() function for this:
CREATE OR REPLACE FUNCTION set_rp_vals(iv_rp_company varchar, iv_rp_portfolio varchar)
RETURNS integer
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
DECLARE
l_retval integer;
BEGIN
l_retval := 1;
RAISE NOTICE '1.iv_rp_company: >>> %', iv_rp_company;
RAISE NOTICE '2.iv_rp_portfolio: >>> %', iv_rp_portfolio;
--set the session variable
perform set_config('rp.company', iv_rp_company, false);
perform set_config('rp.portfolio', iv_rp_portfolio, false);
RETURN l_retval;
EXCEPTION
WHEN OTHERS THEN
RETURN 9;
END;
$function$
;
CREATE FUNCTION
Execute with your values:
SELECT set_rp_vals(iv_rp_company := 'COMPAN',iv_rp_portfolio := 'PORTOF');
NOTICE: 1.iv_rp_company: >>> COMPAN
NOTICE: 2.iv_rp_portfolio: >>> PORTOF
┌─────────────┐
│ set_rp_vals │
├─────────────┤
│ 1 │
└─────────────┘
(1 row)
select
current_setting('rp.company') as company,
current_setting('rp.portfolio') as portfolio;
┌─────────┬───────────┐
│ company │ portfolio │
├─────────┼───────────┤
│ COMPAN │ PORTOF │
└─────────┴───────────┘
(1 row)

How to get a output of a variable from function in postgresql

I am new to PostgreSQL. I have the query:
---------
DO
$$
DECLARE
l_pin INT;
l_pin1 int;
BEGIN
l_pin := 3;
l_pin1 := 4;
select l_pin,l_pin1;
END;
$$
LANGUAGE PLPGSQL;
--------------------------
from above query am getting an error as
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function inline_code_block line 9 at SQL statement
SQL state: 42601
I need to get the values of l_pin and l_pin1 as output.
What you have there is a DO statement, not a "query" nor a "function". DO statements cannot return anything at all.
How to perform a select query in a DO block?
The displayed error is because you cannot call SELECT in a plpgsql code block without assigning the result. To actually return values from a plpgsql function, use some form of RETURN (explicitly or implicitly).
As minimal example:
CREATE OR REPLACE FUNCTION foo(OUT l_pin int, OUT l_pin1 int)
RETURNS record AS -- RETURNS record is optional because of OUT parameters
$func$
BEGIN
l_pin := 3;
l_pin1 := 4;
RETURN; -- RETURN is optional here because of OUT parameters
END
$func$ LANGUAGE plpgsql;
SELECT * FROM foo();
Related:
Can I make a plpgsql function return an integer without using a variable?
SELECT or PERFORM in a PL/pgSQL function
Returning from a function with OUT parameter
First you can create a new type that can hold multiple values:
CREATE TYPE type_name AS (l_pin INTEGER, l_pin1 INTEGER);
Then you can do something like:
CREATE OR REPLACE FUNCTION function_name()
RETURNS type_name AS $$
DECLARE
result type_name;
BEGIN
/* Code that puts those values into type_name object
i.e.
result.l_pin := 3;
result.l_pin1 := 4;
*/
return result ;
END
$$ language plpgsql

Postgresql plpgsql multiple row loop

I'm busy trying to rewrite an Informix stored procedure for a PostgreSQL
database and I am stuck on something that is probably quite obvious to
everyone who know PostgreSQL.
I have my sql script as follows
-- ensure type and function get created
drop type if exists tp_users cascade;
drop function if exists sp_cmplist();
-- create type
create type tp_users as (
us_id char(30),
us_status char(1)
);
create function sp_cmplist()
returns tp_users as $$
declare
lr_users tp_users;
begin
for lr_users in
select users.us_id, users.us_status
from users
loop
return lr_users;
end loop;
end
$$ language 'plpgsql';
select sp_cmplist();
this is just a dummy script to select from an imaginary users table but how would I use this script with a cursor or loop to make sure all results are returned?
This code works:
CREATE TABLE foo(a int);
INSERT INTO foo VALUES(10),(20);
CREATE OR REPLACE FUNCTION retfoo()
RETURNS SETOF foo AS $$
BEGIN
RETURN QUERY SELECT * FROM foo;
RETURN;
END;
$$ LANGUAGE plpgsql;
postgres=# SELECT * FROM retfoo();
┌────┐
│ a │
├────┤
│ 10 │
│ 20 │
└────┘
(2 rows)
Time: 1.143 ms
I may have answered my own question with the following
drop type if exists tp_users cascade;
drop function if exists sp_cmplist();
create type tp_users as (
us_id text,
us_status text,
lv_nothing text,
lv_cnt int
);
create function sp_cmplist()
returns setof tp_users as $$
declare
lr_users tp_users;
lv_cnt int;
begin
lv_cnt := 0;
for lr_users in
select users.us_id, users.us_status
from users
loop
-- increment this counter for testing purposes
lv_cnt := lv_cnt + 1;
lr_users.lv_nothing := 'yupy';
lr_users.lv_cnt := lv_cnt;
return next lr_users;
end loop;
return;
end
$$ language 'plpgsql';
select * from sp_cmplist();
this seems to work perfectly

PL/pgSQL syntax error

I have a very simple PL/pgSQL script:
declare x varchar(100);
When I run it I get a message:
[WARNING ] declare x varchar(100)
ERROR: syntax error at or near "varchar"
LINE 1: declare x varchar(100)
^
I really don't understand what is wrong with this.
you can use procedural statements only inside function body in PostgreSQL.
CREATE OR REPLACE FUNCTION foo()
RETURNS int AS
$$ -- here start procedural part
DECLARE x int;
BEGIN
x := 10;
RETURN x;
END;
$$ -- here finish procedural part
LANGUAGE plpgsql; -- language specification
or in temporary function (anonymous block)
DO $$
DECLARE x int;
BEGIN
x := 10;
RAISE NOTICE '>>>%<<<', x;
END;
$$;
isn't possible to use procedural statements as SQL statements like T-SQL.
Use exemple
DO $$
Declare
test varchar;
begin
test := 'teste';
if (char_length(test) > 0) then
RAISE NOTICE '>>>%<<<', test;
end if;
end;
$$;
I have resolved this by the following piece of code:
do $$
declare TypeId int;
declare MasterId int;
begin
TypeId := null;
MasterId := null;
end;
$$;