is it possible to execute a storep procedure inside select query ?
select e.Name, dbo.get_sth e.Id
from emp e
I get the error
Incorrect syntax near 'e.Id'
No. But you can execute a function inside a select statement. So recreate your Stored Procedure as a function and this should work.
It will be called for every row so be careful of performance if returning many rows.
Related
I have created a procedure to generate temp table using colpivot https://github.com/hnsl/colpivot
and saving the result into a physical table as below in PGSQL
create or replace procedure create_report_table()
language plpgsql
as $$
begin
drop table if exists reports;
select colpivot('_report',
'select
u.username,
c.shortname as course_short_name,
to_timestamp(cp.timecompleted)::date as completed
FROM mdl_course_completions AS cp
JOIN mdl_course AS c ON cp.course = c.id
JOIN mdl_user AS u ON cp.userid = u.id
WHERE c.enablecompletion = 1
ORDER BY u.username' ,array['username'], array['course_short_name'], '#.completed', null);
create table reports as (SELECT * FROM _report);
commit;
end; $$
colpivot function , drop table , delete table works really fine in isolation. but when I create the procedure as above, and call the procedure to execute, this throws an error Query has no result in destination data
Is there any way I can use colpivot in collaboration with several queries as I am currently trying ?
Use PERFORM instead of SELECT. That will execute the statement, without the need to keep the result somewhere. This is what the manual says:
Sometimes it is useful to evaluate an expression or SELECT query but discard the result, for example when calling a function that has
side-effects but no useful result value. To do this in PL/pgSQL, use
the PERFORM statement
As a follow-up to this question:
How to "PERFORM" CTE queries in PL/pgSQL?
I try:
perform (with test_as_cte as(select * from myTable) select * from test_as_cte);
But get the following error:
SQL Error [42601]: ERROR: subquery must return only one column
Where: PL/pgSQL function inline_code_block line 9 at PERFORM
If I replace * with myCol in the above code there is no error.
However, I need to do realistic performance testing with the CTE and return multiple columns.
The WITH query enclosed in parentheses is treated like a sub-select. It works fine the way you have it as long as it returns a single value (one column of one row). Else you must treat it as subquery and call it like this (inside a PL/pgSQL code block!):
PERFORM * FROM (with test_as_cte as (select * from b2) select * from test_as_cte t) sub;
Or just:
PERFORM FROM (<any SELECT query>) sub;
The manual:
PERFORM query;
This executes query and discards the result. Write the query
the same way you would write an SQL SELECT command, but replace the
initial keyword SELECT with PERFORM. For WITH queries, use
PERFORM and then place the query in parentheses. (In this case, the
query can only return one row.)
I think this could be clearer. I'll suggest a fix for the documentation.
I'm new to postgres, for a scenario i stored SQL statements inside a table with respective to table name. in the function i'm trying to filter the table name by passing them as a parameter to get the query from the table. But when i execute the query from the variable it gives out error
"SQL Error [42P01]: ERROR: relation "public.table_name" does not exist
Where: PL/pgSQL function ops_data_refresh(text) line 45 at EXECUTE"
execute format('select query from public.ops_dw_table_load where target_table=''%s'' and is_active =true',main_table)
into qry1;
if qry1 is not null then
raise notice '%',qry1;
execute qry1;
raise notice output insert into public.table_name select * from stage.table_name;
with raise notice im able to see the query which is in the table, if I run it manually things are working fine. but when running from function it throws the above error.
There is an SQL injection bug in your code. It should be:
EXECUTE format('SELECT ... target_table = %L ...', main_table);
But the problem is in the second EXECUTE: the query references a table that does not exist. Either change the query or create the table.
I had a query in SQL for postgres to get the count
SELECT COUNT(*) AS count_variable FROM user WHERE something=something;
When I executed, it was returning the count. Then as per requirement this query was required inside a Postgres Function.When I used this query inside Function, Postgres replied
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 myfuntion(integer,integer) line 11 at SQL statement
I searched for this error and found that, this happens if query returned null while using SELECT, But already I was getting value when executed directly on command line.
And also some posts told to discard it we should use PERFORM instead of SELECT. So my new query inside the same function was
PERFORM COUNT(*) AS count_variable FROM user WHERE something=something;
After this function started working, but count_variable is always zero. I am checking it using raise after PERFORM query.
raise notice 'count_variable: %', count_variable;
count_variable is declared as
DECLARE
count_variable int;
...
BEGIN
count_variable := 0;
Is there anything I am missing or doing wrong, or COUNT() function doesn't works inside function. If count() is not available, is their any alternative for counting rows. Somewhere I saw ##ROWCOUNT is also a variable to get row count, but it gives error.
Help will be highly appreciated.
You don't want to discard the result of the select, so perform is the wrong choice. You want to store the result of the query in a variable, so you need an INTO clause:
DECLARE
count_variable int;
...
BEGIN
SELECT COUNT(*) INTO count_variable
FROM "user"
WHERE something=something;
...
Just because you give the column an alias that is the same name as a variable, does not mean the result is stored in that variable. The column names have no relation with variables.
This is all explained in detail in the manual. Especially the chapter Executing a Query with a Single-row Result
I was attempting to use Dynamic SQL to run some queries in postgres.
Example:
EXECUTE format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition)))
I have to query a table, which is of the form result_%s_table wherein, I need to substitute the correct table name (an id) from an another table.
I get the error ERROR: prepared statement "format" does not exist
Link: string substitution with query result postgresql
EXECUTE ... USING only works in PL/PgSQL - ie within functions or DO blocks written in the PL/PgSQL language. It does not work in plain SQL; the EXECUTE in plain SQL is completely different, for executing prepared statements. You cannot use dynamic SQL directly in PostgreSQL's SQL dialect.
Compare:
PL/PgSQL's EXECUTE ... USING; to
SQL's EXECUTE
See the 2nd last par in my prior answer.
In addition to not running except in PL/PgSQL your SQL statement is wrong, it won't do what you expect. If (select id from ids where condition = some_condition) returns say 42, the statement would fail if id is an integer. If it's cast to text you'd get:
EXECUTE format('SELECT * from result_%s_table', quote_ident('42'));
EXECUTE format('SELECT * from result_%s_table', '"42"');
EXECUTE 'SELECT * from result_"42"_table';
That's invalid. You actually want result_42_table or "result_42_table". You'd have to write something more like:
EXECUTE format('SELECT * from %s', quote_ident('result_'||(select id from ids where condition = some_condition)||'_table'))
... if you must use quote_ident.
CREATE OR REPLACE FUNCTION public.exec(
text)
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN QUERY EXECUTE $1 ;
END
$BODY$;
usage:
select * from exec('select now()') as t(dt timestamptz)
Try using
RETURN QUERY EXECUTE '<SQL Command>'
This will return data into form of table. You have to use this into stored function of PostgreSQL.
I have already created on full demonstration on custom filter and custom sorting using dynamic query of PostgreSQL.
Please visit this url:
http://www.dbrnd.com/2015/05/postgresql-dynamic-sql/
These all look more complicated than the OP's question. A different formatting should do the trick.. but it could absolutely the case that I don't understand.
From how I read OP's question, I think others in a similar situation may benefit from how I got it.
I am using Postgre on Redshift, and I ran into this issue and found a solution.
I was trying to create a dynamic query, putting in my own date.
date = dt.date(2018, 10, 30)
query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''
But, the query entirely ignores the condition when typing it this way.
However, if you use the percent sign (%), you can insert the date correctly.
One correct way to write the above statement is:
query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''
So, maybe this is helpful, or maybe it is not. I hope it helps at least one person in my situation!
Best wishes.
EXECUTE will work only on pl/pqsql environment.
instead of EXECUTE try with SELECT
SELECT format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition))
output would be the dynamic query.