execute immediate errors - amazon-redshift

I'm using Amazon RedShift SQL (used to use Oracle many years ago) and am getting constant syntax errors every way that I try EXECUTE IMMEDIATE. I have even copied and posted code from PostgreSQL documentation pages (e.g. using sprintf) but to no avail. I reckon the below should work...?
declare
stm varchar(200);
begin
stm = 'GRANT SELECT, INSERT, TRIGGER, UPDATE, DELETE, REFERENCES, RULE ON public.angus TO adcd;';
execute immediate stm;
end;
Amazon Invalid operation: syntax error at or near "varchar"

There are two problems:
You use EXECUTE IMMEDIATE, which you cannot have found in the PostgreSQL documentation, since it is Oracle syntax. The PL/pgSQL statement is EXECUTE.
You are trying to execute PL/pgSQL code as SQL statement, which won't work.
Use a DO statement:
DO $$DECLARE
...
END;$$;

Syntax for a standalone anonymous block slightly different, also the code is actually submitted as a string. See Postgres DO and search Dollar Quoting. Try
Do $$
declare
stm varchar(200);
begin
stm = 'GRANT SELECT, INSERT, TRIGGER, UPDATE, DELETE, REFERENCES, RULE ON public.angus TO adcd;';
execute immediate stm;
end;
$$

Related

DbUp throwing Npgsql exception when using SQL-language syntax for PostgreSQL functions

