INSERT INTO temp table not working in stored procedure [duplicate] - postgresql

This question already has answers here:
Creating temporary tables in SQL
(2 answers)
Closed 9 months ago.
This script works fine when running on dbeaver, I can work with the new created temp table:
SELECT someField
INTO TEMP tmp_TableZZ
FROM "_fdw_xxx".myTable;
But when inside a stored procedure, I got this error message:
SQL Error [42601]: ERROR: "temp" is not a known variable
Same code:
CREATE OR REPLACE procedure PopulateSomething()
LANGUAGE plpgsql
AS $procedure$
DECLARE v_ReportDte date;
begin
--some code omitted
SELECT someField
INTO TEMP tmp_TableZZ
FROM "_fdw_xxx".myTable;
--some code omitted
end; $procedure$
;
Using TEMPORARY instead of TEMP got the same result.

well, I find out that SELECT INTO in SQL is different from SELECT INTO in pgsql.
The former accepts TEMP as the parameter, the latter expects a variable to store some value.

Related

Postgresql - Unable to create stored procedure as defintion contains temporary table

In postgresql 13, I am inserting data of a table into temporary table at run time. Query works fine when executed. But when I try to create store procedure on top of the query it fails with error: ERROR: "temp" is not a known variable
Can someone please help me to understand what am I missing?
DB FIDDLE
CREATE OR REPLACE PROCEDURE dbo.<proc-name>()
LANGUAGE plpgsql
AS $$
BEGIN
DROP TABLE IF EXISTS child;
SELECT Id, Name
into TEMP TABLE child
FROM dbo.master;
COMMIT;
END;
$$;
Thanks
SELECT ... INTO is PL/pgSQL syntax to store a query result in a variable. You should use CREATE TABLE ... AS SELECT.

using execute in postgres returns syntax error

