Error with NEW to create a function for a trigger - sql

I am trying create a function for a trigger like this:
CREATE FUNCTION backup_largeobjects_grant()
RETURNS trigger AS $$
BEGIN
GRANT SELECT ON LARGE OBJECT NEW.loid TO backup;
END; $$
LANGUAGE plpgsql;
But this gives me error when it reaches the NEW.
ERROR: syntax error at or near "NEW"
I've been looking but not understand that I'm doing wrong.
Any idea?

It looks like GRANT ... ON LARGE OBJECT statements can't be parameterised; the object ID will need to appear as a literal integer value.
You can achieve this in a stored procedure by building the statement as a string:
EXECUTE 'GRANT SELECT ON LARGE OBJECT ' || NEW.loid::text || ' TO backup';

Related

Generated string to SQL request in snowflake

I am actually trying to find a solution for my issue. The problem is this one :
A function generate a string, this string is a SQL request, and I want to use snowflake to "read" and execute this SQL request.
Do you have a solution for this kind of problem please ?
I still continue to try to find a solution if I find it I will put it here.
Here is my problem with more information about it.
create or replace function var_test(arg1 varchar)
returns varchar as
$$
'CREATE OR REPLACE TABLE ENV_EUT.EUT.TABLE_TEST_ALEXIS_' || arg1 || '(a varchar);'
$$
;
SELECT var_test('3') AS num_table;
With this request, i get back a table with 1 column and a value in this column :
CREATE OR REPLACE TABLE ENV_EUT.EUT.TABLE_TEST_ALEXIS_3(a varchar);
My problem now is I don't succeed to execute the string in this table. Do you see a way to do this please ? Best regards
Thank you all
Check out Snowflake Scripting.
https://docs.snowflake.com/en/developer-guide/snowflake-scripting/index.html
You can declare a statement as a variable and execute it.
See also: execute immediate
https://docs.snowflake.com/en/sql-reference/sql/execute-immediate.html
-- very simple sproc
create or replace procedure myprocedure(arg1 string)
returns varchar
language sql
as
$$
-- declare variables
declare
smt string;
begin
-- construct statement
smt := 'CREATE OR REPLACE TABLE TEST_ALEXIS_' || arg1 || ' (a varchar)';
-- execute statement
execute immediate smt;
-- message to return on success
return 'Successfully executed statement: ' || smt;
-- message to return on exception
exception
when statement_error then
return object_construct('Error type', 'STATEMENT_ERROR',
'SQLCODE', sqlcode,
'SQLERRM', sqlerrm,
'SQLSTATE', sqlstate);
end;
$$
;
-- call sproc to create table
call myprocedure('TEST');

Postgres set working schema from inside of function