I'm using DbUp to deploy to a PostgreSQL-14 database. When I try to create a function or procedure using SQL-language syntax, DbUp throws an Npgsql.PostgresException 42601, claiming there's a syntax error. I've run the below code successfully using pgAdmin, so I'm not sure why DbUp is having a hard time with it (unless it doesn't support postgres 14?)
Here is my script:
CREATE OR REPLACE FUNCTION test_function() RETURNS VARCHAR(11)
LANGUAGE SQL
BEGIN ATOMIC
SELECT 'Hello World';
END;
and here is the error:
ERROR: syntax error at end of input at character 114
STATEMENT: CREATE OR REPLACE FUNCTION test_function() RETURNS VARCHAR(11)
LANGUAGE SQL
BEGIN ATOMIC
SELECT 'Hello World'
I'm aware I could rewrite the function in plpgsql language, but I want the dependency tracking that SQL language offers.
#ChrisKelly thanks, I wasn't aware of this new syntax! Unfortunately this breaks Npgsql's internal SQL parser, since the semicolon causes the statement to be split... I've opened this issue to track this as an Npgsql bug; some workarounds are suggested there.
If you can't use the workarounds in that issue, then as I posted previously you can use this alternative syntax, even if it's inferior (dependency tracking and so on):
CREATE OR REPLACE FUNCTION test_function() RETURNS VARCHAR(11)
LANGUAGE SQL
RETURN 'Hello World';

"ERROR: invalid transaction termination" when trying to execute a procedure with nested transaction control

According to the documentation (https://www.postgresql.org/docs/current/app-psql.html), even with AUTOCOMMIT set to off, PSQL issues an implicit BEGIN just before any command that is not already in a transaction block and is not itself a BEGIN or other transaction-control command, nor a command that cannot be executed inside a transaction block such as VACUUM. (Unfortunately CALL is not treated in the same way as VACCUM). And, according to Shaun Thomas (https://blog.2ndquadrant.com/pg-phriday-stored-procedures-postgres-11/), the invalid transaction termination error happens because it is not possible to close the current transaction (in this case the one initiated by PSQL) from within the procedure. I have tried with all the PSQL settings related to transaction control, but the invalid transaction termination error occurs with all of them; even if the commands file processed by PSQL contains only the CALL statement.
This is the procedure I'm calling:
create or replace procedure producto$cargar_imagenes(_super$ bigint, _archivo$ character varying) as $$
declare
_msg character varying;
_log rastro_proceso%ROWTYPE;
begin
perform rastro_proceso_temporal$insert(_super$);
perform producto$cargar_imagenes$biz(_super$, _archivo$);
if (_super$ is not null and _super$ > 0) then
perform producto$cargar_imagenes$log(_super$, _archivo$);
else
perform tarea_usuario$private$update(6519204281880642486, null);
end if;
commit;
end;
$$ language plpgsql set search_path = public;
It fails at the commit statement; it works if I comment it out.
Remove the SET clause. Per the documentation:
If a SET clause is attached to a procedure, then that procedure cannot execute transaction control statements (for example, COMMIT and ROLLBACK, depending on the language).
It appears that in pg11 (tested in version 11.6) you have the same problem if you include the "SECURITY DEFINER" clause in the procedure definition. So I guess SECURITY DEFINER qualifies as a "SET" clause.
When I remove SECURITY DEFINER I can include a COMMIT statement within the procedure definition without getting the ERROR:invalid transaction termination on the COMMIT statement.
It is also unfortunate that this is a run time error, and NOT a compilation error.

How to use DO in postgres

I am attempting to get a better understanding of the DO command in postgreSQL 9.1
I have following code block,
DO
$do$
BEGIN
IF 1=1 THEN
SELECT 'foo';
ELSE
SELECT 'bar';
END IF;
END
$do$
However it returns the following error:
[42601] ERROR: query has no destination for result data Hint: If you want to discard the results of a SELECT, use PERFORM instead. Where: PL/pgSQL function "inline_code_block" line 4 at SQL statement
PostgreSQL DO command creates and executes some specific short life function. This function has not any interface, and then it cannot to return any output other then changes data in tables and some debug output.
Your example has more than one issues:
Only PostgreSQL table functions can returns some tabular data. But the mechanism is significantly different than MSSQL. PostgreSQL user's should to use RETURN NEXT or RETURN QUERY commands.
CREATE OR REPLACE FUNCTION foo(a int)
RETURNS TABLE(b int, c int) AS $$
BEGIN
RETURN QUERY SELECT i, i + 1 FROM generate_series(1,a) g(i);
END;
$$ LANGUAGE plpgsql;
SELECT * FROM foo(10);
DO anonymous functions are not table functions - so no output is allowed.
PostgreSQL 9.1 is not supported version, please upgrade
If you have some experience only from MSSQL, then forget it. A concept of stored procedures of PostgreSQL is very similar to Oracle or DB2, and it is significantly different to MSSQL does. T-SQL integrates procedural and SQL constructs to one set. Oracle, PostgreSQL, ... procedural functionality can embedded SQL, but procedural functionality is not integrated to SQL.
Please, read PostgreSQL PLpgSQL documentation for better imagine about this technology.

Postgresql how to multiple stored procedure in transaction

I have many stored procedure in my postgresql db,
and for some reason i need to run many procedure in transaction so if there is a error it will rollback.
is there any way to do this?
edit 1
i run this through java and for some reason i cant make transaction from java and i cant run query string, just store procedure only.
I actually thinking making procedure like this
CREATE OR REPLACE FUNCTION ldt_pricing_rule_v1_api.start()
RETURNS VOID
LANGUAGE PLPGSQL
SECURITY DEFINER
AS $$
BEGIN
EXECUTE 'begin transaction'
RETURN;
END
$$;
select ldt_pricing_rule_v1_api.start();
but it's will display this
ERROR: cannot begin/end transactions in PL/pgSQL
HINT: Use a BEGIN block with an EXCEPTION clause instead.
BEGIN ... COMMIT should to work.
BEGIN
SELECT func1();
SELECT func2();
COMMIT;
PostgreSQL 11 (it is not released yet) has procedures where you can control transactions explicitly. Procedures are started by CALL statement like any other databases. Now, PostgreSQL functions doesn't allow control transactions (explicitly).
Any PostgreSQL function is executed under transaction - explicitly started by user (like my example), or implicitly started by system (by autocommit mode).
So outer BEGIN starts explicit transaction:
BEGIN
SELECT func1();
SELECT func2();
COMMIT;
and if there is any unhandled fail, then only ROLLBACK command is available.
or implicit transaction:
CREATE OR REPLACE FUNCTION outerfx()
RETURNS void AS $$
BEGIN
PERFORM func1();
PERFORM func2();
END;
$$ LANGUAGE plpgsql;
SELECT outerfx(); -- starts outer transaction implicitly.
Now, functions func1, func2 are executed under transaction too.

How can I execute pl/pgsql code without creating a function?

With SQL Server, I can execute code ad hoc T-SQL code with full procedural logic through SQL Server Management Studio, or any other client. I've begun working with PostgreSQL and have run into a bit of a difference in that PGSQL requires any logic to be embedded in a function.
Is there a way to execute PL/PGSQL code without creating an executing a function?
Postgres 9
DO $$
-- declare
BEGIN
/* pl/pgsql here */
END $$;
No, not yet. Version 9.0 (still alpha) will have this option (do), you a have to wait until it's released.
I struggled to get this working because it's fairly strict about adding semi colons in exactly the right places. But once you get used to that it works well. Besides the inability to return records of course, however you can raise notices & exceptions and do the other workarounds like using temp tables as #ErwinBrandstetter pointed out in a comment above.
e.g.:
DO
$$
BEGIN
IF EXISTS(SELECT 'any rows?'
FROM {your_table}
WHERE {your_column} = 'blah')
THEN
RAISE NOTICE 'record exists';
ELSE
RAISE EXCEPTION 'record does not exist';
END IF;
DROP TABLE IF EXISTS foo;
CREATE TEMP TABLE foo AS
SELECT 'bar'::character varying(5) as baz;
END
$$;
SELECT * FROM foo;