Can we create a anonymous block and run in AWS Redshift like in Oracle PL/SQL? - amazon-redshift

Can we create a anonymous block and run in AWS Redshift like in Oracle PL/SQL ? I was trying to execute the following block in Redshift and getting an error “SQL Error [42601]: ERROR: syntax error at or near "record" Position: 14
Fyi:- I dont want to create a stored procedure /function.
declare
cur record;
begin
for cur in select table_name from svv_tables t
loop
execute 'select count(*) from '||cur.table_name ;
commit;
end loop;
end;

From Redshift's docs it seems they don't support DO at this moment.

Related

How to call a procedure with Rollback in the end?

I am working with PostgreSQL with DBeaver. I would like for test purposes to make a procedure call in a transaction; then to Rollback it. I have written the following script:
DO $$
BEGIN
call MyProcedure();
ROLLBACK $$;
I have tried to run it in DBeaver console. I have got the following error:
SQL Error [42601]: ERROR: syntax error at end of input
It pointed out to the final $$.
What is wrong; and how could I reach my goal: to make a procedure call in a transaction; then to Rollback it?
For the DO block, you are missing the end
DO $$
BEGIN
RAISE NOTICE 'test';
ROLLBACK;
END $$;
But since you want to display a table content, you can't use an anonymous block but instead just start/end the transaction.
BEGIN;
select * from test;
call my_procedure();
select * from test;
ROLLBACK;

PostgreSQL ODBC driver and cursor issue

In my app I use cursor to recieve dataset from stored procedure.
But I have an error:
ERROR: invalid transaction termination
CONTEXT: PL/pgSQL function inline_code_block line 6 at COMMIT
SQL state: 2D000
This error raise in case when AutoCommit option is not set.
In DBeaver IDE if autocommit is ON, I have no error.
In pgAdmin 4 this I have error any way (autocommit is on OR is OFF).
In my app I use ODBC driver to connect.
How can I set autocommit option in driver settings?
Test code bellow:
create table test_table (spid int);
insert into test_table
select 1;
insert into test_table
select pg_backend_pid();
do $$
declare
var_ImplicitResultSet refcursor := 'var_implicitresultset';
begin
delete from test_table where spid = pg_backend_pid();
commit;
open var_ImplicitResultSet FOR SELECT spid from test_table where spid <> pg_backend_pid();
END
$$;
fetch all from var_implicitresultset;
Or is there another way to get the dataset from the stored procedure?
P.S. I'm adapting an old application so I need to learn how to return datasets from within procedures
Thanks for answer!

how can I create a stored procedure sql workbench that uses a redshift database?

is it possible to create a stored procedures on sql workbench that uses a redshift database ?
I tried to put in some procedure found on the internet like this one
CREATE OR REPLACE FUNCTION proc_sample RETURN INTEGER
IS
l_result INTEGER;
BEGIN
SELECT max(col1) INTO l_result FROM sometable;
RETURN l_result;
END;
but I get an error
the cursor is not located inside a statement
help please.
Here is my translation of your stored procedure for Redshift:
CREATE OR REPLACE PROCEDURE proc_sample (
l_result OUT INTEGER
)
LANGUAGE plpgsql
AS $$
BEGIN
SELECT max(col1) INTO l_result FROM sometable;
END
$$;
You call this stored procedure in Redshift as follows:
BEGIN; CALL proc_sample(); END;
-- l_result
-- ----------
-- 99
For more information see "Overview of stored procedures in Amazon Redshift"
you can not use from clause in function. you have to use procedure having parameter with out clause.

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.

How to save query errors in plpgsql to a table?

I need to save in a table the error code (SQLSTATE) and the error message (SQLERRM) returned by an INSERT or an UPDATE. My procedure must execute an INSERT, and if an error occurs, it must be saved into an apposite table.
But the problem is that if I use an EXCEPTION block, when an error occurs the transaction is aborted and any command after cannot execute.
How can I save the error returned by a query in a table using PLPGSQL?
There are two possible solutions:
use a CSV format of PostgreSQL log. Later you can import pg log to table by \copy statement. This way is preferred if it is possible, because it has minimal negative impact on performance.
You can emulate autonomous transactions via more techniques
PostgreSQL dblink
PostgreSQL FDW driver
Example of dblink based emulation (by Jon Roberts and me):
CREATE OR REPLACE FUNCTION fn_log_error(_function varchar,
_location int, _error varchar)
RETURNS void AS $$
DECLARE
_sql varchar;
_exec_error varchar;
BEGIN
PERFORM dblink_connect('autonom_connection', 'dbname=...');
_sql := format('INSERT INTO error_log (function_name, location,
error_message, error_time) VALUES (%L, %s, %L, %L)',
_function, _location, _error, clock_timestamp());
PERFORM dblink_exec('autonom_connection', _sql, false);
_exec_error := dblink_error_message('autonom_connection');
IF position('ERROR' in _exec_error) > 0
OR position('WARNING' in _exec_error) > 0 THEN
RAISE EXCEPTION '%', _exec_error;
END IF;
PERFORM dblink_disconnect('autonom_connection');
EXCEPTION
WHEN others THEN
PERFORM dblink_disconnect('autonom_connection');
RAISE EXCEPTION '(%)', SQLERRM;
END;
$$ LANGUAGE plpgsql;
Some other examples:
http://raghavt.blogspot.cz/2012/05/autonomous-transaction-in-postgresql-91.html
http://tapoueh.org/blog/2013/10/14-autonomous-transactions