Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Disclaimer This might be a more theoretical, unpractical question.
I am trying to replace a plpgsql function by a sql function without changing the behaviour or result type. The function looks like this:
create function f() returns void as
$$
begin
perform some_other_function(my_table.my_column)
from my_table;
end;
$$
language plpgsql volatile;
This function returns void, as I do not care about the results.
As said, I am trying to replace it by a sql function. This function is used in a chain of sql functions, so it might be performance-wise better to have this function also a sql function instead of plpgsql (again, see disclaimer).
The following does not work, because now only the first row of my_table is processed.
create function f() returns void as
$$
select some_other_function(my_table.my_column)
from my_table;
$$
language sql volatile;
Note that function some_other_function also returns a void.
Any other clever ways to try out?
You could use an SQL statement that has to scan the whole table before it can produce the first result row, like
CREATE OR REPLACE FUNCTION f() RETURNS void
LANGUAGE sql STABLE AS
'SELECT count(CASE
WHEN some_other_function(my_table.my_column) IS NULL
THEN 0
END
)::text::void
FROM my_table';
or
CREATE OR REPLACE FUNCTION f() RETURNS void
LANGUAGE sql STABLE AS
'SELECT count(*)::text::void
FROM (
SELECT some_other_function(my_table.my_column)
FROM my_table
) q';
Related
I have a void plsql function:
CREATE OR REPLACE FUNCTION do_something(p_id BIGINT)
RETURNS void
AS $$
BEGIN
insert ....
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
I want to call this function from another plsql function, but inside a query like:
SELECT do_something(m.id)
FROM MyTable m
WHERE m.IsActive;
When I run the sproc i get:
ERROR: query has no destination for result data HINT: If you want to
discard the results of a SELECT, use PERFORM instead.
Is it possible to call a void function as part of a select statement?
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
PERFORM do_something(m.id)
FROM MyTable m
WHERE m.IsActive;
PERFORM is the PL/PgSQL alternative for SELECT for when you want to throw the results away. It cannot be used outside PL/PgSQL. For more information, see the manual.
I am trying to implement a function that returns a table with the same structure as an input table in the parameter, using PL/pgSQL (PostgreSQL 9.3). Basically, I want to update a table, and return a copy of the updated table with plpgsql. I searched around SO and found several related questions (e.g. Return dynamic table with unknown columns from PL/pgSQL function and Table name as a PostgreSQL function parameter), which lead to the following minimal test example:
CREATE OR REPLACE FUNCTION change_val(_lookup_tbl regclass)
RETURNS _lookup_tbl%rowtype AS --problem line
$func$
BEGIN
RETURN QUERY EXECUTE format('UPDATE %s SET val = 2 RETURNING * ; ', _lookup_tbl);
END
$func$ LANGUAGE plpgsql;
But I can't get past giving the correct return type for TABLE or SETOF RECORD in the problem line. According to this answer:
SQL demands to know the return type at call time
But I think the return type (which I intend to borrow from the input table type) is known. Can some one help explain if it is possible to fix the signature of the above PL/pgSQL function?
Note, I need to parametrize the input table and return the update of that table. Alternatives are welcome.
What you have so far looks good. The missing ingredient: polymorphic types.
CREATE OR REPLACE FUNCTION change_val(_tbl_type anyelement)
RETURNS SETOF anyelement -- problem solved
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE format(
'UPDATE %s SET val = 2 RETURNING *;'
, pg_typeof(_tbl_type))
);
END
$func$;
Call (important):
SELECT * FROM change_val(NULL::some_tbl);
db<>fiddle here
Old sqlfiddle
See (last paragraph):
Refactor a PL/pgSQL function to return the output of various SELECT queries
I have a void plsql function:
CREATE OR REPLACE FUNCTION do_something(p_id BIGINT)
RETURNS void
AS $$
BEGIN
insert ....
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
I want to call this function from another plsql function, but inside a query like:
SELECT do_something(m.id)
FROM MyTable m
WHERE m.IsActive;
When I run the sproc i get:
ERROR: query has no destination for result data HINT: If you want to
discard the results of a SELECT, use PERFORM instead.
Is it possible to call a void function as part of a select statement?
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
PERFORM do_something(m.id)
FROM MyTable m
WHERE m.IsActive;
PERFORM is the PL/PgSQL alternative for SELECT for when you want to throw the results away. It cannot be used outside PL/PgSQL. For more information, see the manual.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have function in pl/pgsql in postgresql
ie
CREATE or replace FUNCTION check_checklist_is_finalizedtest(application_id bigint)
RETURNS SETOF record AS
$BODY$
DECLARE
sqlresult record;
val boolean:=false;
BEGIN
for sqlresult in execute IMMEDIATE 'select distinct mda.application_id maid,mda.document_type_id mdoctypeid,
dt.multiple_doc dtmdoc,mda.mandatory_doc_application_id mdocaid,COALESCE(ac.doc_correct,false) doccorrect,
COALESCE((select max(e_certificate_no) from application_document ad
where ad.application_id=mda.application_id and ad.document_id=mda.document_type_id and multiple_doc=true and ad."valid"=''||New||''
),'''||1||''')as no_of_docs,
(select count(*) from application_document ad2
where ad2.application_id=mda.application_id and ad2.document_id=mda.document_type_id and ad2."valid"=''||New||''
)as count_of_record
from mandatory_doc_application mda
inner join document_type dt on(mda.document_type_id=dt.document_id)
left join application_checklist ac on(ac.man_doc_app_id= mda.mandatory_doc_application_id)
where mda.application_id='''||$1||''''
LOOP
IF(sqlresult.no_of_docs::bigint=sqlresult.count_of_record and sqlresult.doccorrect=true) then
val=true;
ELSE
val=false;
END IF;
return next sqlresult;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
When function is called subqueries in select statement are not executed.Hence the result is wrong.Can you help me?
Probably something went wrong translating your query to dynamic SQL. The code in your question is very hard to read, which increases the risk of errors.
This strange expression probably does not what you think it does:
and ad2."valid"=''||New||''
You expect a variable New, but it is not declared and you use a constant string there instead.
Next strange thing: the key word IMMEDIATE - PostgreSQL doesn't support it - so your code cannot be compiled probably.
Questions:
Why do you use a dynamic SQL? There doesn't seem to be need for that.
If you use a dynamic SQL, why you don't use a modern form like
FOR r IN EXECUTE 'SELECT * FROM tab WHERE somecol = $1' USING $1
LOOP ...
But your code would be simpler and faster with plain SQL:
BEGIN
RETURN QUERY SELECT no_of_docs::bigint=count_of_record
AND COALESCE(ac.doc_correct,false) = true
FROM ...;
RETURN;
END;
Remember to only select columns that you actually need to return - not others.
I need to show the Tree_Nodes table data
CREATE OR REPLACE FUNCTION sample()
RETURNS TABLE() AS
$BODY$
BEGIN
select * from "Tree_Nodes";
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION sample()
OWNER TO postgres;
It fails with:
ERROR: query has no destination for result data
Avoid the error and i will get the table column format in all data
To return the result of a SELECT, a pure SQL function is much more suitable:
CREATE OR REPLACE FUNCTION sample()
RETURNS TABLE ( .... ) AS
$BODY$
select * from "Tree_Nodes";
$BODY$
LANGUAGE sql;
Or if you really need PL/pgSQL, you need to use return query (which is clearly documented in the manual)
CREATE OR REPLACE FUNCTION sample()
RETURNS TABLE (....)
AS
$BODY$
BEGIN
return query select * from "Tree_Nodes";
END;
$BODY$
LANGUAGE plpgsql;
But you cannot just specify returns table() you have to also define the structure of the result:
CREATE OR REPLACE FUNCTION sample()
RETURNS TABLE(id integer, some_column text, other_column decimal(10,2), ...)
AS
The exact error you quote is caused by using SELECT without an INTO clause in PL/PgSQL. You must either use SELECT INTO somevariable, use RETURN QUERY, if you want to discard the data, use the PERFORM statement instead of SELECT, as covered by the PL/PgSQL manual.
Once you fix that by using RETURN QUERY SELECT .... you'll find that the function still doesn't work, because RETURNS TABLE() doesn't make sense. You're returning an empty result set. It'll fail, complaining that the statement is returning a result set that doesn't match the function.
It makes no sense to do this anyway, since you can just write it as a trivial SQL function like:
CREATE OR REPLACE FUNCTION sample()
RETURNS SETOF "Tree_Nodes"
AS $$
SELECT * FROM "Tree_Nodes";
$$ LANGUAGE sql;
This function appears to serve no purpose. What are you trying to achieve with it?
(By the way, you should generally avoid SELECT * in production code. List the columns. That way, if you add a column later, things that use the table won't suddenly stop working.)