PostgreSQL: Call a Function More Than Once in FROM Clause - function

How can I call a function which returns records more than once in FROM clause? I understand that I have to specify a 'column definition list' when using a function that returns records. But how can I then use aliases for that function?
Example:
CREATE OR REPLACE FUNCTION foo(which_foo int) RETURNS SETOF RECORD AS
$BODY$BEGIN
IF which_foo=0 THEN
RETURN QUERY EXECUTE 'SELECT 1::int,2::int;';
ELSE
RETURN QUERY EXECUTE 'SELECT 1::int,2::int;';
END IF;
END$BODY$
LANGUAGE plpgsql;
SELECT * FROM foo(0) AS (a int, b int);;
SELECT * FROM foo(1) AS (c int, d int);
SELECT * FROM foo(0) AS (a int, b int), foo(1) AS (c int, d int);
The last select statement will fail with:
ERROR: table name "foo" specified more than once
I want to keep using the column definition list, because the function I want to use in the end has to be as generic as possible.

SELECT f0.*, f1.*
FROM
foo(0) AS f0 (a int, b int),
foo(1) AS f1 (c int, d int);

I understand that I have to specify a 'column definition list' when
using a function that returns records.
No, you do not. I wouldn't operate with anonymous records. Declare the return type, since you already know it:
CREATE OR REPLACE FUNCTION foo(which_foo int)
RETURNS TABLE (a int, b int) AS
$func$
BEGIN
IF which_foo = 0 THEN
RETURN QUERY SELECT 1,2;
ELSE
RETURN QUERY SELECT 1,2;
END IF;
END
$func$ LANGUAGE plpgsql;
And assuming you do not want to combine multiple calls into one row, you should use UNION ALL:
SELECT * FROM foo(0)
UNION ALL
SELECT * FROM foo(1);

Related

Calling table function from procedure (pl sql)

