Below is one function which has one query ,
Now I want to convert into dynamic query. I want one table name parameter so query return data from multiple tables.
please help me in this I am new in PostgreSQL , Thanks in Advance !
create or replace function GetEmployees()
returns setof weather as
'select * from weather;'
language 'sql';
This is basic PL/PgSQL. Use PL/PgSQL's EXECUTE .. USING statement and format function with the %I format-specifier.
create or replace function get_sometable(tablename regclass)
returns setof whatever_type as
BEGIN
RETURN QUERY EXECUTE format('select * from %I";', tablename);
END;
language 'plpgsql';
This will only work if all tablenames you might pass return compatible result types, as occurs with partitioning. Otherwise you'll have to return SETOF RECORD and then pass the table layout in the function invocation. See the documentation for a discussion of RECORD and SETOF RECORD.
Look into RETURNS TABLE as another convenient alternative for when the table types aren't compatible but you can still return a compatible subset via a suitable SELECT list.
If you're doing table partitioning, you should really do it as the PostgreSQL documentation on table partitioning advises, using table inheritance and triggers.
(Elaborating on Convert SQL Server stored procedure into PostgreSQL stored procedure)
Related
CREATE OR REPLACE FUNCTION "public"."cross_insert"("p_name" varchar, "p_detail" varchar)
RETURNS SETOF "pg_catalog"."varchar" AS $BODY$
BEGIN
SELECT * FROM public.dblink(
'
host=10.10.10.53
port=5432
user=sassuperuser
password=password10
dbname=blog2
',
'
SELECT * FROM public.funct_insert2(
'''||p_name||''',
'''||p_detail||'''
);
'
);
RETURN query
SELECT ('SUKSES')::character varying;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000
Your code is little bit messy. Try start with reading documentation to PLpgSQL. There are three issues:
PL/pgSQL doesn't allow implicit throwing result of any query. You should to iterate over result (FOR IN SELECT) or you have to save result to variable (SELECT INTO). If you want to do it, then you should to use PERFORM command. So you query should to look like:
PERFORM public.dblink(' .....');
There is not any sense why your function is declared like RETURNS SETOF varchar. Then you have to use RETURN QUERY SELECT 'success'. It is absolutely useless. There is relatively high overhead of this functionality. This should be classic scalar function that returns text or better, that returns void type. The exception is raised on error. So you don't need to returns anything.
Second, don't do this - PostgreSQL has FDW interface. You can use foreign table instead. It will be faster and safer.
A novice when it comes to stored procedures/functions. I have searched Google, Stackoverflow, and Youtube and are finding all sorts of examples that are convoluted, some not in English.
I'm trying to understand the basic syntax for a stored function to return a table in Postgresql. In MySql this is elementary but I can't seem to wrap my head around the syntax for Postgresql I have the SQL statement I need to return the rows I want (table), as seen below. I have tried the following code but it doesn't work. Help is much appreciated, thanks in advance.
CREATE OR REPLACE FUNCTION Getcurrent()
RETURNS table AS $schedule$
$BODY$ BEGIN
SELECT *
FROM archived_table
WHERE table_id>=ALL(SELECT table_id FROM archived_table);
RETURN schedule;
END;$BODY$
LANGUAGE plpgsql;
********** Error **********
ERROR: syntax error at or near "AS"
LINE 2: RETURNS table AS $schedule$
^
This is the error message.
I have referenced the following link and have had no luck with this.https://www.postgresql.org/docs/9.1/static/sql-createfunction.html
Im using pgAdminIII, in the public schema, on my company's server.
The desired results is to have the table returned once the function is called.
RETURNS TABLE is not complete, hence the error message.
You can use the RETURNS SETOF <table_name> form, if you intend to return all columns of a table.
Otherwise, you'll need to mention every output column by name and type, with either RETURNS TABLE:
RETURNS TABLE (
col_alias_1 INT,
col_alias_2 TEXT,
col_alias_3 <some_other_type>,
...
)
Or with OUT parameters + RETURNS SETOF RECORD to indicate that you'll (possibly) return multiple rows at once.
Also, if your operation is as simple as a few SQL statements, use LANGUAGE SQL instead:
CREATE OR REPLACE FUNCTION Getcurrent()
RETURNS SETOF archived_table
LANGUAGE SQL
AS $BODY$
SELECT *
FROM archived_table
WHERE table_id>=ALL(SELECT table_id FROM archived_table);
$BODY$;
I've got a function to return relevant position of an array matching given value like below:
CREATE OR REPLACE FUNCTION get_index(needle ANYELEMENT, haystack ANYARRAY)
RETURNS TABLE (i_position int)
AS $$
SELECT
i+i_step AS i_position
FROM (VALUES(1),(2)) steps(i_step),
generate_series(array_lower($2,1), array_upper($2,1)) AS i
WHERE $2[i] = $1
$$ LANGUAGE SQL STABLE;
Instead of passing a single value to the function, I want to pass a table name, as one column of the table would be used to do the value comparison (WHERE $2[i] = $1 ), instead of a single value passed to the function. However, it doesn't seem like the function support SQL using argument as table name.
I'm wondering if there's alternative. I'd like to use SQL function instead of PLPGSQL, for the sake of performance. As our table is huge.
I'd like to achieve something like below:
CREATE OR REPLACE FUNCTION get_index(tbl ANYELEMENT, haystack ANYARRAY)
RETURNS TABLE (i_position int)
AS $$
SELECT
i+i_step AS i_position
FROM (VALUES(1),(2)) steps(i_step),
generate_series(array_lower($2,1), array_upper($2,1)) AS i,
$1
WHERE $2[i] = $1.col1
$$ LANGUAGE SQL STABLE;
It is not possible in SQL function - It doesn't support dynamic sql. You have to use PLpgSQL - EXECUTE statement.
SQL function is faster than PLpgSQL only when inlining is successful. When it isn't successful, and SQL function should be evaluated, then PLpgSQL should not be slower. When body of SQL function contains SRF functions like generate_series, then inlining is not effective.
I would like to execute a SQL statement based on a string. I have created the SQL statement through a function which returns a string. Can anybody explain how I can execute the statement that is returned? I know that you can't do it in plain SQL, so I was thinking about putting it in a function. The only issue is that the columns in the statement aren't always the same, so I don't know which data types to use for the columns. I'm using Postgres 9.1.0.
For example, suppose the SQL string returned from my function the is:
Select open, closed, discarded from abc
But, it can also be:
Select open from abc
Or
Select open, closed from abc
How can I execute any of these strings, so that the results would be returned as a table with only the columns listed in the statement?
Edit: the function is written in PL/pgSQL. And the results will be used for reporting where they don't want to see columns that have no values. So the function that I wrote returns the names of all columns that have values and then add it to the SQL statement.
Thanks for your help!
I don't think you can return the rows directly from a function, because its return type would be unknown. Even if you specified the return type as RECORD, you'd have to list the returned columns at call time. Based on Wayne Conrad's idea, you could do this:
CREATE FUNCTION my_create(cmd TEXT) RETURNS VOID AS $$
BEGIN
EXECUTE 'CREATE TEMPORARY TABLE temp_result AS ' || cmd;
END;
$$ VOLATILE LANGUAGE plpgsql;
Then use the function like this:
BEGIN;
SELECT my_create(...);
SELECT * FROM temp_result;
ROLLBACK; -- or COMMIT
I am trying to write a procedure (function) in Postgres 9.1 to just select all data from a view and return it (all columns) so our application can use it. The intent is to have the application make a call to the procedure whenever it wants the data. My problem is that I cannot seem to get the syntax right to have it return any data. I have written procedures in MySQL, SQL Server and Oracle but never in postgres and it is quite different. Once it works is the best way to call it to just use select "function-name"? Any help would be appreciated.
CREATE OR REPLACE FUNCTION fg.get_flight_times()
RETURNS setof record AS
$BODY$
declare times record;
begin
select * into times from fg.fn_dy_dest_dep_arr;
return;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION fg.get_flight_times()
OWNER TO jason;
GRANT EXECUTE ON FUNCTION fg.get_flight_times() TO fltrakr;
Inside a PL/pgSQL function you need to use RETURN NEXT or RETURN QUERY as documented in the manual:
http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#AEN54092
User RETURNS setof record is no longer necessary in 9.1, using returns table is a lot easier. If you only want to return the result of SELECT statement, you can use SQL as well, which makes the function even easier:
CREATE OR REPLACE FUNCTION fg.get_flight_times()
RETURNS table (col1 integer, col2 text, col3 text)
$BODY$
select col1, col2, col3 from fg.fn_dy_dest_dep_arr;
$BODY$
LANGUAGE sql
VOLATILE
COST 100;
Note that in this case, you have to specify the column definition returned by your function at creation time. With that version you just use:
select * from fg.get_flight_times();
When using returns setof record you don't need to specify the columns at creation time, but you will be forced to do so when selecting from the function (which I find more complicated, as this needs to be done everytime the function is used):
CREATE OR REPLACE FUNCTION fg.get_flight_times()
RETURNS setof record
$BODY$
select * from fg.fn_dy_dest_dep_arr;
$BODY$
LANGUAGE sql
VOLATILE
COST 100;
And this is used like this:
select *
from fg.get_flight_times() f(col1 integer, col2 text, col3 text);
Much more complicated in my opinion (because the caller needs to know the structure and datatypes of the columns)
Do read the manual, everything I have written here is documented there as well (I know it only because I have already read the manual...)