SQL (Postgres) function definition - RETURNS - sql

I am trying to create a very simple PostgreSQL function, though I keep getting a very strange syntax error. The syntax I use is different from anything I have seen online (though this is the one the textbook uses), and thus I can't figure out why it fails...
This is the SQL:
CREATE OR REPLACE FUNCTION gsum(graphID integer)
RETURNS integer
BEGIN
DECLARE total integer DEFAULT 0
SELECT sum(weight) INTO total
FROM Edge
WHERE gno = graphID
RETURN total;
END;
The error is:
ERROR: syntax error at or near "BEGIN"
LINE 3: BEGIN
^
********** Error **********
ERROR: syntax error at or near "BEGIN"
SQL state: 42601
Character: 68

Your basic mistakes:
DECLARE must come before BEGIN.
Statements need to be terminated with ;.
Function body of a plpgsql function is a string and needs to be quoted. Use dollar-quoting to avoid complications with quotes in the body.
Missing keyword AS.
Missing language declaration LANGUAGE plpgsql.
Type mismatch.
You don't need a default.
This would still return NULL if the sum is NULL.
CREATE OR REPLACE FUNCTION gsum(graphID integer)
RETURNS integer AS
$func$
DECLARE
total integer;
BEGIN
SELECT sum(weight)::int INTO total
FROM edge
WHERE gno = graphID;
RETURN COALESCE(total, 0);
END
$func$ LANGUAGE plpgsql;
And you'd better use a simple SQL function for this like #Clodoaldo advised. Just add COALESCE().

It can be plain SQL in instead of plpgsql
create or replace function gsum(graphid integer)
returns bigint as $$
select sum(weight) as total
from edge
where gno = graphid;
$$ language sql;
Notice that if weight is integer sum will return bigint not integer.

CREATE OR REPLACE FUNCTION gsum(graphID integer)
RETURNS integer AS
$BODY$
DECLARE
total integer DEFAULT 0;
BEGIN
SELECT sum(weight) INTO total
FROM Edge
WHERE gno = graphID;
RETURN total;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

Related

Error while creating a User Defined Function in postgreSQL using SQL language

I am trying to create the following SQL(the only language I need for my use case) User Defined Function in PostgreSQL.
CREATE function sql_replace(textinput text,pattern character,lefttext integer,righttext integer)
returns text AS $$
DECLARE strlength integer default 0;
BEGIN
strlength = length($1);
return substr($1,1,$3 )
||regexp_replace(substr($1,$3+1,(strlength-$3-$4)),'[0-9]',$2)
||substr($1,(strlength-$4+1),$4 );
-- Additional logic
END;
$$ language SQL VOLATILE;
I have been encountering an error near line 3 in the declare statement. I have tried to push the declare statement inside the begin block but it didn't help. I have also tried to align the input type with SQL but got the same error.

Postgresql Error - Function return type mismatch

I'm looking for some help with a SQL function I am defining under pgAdmin3 for PostGreSQL.
It is a simple function supposed to calculate a ratio given a certain id but when I try to add the function, I get an error message.
Here is the code for the function:
CREATE OR REPLACE FUNCTION data.func_net_exposure(id_fund_arg text)
RETURNS real AS
$BODY$
DECLARE
net_exposure real;
AUM smallint;
BEGIN
AUM := (SELECT sum(cash_fund_total) from main.main_cash where id_fund = id_fund_arg);
net_exposure := (SELECT ROUND(sum(exposure_eur)/(100*AUM)) from main.main_inventory where id_fund = id_fund_arg);
return net_exposure;
END;
$BODY$
And here is the error message I get when I try to add the function:
An error has occurred:
13:13:54: Error: ERROR: return type mismatch in function declared to
return real DETAIL: Function's final statement must be SELECT or
INSERT/UPDATE/DELETE RETURNING. CONTEXT: SQL function
"func_net_exposure"
Any clue on how to solve this error?
The system thinks the function's language is SQL and therefore expects the last statement to be a SELECT or ... RETURNING. The language should be PL/pgSQL. Add a language specification like:
CREATE OR REPLACE FUNCTION data.func_net_exposure(id_fund_arg text)
RETURNS real AS
$BODY$
...
$BODY$
LANGUAGE PLpgSQL;