I'm trying to debug this adn find out why I'm getting syntax error:
CREATE OR REPLACE FUNCTION public.myfunc(_report_id integer, _cutoff_date date)
RETURNS record
LANGUAGE plpgsql
AS $function$
declare
_deliverable_id RECORD ;
BEGIN
FOR _deliverable_id IN
SELECT deliverable_id FROM public.deliverables where report_id=_report_id
LOOP
execute format('DROP TABLE IF EXISTS report.products_%I',_deliverable_id);
END LOOP;
END
$function$
;
When I execute this, I get:
syntax error at or near ""(1111)""
1111 is one deliverable for sure, so this leads me to think it has something to do with the execute statement format, or the way I'm using %I?
%I is replaced as a whole identifier. If you want to concatenate things, you need to do it before replacement.
You can test/debug this for yourself by inspecting the result of the format() function:
select format('DROP TABLE IF EXISTS report.products_%I',42);
returns DROP TABLE IF EXISTS report.products_"42"
you need to use:
select format('DROP TABLE IF EXISTS report.%I',concat('products_', 42));
which correctly returns DROP TABLE IF EXISTS report.products_42
(obviously you need to replace 42 with your variable.

Not able to dynamically truncate table in Redshift Stored Procedure

I have a table in Redshift (let's call it a status table) where I set the status of tables which I want to truncate. I created a Redshift Stored Procedure in order to achieve that. Here is my code for the SP:
CREATE OR REPLACE PROCEDURE <schema>.truncate_table()
AS $$
DECLARE
v_tpsl RECORD;
exec_statement VARCHAR(256);
BEGIN
FOR v_tpsl in SELECT * from <schama>.tablename_process_status_log WHERE status = 'TRUE' LOOP
exec_statement = 'TRUNCATE TABLE <schema>.' + quote_ident(v_tpsl.staging_table_name) + '_test;';
RAISE INFO 'statement = %', exec_statement;
EXECUTE exec_statement;
END LOOP;
END;
$$
LANGUAGE plpgsql;
Now when I am CALLING the Stored Procedure, I am getting this error:
SQL Error [500310] [34000]: [Amazon](500310) Invalid operation: cursor does not exist;
I looked at the documentation of the SP to check if Truncate is possible or not. By looking at the examples, it looks like it's possible.
I am not sure what is going wrong in this. I am using RedshiftJDBC42-no-awssdk-1.2.34.1058.jar and connecting via DBeaver.
It looks like I have found the answer. According to this, Any cursor that is open (explicitly or implicitly) is closed automatically when a COMMIT, ROLLBACK, or TRUNCATE statement is processed. In my next iteration of the loop, it's trying to accessing the cursor which is already closed.

query has no destination for result data [duplicate]

This question already has answers here:
Error: query has no destination for result data while using a cursor
(2 answers)
Function with SQL query has no destination for result data
(3 answers)
Closed 8 years ago.
i have table like below with name student
S.No Name
1. Ramesh
2. Raju
3. SOmu
-------------
------------- etc
My requirement is when i am passing the S.no i will get the Name by using function
My function like below:
CREATE OR REPLACE FUNCTION fn_name(v_sno bigint)
RETURNS TEXT
AS
$BODY$
DECLARE RESULT VARCHAR(5000);
BEGIN
SELECT RESULT "Name" FROM "Student" WHERE "s.no" = v_sno;
RETURN RESULT;
END;
$BODY$
LANGUAGE plpgsql
COST 100;
ALTER FUNCTION fn_name(bigint)
OWNER TO postgresql
but i am getting the following 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 fn_name(bigint) line 6 at SQL statement
please help me how to resolve the above issue.
The immediate question is easily answered by the manual (see SELECT INTO).
However, all that is a rather overcomplicated way to do what you want. Things notably wrong:
varchar(5000) is weird and unnecessary. Use text or unqualified varchar.
SELECT RESULT "Name" doesn't do what you probably think it does. That's trying to SELECT a column named result and alias it as Name. I think you were looking for SELECT INTO.
"s.no" means the column named s.no. Is that what you meant? Because that's a horrid name for a column; without the quotes it'd be interpreted as the column no from the table s. Don't use periods in column names or table names.
All you really need is:
CREATE OR REPLACE FUNCTION fn_name(bigint)
RETURNS TEXT AS
$BODY$
SELECT "Name" FROM "Student" WHERE "s.no" = $1;
$BODY$
LANGUAGE sql;
(assuming "s.no" really is your column name, not a mangled attempt at an alias).
If you had to use PL/PgSQL for this simple job for some reason (maybe you intend to make it more complex later), you'd write:
CREATE OR REPLACE FUNCTION fn_name(v_sno bigint)
RETURNS TEXT AS
$BODY$
DECLARE
result text;
BEGIN
SELECT INTO result "Name" FROM "Student" WHERE "s.no" = $1;
RETURN result;
END;
$BODY$
LANGUAGE plpgsql;

Retrieving a value from a RECORD

In a plpgsql function, I have a variable of type record:
my_rec RECORD;
This record contains a row from an arbitrary table, so I do not know the columns before it is executed.
However, I do have the name of at least one of the columns available as a varchar.
The question is: How do I retrieve the value for a given column from my_rec?
Use hstore to work with records with dynamic columns in PL/PgSQL functions:
CREATE EXTENSION hstore;
CREATE OR REPLACE FUNCTION test_fn(col_name text) RETURNS text AS $$
DECLARE
input_row record;
col_value text;
BEGIN
SELECT INTO input_row
*
FROM ( VALUES ('a','b','c',1) ) AS dummyrow(col1,col2,col3,intcol);
SELECT INTO col_value
hstore(input_row) -> col_name;
RETURN col_value;
END;
$$ LANGUAGE 'plpgsql';
hstore is an extension, but it's an extension that's been bundled with PostgreSQL since 8.3 and has been installable using CREATE EXTENSION since 9.1. The record-to-hstore conversion has been supported since something like 8.4 or 9.0.
I don't know of a way to do this in plpgsql. I did a bit of testing for you and tried to make a "EXECUTE SELECT" solution work, such as:
EXECUTE 'select $1.' || quote_ident(the_param) USING my_rec INTO my_var;
This does not work for me and I get:
could not identify column "{{param_value here}}" in record data type
Here is a very similar question from a few years ago saying that it is not possible with plpgsql. Per it's suggestion, it appears that it should be possible with some other languages. Quoting Tom Lane's answer:
There is no way to do that in plpgsql. You could do it in the other PLs
(eg plperl, pltcl) since they are not as strongly typed as plpgsql.