I am having big trouble calling a function that returns a table from my procedure. I believe there is something wrong with my declaration so its not compiling. Here is my code.. the developer underlines with red the SELECT "D_ID" and from table "(IREL_FN (X))"; . And here is my code.
CREATE OR replace PROCEDURE Irrelevant_skata (x NUMBER)
AS
d_id T_ID_TABLE;
BEGIN
DECLARE
TYPE yo_table
IS
TABLE OF YO_TABLE;
YO_TABLE "(IREL_FN (X))"%TYPE;
id NUMBER;
BEGIN
SELECT "D_ID"
INTO yo_table
FROM TABLE "(IREL_FN (X))";
EXCEPTION
WHEN no_data_found THEN
dbms_output.Put_line('NO DATA FOUND');
END;
END irrelevant_skata;
And the function
CREATE OR replace FUNCTION Irel_fn (x IN NUMBER)
RETURN T_ID_TABLE
AS
id T_ID_TABLE;
BEGIN
BEGIN
SELECT Cast(MULTISET(SELECT "id"
FROM "somethingcopy"
WHERE "kati" IN (SELECT "auto"
FROM "ekeino"
WHERE "id" = x)) AS T_ID_TABLE)
INTO id
FROM dual;
RETURN id;
EXCEPTION
WHEN no_data_found THEN
dbms_output.Put_line('null');
END;
END irel_fn;
It's hard to answer without knowing what you're trying to do.
YO_TABLE "(IREL_FN (X))"%TYPE;
This doesn't make any sense. You can't declare a variable to be %type of a function. Looking up at YO_TABLE declaration, you write
DECLARE
TYPE yo_table
IS
TABLE OF YO_TABLE;
Huh? table declaration is table of same variable you're declaring?
And this:
SELECT "D_ID"
INTO yo_table
FROM TABLE "(IREL_FN (X))";
You don't need quotes when casting table, and the x in IREL_FN (X) is a formal parameter, you need to replace it with the actual value what you need to pass
create or replace
PROCEDURE IRRELEVANT_SKATA (INSID IN NUMBER) AS ID T_ID_TABLE ;
BEGIN
DECLARE
YO_TABLE T_ID_TABLE;
BEGIN
select ID
into YO_TABLE
from table(IREL_FN(INSID));
EXCEPTION
WHEN NO_DATA_FOUND THEN dbms_output.put_line('NO DATA FOUND');
END;
END IRRELEVANT_TWEET;
<-----------------------------FUNCTION---------------------------------->
create or replace
FUNCTION IREL_FN ( D_ID IN NUMBER ) RETURN T_ID_TABLE AS
ID T_ID_TABLE;
BEGIN
BEGIN
SELECT CAST(
MULTISET(
SELECT "Id"
FROM "SOMETHINGCOPY"
WHERE "KATI" = (SELECT "EKEINO" FROM "AUTO" WHERE "Id"=D_ID)
INTO ID
FROM DUAL;
return ID;
EXCEPTION
WHEN NO_DATA_FOUND THEN dbms_output.put_line('null');
END;
END IREL_FN;
I hope I helped :)
I am answering to your question marked as duplicate (the problem with exact fetch).
I rewrote your code in the following way, hope it helps. I makes the Irel_fn to be a pipelined function, however you can still write Cast multiset if you like , however you need to use type constructor as well.
create table auto(id number)
this table is instead of your source "AUTO" (so I could compile it).
create or replace type t_id as object (id number);
/
Create or replace type t_id_table is table of t_id;
/
create or replace FUNCTION Irel_fn (x IN NUMBER) RETURN T_ID_TABLE PIPELINED
as
BEGIN
for rec in (select id from auto where id=x)
loop
Pipe row (t_id(rec.id));
end loop;
return;
end;
/
create or replace procedure Irrelevant_skata (insid in NUMBER) is
bob t_id_table;
BEGIN
select t_id(id) bulk collect into bob from table(irel_fn(insid));
END;

PostgreSQL: Getting result of a function in a single column in PostgreSQL

Trying to display the result in the form of table with different columns, but getting all result in a single column.
--My Function
create or replace function test1()
returns table ( "Fname" varchar(20),"Lname" varchar(20),"A-B" bigint,"C-D" bigint,
"E-F" bigint ) as
$body$
begin
return query
SELECT tb."Fname",tb."Lname",count(tb."City"='A-B' OR NULL) AS "A-B",
count(tb."City"='C-D' OR NULL) AS "C-D",
count(tb."City"='E-F' OR NULL) AS "E-F"
FROM "Table1" tb
WHERE tb."City" in ('A-B','C-D','E-F')
GROUP BY 1,2
ORDER BY 1,2;
end
$body$
language plpgsql;
In instead of
select test1()
do
select * from test1()
You need no plgpsql for this. This is just a plain query.
But supposing you just want to test it: How do you call the function?
For table returning functions you do: select * from f1();.
For functions returning one value you do select f1();.

Return multiple rows from plpgsql function

I have the below function:
CREATE OR REPLACE FUNCTION function1() RETURNS TABLE(foo1 VARCHAR, foo2 VARCHAR) AS $$
BEGIN
RETURN QUERY SELECT e.col1, e.col2 FROM my_table e;
END;
$$ LANGUAGE plpgsql;
It returns something like this:
function1
record
|--------------|
(a,b)
(c,d)
But I'm expecting a result analog to a query like this:
SELECT e.col1, e.col2 FROM my_table e;
col1 col2
|-----|-----|
a b
c d
Because I want to execute the function a get the separates columns values in a java resultSet and iterate accros them. Thanks!
You need to do
select * from function1();

how to combine two sql statements into a function

I am trying to combine the following two sql statements in my application code into a function in postgresql, but I'm having some trouble.
Here are the two sql queries I'd like to combine:
UPDATE userrange f
SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
WHERE f.uservalue IN(
SELECT a.uservalue FROM userrange a WHERE UsedYesNo=false Order By id ASC Limit 1)
RETURNING a.uservalue;
The results from the above statement are used in this query:
INSERT INTO widget
VALUES(DEFAULT, uservalue, 'test','123456778',1,"testservername", now(), Null)
So far, I've built function that just does the first update statement, like so:
CREATE or REPlACE FUNCTION create_widget(IN user_id integer, IN password character varying DEFAULT NULL::character varying)
RETURNS TABLE(uservalue integer) AS
$BODY$
BEGIN
RETURN QUERY
UPDATE userrange f SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
WHERE f.uservalue IN(
SELECT a.uservalue FROM userrange a WHERE UsedYesNo=false Order By id ASC Limit 1)
RETURNING a.uservalue;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
It compiles but when I execute it, it fails with the error:
ERROR: missing FROM-clause entry for table "a" LINE 4: RETURNING a.uservalue
I'm just googling this error to see how I can fix it... but could I just create a variable
called uservalue in a DECLARE section and use it in the secondary query? Or can i combine the sql into one
thanks.
If you can forego the function and you have PostgreSQL 9.2+, you can do the update and insert in a single query. It should be straightforward to port this to a function if necessary.
WITH f AS (
UPDATE userrange f
SET UsedYesNo = true, user_id=user_id, updateddatetime=now()
WHERE UsedYesNo IS FALSE
RETURNING f.uservalue)
INSERT INTO widget (<column list>)
SELECT f.uservalue, 'test','123456778',1,"testservername", now(), NULL
FROM f;
-- [edit: added function]
-- Note: the following function is untested
CREATE OR REPLACE FUNCTION create_widget(IN p_user_id INTEGER, IN p_password VARCHAR DEFAULT NULL::VARCHAR)
RETURNS TABLE(uservalue integer) AS
$BODY$
BEGIN
RETURN QUERY
WITH f AS (
UPDATE userrange f
SET UsedYesNo = true,
user_id = p_user_id,
updateddatetime = now()
WHERE UsedYesNo IS FALSE
RETURNING f.uservalue)
INSERT INTO widget (<column_list>)
/* Omit the DEFAULT, by not including it in the column list above,
* the DEFAULT already defined on the column will be used.
*/
SELECT f.uservalue, 'test','123456778',1,"testservername", now(), NULL
FROM f;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

Select from mysql stored procedure

Since this can not be done like :
select * from (call my_stored_procedure(params));
Is there any alternative for the above statement ?
A procedure could return multiple result sets, each with its own schema. It's not suitable for using in a SELECT statement.
User-defined function could be an option. Here's an example:
CREATE FUNCTION CubicVolume
-- Input dimensions in centimeters
(#CubeLength decimal(4,1), #CubeWidth decimal(4,1),#CubeHeight decimal(4,1) )
RETURNS decimal(12,3) -- Cubic Centimeters.
AS
BEGIN
RETURN ( #CubeLength * #CubeWidth * #CubeHeight )
END
more on this link : http://msdn.microsoft.com/en-us/library/aa175085%28SQL.80%29.aspx
Create a temporary table variable and insert sp values into it, like :
Declare #t table
(
--column numbers will be equals to the numbers return by SP
)
Insert Into #t
call my_stored_procedure(params)
Select * From #t