PostgreSQL: No function matches the given name and argument types

I have the following procedure:
DROP FUNCTION presAdress();
CREATE FUNCTION presadress() RETURNS VARCHAR(100) AS $$
DECLARE studioName text;
BEGIN
RETURN (
SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (
SELECT presC#
FROM Studio
WHERE name = studioName)
);
END;
$$ LANGUAGE plpgsql;
I try to run the procedure:
select presadress('Paramount');
But I get the following error message:
ERROR: function presadress(text) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 294
I suspect that this is because there is some kind of error regarding the in parameters of the procedure, but I have been unable to find a solution.
Use a function parameter, like #Gordon demonstrates, but you don't need plpgsql for this at all. And the query can simplified (shorter, faster):
CREATE FUNCTION presadress(_studioname text)
RETURNS text AS
$$
SELECT m.address
FROM studio s
JOIN movieexec m ON m.cert# = s.presc#
WHERE s.name = _studioname
$$ LANGUAGE sql STABLE;
Function volatility can be STABLE.
Related:
How do IMMUTABLE, STABLE and VOLATILE keywords effect behaviour of function?
Difference between language sql and language plpgsql in PostgreSQL functions
PostgreSQL Stored Procedure Performance
I think you want a declaration more like this:
CREATE FUNCTION presadress (v_studioName text)
RETURNS VARCHAR(100) AS $$
BEGIN
RETURN(SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (SELECT presC#
FROM Studio
WHERE name = v_studioName)
);
END;
$$ LANGUAGE plpgsql;

Concatenate variable into dynamic SELECT statement in PL/pgSQL

I want to use a variable in a dynamic SELECT statement (that is in an EXECUTE statement) like this:
CREATE OR REPLACE FUNCTION get_factor()
RETURNS TABLE(factor numeric) AS
$BODY$
DECLARE
_query character varying;
_some_condition integer := 50;
_result decimal;
BEGIN
_query := 'SELECT factors.factor_material FROM factors
WHERE factors.condition = _some_condition;';
EXECUTE _query INTO _result;
RETURN QUERY SELECT _result;
END;
I have a variable _some_condition integer := 50; and I want to concatenate its value into the SELECT statement (...WHERE factors.condition = _some_condition;) however this is giving me a "column does no exist" error:
ERROR: column "_some_condition" does not exist
LINE 1: ...erial WHERE factors.city_id = _some_cond...
^
CONTEXT: PL/pgSQL function get_factor() line 12 at EXECUTE statement
Why am I getting this error and how to fix this? Keep in mind I have to use a dynamic SELECT statement.
Since you are trying to pass a value (which is not the same as a literal, btw), all you need is the USING clause of the plpgsql EXECUTE command, like #Craig commented.
While being at it, simplify your function with RETURN QUERY EXECUTE:
CREATE OR REPLACE FUNCTION get_factor()
RETURNS TABLE(factor numeric) AS
$func$
DECLARE
_some_condition integer := 50;
BEGIN
RETURN QUERY EXECUTE
'SELECT factor_material
FROM factors
WHERE condition = $1'
USING _some_condition;
END
$func$ LANGUAGE plpgsql;
Nothing in this example requires dynamic SQL. You could just:
RETURN QUERY
SELECT f.factor_material
FROM factors f
WHERE f.condition = _some_condition;

syntax error at or near create when creating a function

So I am creating a function in PostgreSQL for the first time and I am having a problem with the syntax
CREATE OR REPLACE FUNCTION uni() RETURNS INTEGER AS $$
DECLARE
mviews RECORD;
BEGIN
FOR mviews IN SELECT id,universite_adi FROM proaca.a LOOP
INSERT INTO proaca.universite (id,ad,ulke_id)
VALUES (mviews.id,mviews.universite_adi,1)
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
ERROR: syntax error at or near "create"
Line 2: $BODY$CREATE OR REPLACE FUNCTION uni() RETURNS INTEGER AS $$
The syntax error was solved by a_horse in the comments:
missing a ; to terminate the INSERT statement.
You don't need that loop. Just plain sql
create or replace function uni()
returns integer as $$
insert into proaca.universite (id, ad, ulke_id)
select id, universite_adi, 1
from proaca.a
returning 1
;
$$ language sql;