If two stored functions have the same name,name and types of arguments, but different return type, will they be considered as two distinct functions?
It is an error to try to create a function with the same name and arguments
create function f() returns int as $$
select 1;
$$ language sql;
CREATE FUNCTION
create function f() returns text as $$
select '1';
$$ language sql;
ERROR: function "f" already exists with same argument types
Related
I've created a function like this.
create or replace function pesquisar_imoveis_residenciais_venda()
returns table(preco decimal)
as $$
begin
select preco from casa_venda;
end; $$
language 'plpgsql';
When I call it
select pesquisar_imoveis_residenciais_venda()
I get the column reference preco is ambiguous.
I've visited some related question. But they are too difficult to follow, very complex functions.
The columns defined in the RETURNS QUERY clause are variables in the PL/pgSQL function body, so the ambiguity is between the variable preco and the table column of the same name. You need to qualify the reference with either the table name or the function name to disambiguate that.
But your function definition has other issues. I think you want:
create or replace function pesquisar_imoveis_residenciais_venda()
returns table(preco decimal)
as $$
begin
return query select cv.preco from casa_venda cv;
end; $$
language 'plpgsql';
select *
from pesquisar_imoveis_residenciais_venda();
Here is a db<>fiddle.
You can override the plpgsql.variable_conflict configuration parameter:
create or replace function pesquisar_imoveis_residenciais_venda()
returns table(preco decimal)
as $$
#variable_conflict use_column
begin
select preco from casa_venda;
end; $$
language 'plpgsql';
This assumes you want to use the column value and not the variable value. If that's not the case then specify #variable_conflict use_variable instead.
See the docs for further details.
it means column name Preco in table casa_venda is not exist or exist more than 1 time.
For the first time I'm trying to create function in PostgreSQL:
This function must accept parameter with array type. Array contains sequence of biginteger values. Size of array not arbitrary, but known in advance.
create function get_total (cols ARRAY) returns biginteger AS
$BODY$
begin
// Some logics
end;
$BODY$
Usage in query
select
stats.value1,
stats.value2,
get_total(array_agg(ARRAY[stats.value2, stats.value1]))
from stats;
It returns error:
type cols[] does not exist
SQL state: 42704
When I run in Select only array_agg(ARRAY[stats.value2, stats.value1]), I see, that array created successfully. So the problem in function parameter.
What am I doing wrong?
You have to declare the parameter as bigint[], which reads an array of type bigint e.g.
CREATE OR REPLACE FUNCTION get_total (bigint[])
RETURNS bigint AS
$$
BEGIN
-- your fancy logic goes here
END;
$$ LANGUAGE plpgsql
Function call:
SELECT get_total(ARRAY[1111111111111,1111111111111]);
An elegant alternative is to declare the parameter as VARIADIC. Doing so you may call your function with multiple parameters,e.g.:
CREATE OR REPLACE FUNCTION get_total (VARIADIC bigint[])
RETURNS bigint AS
$$
BEGIN
-- your fancy logic goes here
END;
$$ LANGUAGE plpgsql;
Function call:
SELECT get_total(1111111111111,1111111111111,1111111111111);
Demo: db<>fiddle
The syntax cols ARRAY is the same as cols[] and means “an array with elements of type cols”. That's why you get that error message for the function definition.
If the element type is bigint, the function should be defined as
CREATE FUNCTION get_total(cols bigint ARRAY) RETURNS bigint
Just reading this answer about using a new type to return multiple fields in PostgreSQL.
So we can do this.
CREATE TYPE my_type AS (a text, b text, c text)
CREATE OR REPLACE FUNCTION get()
RETURNS my_type AS
$$
DECLARE
result_record my_type;
BEGIN
SELECT r[1], r[2], r[3]
INTO result_record.a, result_record.b, result_record.c
FROM regexp_split_to_array('a.b.c', '\.') r;
RETURN result_record;
END
$$ LANGUAGE plpgsql;
I was wondering if we can do the same thing without declaring the custom type in the function and/or using the language sql instead of plpgsql?
Ok, so this question probably shouldn't have been asked, because the answer is almost intuitive.
CREATE OR REPLACE FUNCTION get2()
RETURNS my_type AS
$$
SELECT r[1] AS a, r[2] AS b, r[3] AS c
FROM regexp_split_to_array('a.b.c', '\.') r;
$$ LANGUAGE sql;
Or using just SQL
select cast((r[1], r[2], r[3]) as my_type) from regexp_split_to_array('a.b.c', '\.') r;
I've got a postgresql stored procedure, which is returning an integer.
When I call that function, the result is returned with the function name as column name.
For example the name of the function is: "add-person". The column name, when invoking the function, is "add-person".
Is there a way to make the database return the integer with a self-choosen column name? For example "id"?
I think it is pretty easy, but I currently miss the forests for the trees..
Edit:
What i'd missed to tell, is that the return value is a variable, like so:
CREATE OR REPLACE FUNCTION "scheme"."add-person"(arggivenname character varying, argfamilyname character varying) RETURNS integer AS
$BODY$
DECLARE
varResponse integer;
BEGIN
-- Operations before
INSERT INTO "scheme"."table"
(
given_name,
family_name
)
VALUES
(
arggivenname,
argfamilyname
)
RETURNING
"id"
INTO
varResponse;
-- Operations after
RETURN varResponse;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
You can us the AS statement for that. That means:
Select add-person() AS yourcolumnname
To have a named column from a function it is necessary to create a type and return that type from the function
create type mytype as (mycolumn integer);
create or replace function ri()
returns mytype as $$
select 1;
$$ language sql;
select * from ri();
mycolumn
----------
1
Edit
Or much simpler without the type creation as in #pozs comment:
create or replace function ri(out mycolumn integer)
as $$
select 1;
$$ language sql;
I am trying to write a PL/pgSQL function with optional arguments. It performs a query based on a filtered set of records (if specified), otherwise performs a query on the entire data set in a table.
For example (PSEUDO CODE):
CREATE OR REPLACE FUNCTION foofunc(param1 integer, param2 date, param2 date, optional_list_of_ids=[]) RETURNS SETOF RECORD AS $$
IF len(optional_list_of_ids) > 0 THEN
RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2 AND id in optional_list_of_ids);
ELSE
RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2);
ENDIF
$$ LANGUAGE SQL;
What would be the correct way to implement this function?
As an aside, I would like to know how I could call such a function in another outer function. This is how I would do it - is it correct, or is there a better way?
CREATE FUNCTION foofuncwrapper(param1 integer, param2 date, param2 date) RETURNS SETOF RECORD AS $$
BEGIN
CREATE TABLE ids AS SELECT id from foobar where id < 100;
RETURN QUERY (SELECT * FROM foofunc(param1, param2, ids));
END
$$ LANGUAGE SQL
Since PostgreSQL 8.4 (which you seem to be running), there are default values for function parameters. If you put your parameter last and provide a default, you can simply omit it from the call:
CREATE OR REPLACE FUNCTION foofunc(_param1 integer
, _param2 date
, _ids int[] DEFAULT '{}')
RETURNS SETOF foobar -- declare return type!
LANGUAGE plpgsql AS
$func$
BEGIN -- required for plpgsql
IF _ids <> '{}'::int[] THEN -- exclude empty array and NULL
RETURN QUERY
SELECT *
FROM foobar
WHERE f1 = _param1
AND f2 = _param2
AND id = ANY(_ids); -- "IN" is not proper syntax for arrays
ELSE
RETURN QUERY
SELECT *
FROM foobar
WHERE f1 = _param1
AND f2 = _param2;
END IF;
END -- required for plpgsql
$func$;
Major points:
The keyword DEFAULT is used to declare parameter defaults. Short alternative: =.
I removed the redundant param1 from the messy example.
Since you return SELECT * FROM foobar, declare the return type as RETURNS SETOF foobar instead of RETURNS SETOF record. The latter form with anonymous records is very unwieldy, you'd have to provide a column definition list with every call.
I use an array of integer (int[]) as function parameter. Adapted the IF expression and the WHERE clause accordingly.
IF statements are not available in plain SQL. Has to be LANGUAGE plpgsql for that.
Call with or without _ids:
SELECT * FROM foofunc(1, '2012-1-1'::date);
Effectively the same:
SELECT * FROM foofunc(1, '2012-1-1'::date, '{}'::int[]);
You have to make sure the call is unambiguous. If you have another function of the same name and two parameters, Postgres might not know which to pick. Explicit casting (like I demonstrate) narrows it down. Else, untyped string literals work, too, but being explicit never hurts.
Call from within another function:
CREATE FUNCTION foofuncwrapper(_param1 integer, _param2 date)
RETURNS SETOF foobar
LANGUAGE plgpsql AS
$func$
DECLARE
_ids int[] := '{1,2,3}';
BEGIN
-- whatever
RETURN QUERY
SELECT * FROM foofunc(_param1, _param2, _ids);
END
$func$;
Elaborating on Frank's answer on this thread:
The VARIADIC agument doesn't have to be the only argument, only the last one.
You can use VARIADIC for functions that may take zero variadic arguments, it's just a little fiddlier in that it requires a different calling style for zero args. You can provide a wrapper function to hide the ugliness. Given an initial varardic function definition like:
CREATE OR REPLACE FUNCTION foofunc(param1 integer, param2 date, param2 date, optional_list_of_ids VARIADIC integer[]) RETURNS SETOF RECORD AS $$
....
$$ language sql;
For zero args use a wrapper like:
CREATE OR REPLACE FUNCTION foofunc(integer, date, date) RETURNS SETOF RECORD AS $body$
SELECT foofunc($1,$2,$3,VARIADIC ARRAY[]::integer[]);
$body$ LANGUAGE 'sql';
or just call the main func with an empty array like VARIADIC '{}'::integer[] directly. The wrapper is ugly, but it's contained ugliness, so I'd recommend using a wrapper.
Direct calls can be made in variadic form:
SELECT foofunc(1,'2011-01-01','2011-01-01', 1, 2, 3, 4);
... or array call form with array ctor:
SELECT foofunc(1,'2011-01-01','2011-01-01', VARIADIC ARRAY[1,2,3,4]);
... or array text literal form:
SELECT foofunc(1,'2011-01-01','2011-01-01', VARIADIC '{1,2,3,4}'::int[]);
The latter two forms work with empty arrays.
You mean SQL Functions with Variable Numbers of Arguments? If so, use VARIADIC.