I am facing a problem I have a function which used to create schema and tables inside that schema after table creation I am calling a function which supposed to populate this schema however feels like the second function doesn't set the working schema and throws the error that object doesn't exits (
ERROR: relation "table" does not exist
LINE 1: INSERT INTO table
here is what the function looks like.
CREATE OR REPLACE FUNCTION create_schema(
t_shema character varying,
t_country TEXT
)
RETURNS character varying
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
tname text := t_shema;
tschem_name text := tname||'_work';
tsql_dyn text ;
tschema_check numeric := 0 ;
BEGIN
SELECT 1
INTO TSCHEMA_CHECK
FROM PG_NAMESPACE
WHERE NSPNAME = TSCHEM_NAME;
IF TSCHEMA_CHECK = 1 THEN
RETURN 'Schema '||tschem_name ||' Already exists';
ELSE
tsql_dyn := 'CREATE SCHEMA '||tschem_name||';';
raise notice 'EXECUTE %', tsql_dyn;
EXECUTE tsql_dyn;
tsql_dyn := 'SET search_path TO '||tschem_name ||';';
raise notice 'EXECUTE %', tsql_dyn;
EXECUTE tsql_dyn;
--other DDLs
---execute of function which populates freshly created schema
SELECT public.populate_empty_schema(tname, t_country);
RETURN tname ||' created';
END IF;
END;
$BODY$;
The second function also has a statement as first which sets the working schema.
Both functions work fine if get called separately, trows error only if second get called from the first
Your function is vulnerable to SQL injection.
Instead of
tsql_dyn := 'CREATE SCHEMA '||tschem_name||';';
write
tsql_dyn := format('CREATE SCHEMA %I', tschem_name);
To set the search_path in populate_empty_schema, pass the schema name to the function and have it execute
PERFORM set_config('search_path', v_schema, TRUE);
feels like Postgres cannot set working schema from the second function, my solution. was just deleting the set search path from the second function and it is working. feels like it couldn't set it as shcema is not committed at the point when the 2-nd function gets called.

Getting ERROR while running ALTER statement inside the SQL function

I wrote a SQL function to ALTER the SCHEMA Ownership. I am able to run the statement directly(without function) but getting error while running the ALTER statement within the function.
Function "test" created successfully:
CREATE OR REPLACE FUNCTION test.update_ownership(schemaname text) RETURNS text AS $$
DECLARE
BEGIN
ALTER SCHEMA schemaname OWNER TO postgresql;
END;
$$ LANGUAGE plpgsql;
Executing the function as:
select test.update_ownership('myschema')
I am getting an ERROR while executing the function i.e.:
ERROR: schema "schemaname" does not exist
CONTEXT: SQL statement "ALTER SCHEMA schemaname OWNER TO postgresql"
PL/pgSQL function collection.update_ownership(text) line 4 at SQL statement
SQL state: 3F000
You can't use parameters as identifiers, you have to use dynamic SQL for this. Generating the SQL is best done using the format() function to properly deal with identifiers.
CREATE OR REPLACE FUNCTION test.update_ownership(schemaname text)
RETURNS void
AS $$
BEGIN
execute format('ALTER SCHEMA %I OWNER TO postgresql', schemaname);
END;
$$ LANGUAGE plpgsql;

Call multiple stored procedures within a stored procedure

I want to create a stored procedure that calls multiple other stored procedures and saves the output parameters into variables as each stored procedure's output is the input parameters for the next one.
My code looks like this:
CREATE PROCEDURE sa.sp_step0(inout name text)
LANGUAGE plpgsql
AS $$
DECLARE
id text;
run text;
tables_step2 text[];
tables_step3 text[];
tables_step4 text[];
table_step5 text;
BEGIN
call sa.sp_step1(model_name) insert into id,run;
call sa.sp_step2(id,run) insert into id,run,tables_step2;
call sa.sp_step3(id,run,tables_step2) insert into id,run,tables_step3;
call sa.sp_step4(id,run,tables_step3) insert into id,run,tables_step4;
call sa.sp_step5(id,run,tables_step4) insert into id,run,tables_step5;
return;
end
$$;
I get the following error:
SQL Error [42601]: ERROR: syntax error at or near "insert"ΒΆ
It looks to me as though you're using the syntax of some other database product.
To do what you're trying to do in PostgreSQL, you'd need to declare your procedures something like this:
CREATE PROCEDURE sp_step1(IN model_name TEXT, INOUT id TEXT, INOUT run TEXT)
LANGUAGE plpgsql
AS...
and then call your procedures as
call sa.sp_step1(model_name, id, run);
call sa.sp_step2(id, run, tables_step2);
call sa.sp_step3(id, run, tables_step2, tables_step3);
...
Man I love it when I figure out my own errors and help someone else out there in the www....
basically, if you want to save the outputs of a stored procedure into a variable, you would do the following:
execute ('sa.sp_step1(''' || model_name|| ''')') into id,run;

error of running a stored proceudre in IBM netezza SQL database

I need to create a stored procedure in IBM netezza SQL database from IBM Aginity workbench.
This is my SQL code to create the SP:
CREATE OR REPLACE PROCEDURE "SP_drop_a_table_if_exists"(varchar(128))
RETURNS boolean
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
declare
oname alias for $1;
o record;
begin
select otype into o
from (
select 'TABLE' otype from _v_table where tablename = upper(oname)
union all
select 'VIEW' otype from _v_view where viewname = upper(oname)
) x;
if found then
execute immediate 'DROP '||o.otype||' '||oname;
end if;
end;
END_PROC;
I created successfully.
But, when I ran it,
CALL SP_drop_a_table_if_exists('test_a_table':: varchar(128))
I got error:
ERROR[42S02] error: function 'sp_drop_a_table_if_exists(varchar)' does not exists
unable to identify a function that satisdy the given argument types
you may need to add explicit typecasts
Any help would be appreciated !
You created your stored procedure with mixed case inside of double quotes...
CREATE OR REPLACE PROCEDURE "SP_drop_a_table_if_exists"(varchar(128))
...but when you call the stored procedure you don't use double quotes, so the name is being converted all upper case.
CALL SP_drop_a_table_if_exists('test_a_table':: varchar(128))
Try this instead:
CALL "SP_drop_a_table_if_exists"('test_a_table':: varchar(128))
I should also mention that more recent versions of NPS support this syntax for the DROP TABLE command:
DROP TABLE TABLENAME IF EXISTS;