Procedure returns query table in Postgresql - sql

I try to create a procedure that return a query table from Postgresql, but I'm stuck at creating the procedure
CREATE OR REPLACE PROCEDURE "sap_data"."get_emp_number"(dep VARCHAR)
RETURNS TEMP TABLE (
emp_id VARCHAR,
department VARCHAR)
AS $BODY$
BEGIN
RETURN QUERY SELECT
emp_id,
department
FROM
emp_data
WHERE
department = dep
END;$BODY$
LANGUAGE plpgsql
When I save this procedure, this error occurs:
ERROR: syntax error at or near "TABLE"
LINE 2: RETURNS TABLE (
I want to return this as a query so I can query this table using parameter to filter it.

There are several errors in the creation.
It is function.
Functions can't return a temporal table.
You should prefix columns with a table name in RETURN QUERY SELECT.
The semicolon before END is needed.
it might look something like this:
CREATE OR REPLACE Function "get_emp_number"(dep VARCHAR)
RETURNS TABLE (
emp_id VARCHAR,
department VARCHAR)
AS $BODY$
BEGIN
RETURN QUERY SELECT
emp_data.emp_id,
emp_data.department
FROM
emp_data
WHERE
emp_data.department = dep;
END;
$BODY$
LANGUAGE plpgsql

Related

Postgresql, function returns query by calling another function

Postgresql 12. Want a function to return query by calling another function but don't know how to call.
create or replace function getFromA()
returns table(_id bigint, _name varchar) as $$
begin
RETURN QUERY SELECT id, name from groups;
end; $$ language plpgsql;
create or replace function getFromB()
returns table(_id bigint, _name varchar) as $$
begin
return query select getFromA();
end; $$ language plpgsql;
select getFromB();
gets error:
SQL Error [42804]: ERROR: structure of query does not match function result type
Detail: Returned type record does not match expected type bigint in column 1.
Where: PL/pgSQL function getfromb() line 3 at RETURN QUERY
How to fix this?
The problem is in getFromB():
return query select getFromA();
Unlike some other databases, Postgres allows set-returning functions directly in the select clause. This works, but can be tricky: this returns a set, hence not the expected structure.
You would need to select ... from getFromA() instead: this way it returns the proper data structure.
create or replace function getFromB()
returns table(_id bigint, _name varchar) as $$
begin
return query select * from getFromA();
end; $$ language plpgsql;
Demo on DB Fiddle

How to create a procedure that returns a set of rows from a table in postgreSQL

How do i create a Procedure that returns a set of rows from a table?
or is it even possible to return a tabular result set with procedure.
I tried adding returns setof students like you do in a function and table(id int) but it doesn't work.
SAMPLE CODE:
CREATE OR REPLACE PROCEDURE getStudents()
LANGUAGE plpgsql
AS $$
BEGIN
SELECT * FROM STUDENTS
COMMIT;
RETURN;
END;
$$;
I can call it but it says query has no destination for result data
Procedures aren't meant to return data, that's what functions are for.
You can use a plain SQL function for this, no need for PL/pgSQL:
CREATE OR REPLACE funct get_students()
returns setof student
LANGUAGE sqö
AS $$
select *
from students;
$$;
Then use it like a table:
select *
from get_students();
There is also no need for a commit.
Try to use function instead of procedure. I usually use this.
You need to create a ctype for fetching the data.
Put whatever columns you have to fetch from STUDENTS table.
Syntax is as follows:
CREATE TYPE students_data_ctype AS
(
column_1 int4,
column_2 varchar(100),
column_3 varchar(500)
)
Then create a funcction :
CREATE
OR
REPLACE
FUNCTION PUBLIC.getStudents
()
RETURNS SETOF students_data_ctype AS $BODY$ DECLARE res
students_data_ctype;
BEGIN
FOR res IN
SELECT
column_1,
column_2,
column_3
FROM
STUDENTS
LOOP RETURN NEXT res;
END LOOP;
END
; $BODY$ LANGUAGE 'plpgsql'
GO
Function call :
Select * FROM getStudents()
Taddaaa! You will get your data.

PostgreSQL - Creating a loop with a SELECT

I have these Stored Procedure logic to be implemented:
CREATE OR REPLACE FUNCTION get_array(arraynumbers integer[])
RETURNS TABLE (name text) AS $$
DECLARE
index integer := 0
BEGIN
FOREACH index < arraynumbers
LOOP
SELECT e.name as empname FROM employee as e
WHERE e.id = arraynumbers[index]
LIMIT 1
name.push(empname)
ENDLOOP;
RETURN name;
END;
$$
LANGUAGE PLPGSQL;
The goal is to loop based on the length of the array parameter and every index of the parameter will be the condition for retrieving a record and push it to a variable and return the variable as table.
What is the correct way of writing it in PostgreSQL Stored Procedure?
It's unclear to me what exactly the result should be, but as far as I can tell, you don't need a loop or a PL/pgSQL function:
CREATE OR REPLACE FUNCTION get_array(arraynumbers integer[])
RETURNS TABLE (name text)
AS
$$
SELECT e.name
FROM employee as e
WHERE e.id = any(arraynumbers);
$$
LANGUAGE SQL;
This will return one row for each id in arraynumbers that exist in the employee table. As the function is declared as returns table there is no need to collect the values into a single variable (which you didn't declare to begin with)

Function with SQL query has no destination for result data

I am trying to create a function that returns a SELECTed resultset.
When I call my postgres function like this select * from tst_dates_func() I get an error as shown below:
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 "tst_dates_func" line 3 at SQL statement
********** Error **********
ERROR: query has no destination for result data
SQL state: 42601
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Context: PL/pgSQL function "tst_dates_func" line 3 at SQL statement
Here is the function I created:
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
END;
$BODY$
LANGUAGE plpgsql;
I am not sure why I am getting the above error. I would like to run select * from tst_dates_func();
and get data back. Or further join the result set if needed. What is the problem here?
Do it as plain SQL
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
$BODY$
LANGUAGE sql;
If you really need plpgsql use return query
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
perform SELECT dblink_connect('remote_db');
return query
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
END;
$BODY$
LANGUAGE plpgsql;
In PLPGSQL - use RETURN QUERY
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
RETURN QUERY (select a.date_value, a.date_id, a.date_desc from dates_tbl a);
END;
$BODY$
LANGUAGE plpgsql;
I couldn't do it as plain SQL as I needed to enter some data into a database for further processing and wanted to create a variable. Or at least I did not figure out the correct syntax for that. And the accepted answer had code I did not need, such as connecting to the database, as I ran this from inside pgAdmin with a connection setup already. I also had to drop the function when I made edits to it.
I was using this for inserting a geometry for intersection. A different use case and example could help someone else. This also shows how to then view this data and use it just like a table.
-- Get a geojson shape inside of postgres for further use
DROP FUNCTION fun();
CREATE OR REPLACE FUNCTION fun()
RETURNS TABLE (geometry geometry) AS
$BODY$
DECLARE geojson TEXT;
BEGIN
geojson := '{
"type":"Polygon",
"coordinates":[[[-90.9516399548092,39.8942337977775],[-90.9513913202472,39.8936939306154],[-90.9522805177147,39.8937108246505],[-90.9549542293894,39.8937616571416],[-90.954948768846,39.8945506794343],[-90.9531755591848,39.894492766522],[-90.9531770788457,39.8942868819087],[-90.9516399548092,39.8942337977775]]],
"crs":{"type":"name","properties":{"name":"EPSG:4326"}},
}';
return query (SELECT ST_GeomFromGeoJSON(geojson) AS geometry);
END;
$BODY$
LANGUAGE plpgsql;
-- View test insert
SELECT * FROM fun()

Return a query from a function?

I am using PostgreSQL 8.4 and I want to create a function that returns a query with many rows.
The following function does not work:
create function get_names(varchar) returns setof record AS $$
declare
tname alias for $1;
res setof record;
begin
select * into res from mytable where name = tname;
return res;
end;
$$ LANGUAGE plpgsql;
The type record only allows single row.
How to return an entire query? I want to use functions as query templates.
CREATE OR REPLACE FUNCTION get_names(_tname varchar)
RETURNS TABLE (col_a integer, col_b text) AS
$func$
BEGIN
RETURN QUERY
SELECT t.col_a, t.col_b -- must match RETURNS TABLE
FROM mytable t
WHERE t.name = _tname;
END
$func$ LANGUAGE plpgsql;
Call like this:
SELECT * FROM get_names('name')
Major points:
Use RETURNS TABLE, so you don't have to provide a list of column names with every call.
Use RETURN QUERY, much simpler.
Table-qualify column names to avoid naming conflicts with identically named OUT parameters (including columns declared with RETURNS TABLE).
Use a named variable instead of ALIAS. Simpler, doing the same, and it's the preferred way.
A simple function like this could also be written in LANGUAGE sql:
CREATE OR REPLACE FUNCTION get_names(_tname varchar)
RETURNS TABLE (col_a integer, col_b text) AS
$func$
SELECT t.col_a, t.col_b --, more columns - must match RETURNS above
FROM mytable t
WHERE t.name = $1;
$func$ LANGUAGE sql;