Getting ERROR while running ALTER statement inside the SQL function - sql

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;

Related

Function Doesn't Work: ERROR: syntax error at or near "DELETE"

I am trying to create a function inside Postgres. For some reason my query works perfectly fine when I run it from inside the Query tool. Once I added the query to my function, I get the error
ERROR: syntax error at or near "DELETE"
Not sure what is the problem.
CREATE FUNCTION public.remove_email_header()
RETURNS pg_trigger
LANGUAGE 'plpgsql'
AS $BODY$
DELETE FROM public.spam_dictionary WHERE words LIKE '%FROM%';
$BODY$;
ALTER FUNCTION public.remove_email_header()
OWNER TO postgres;
Two Things to note.
A plpgsql Postgres function uses BEGIN END
The plpgsql should not be quoted.
CREATE FUNCTION remove_email_header()
RETURNS trigger
LANGUAGE plpgsql
AS $BODY$
BEGIN
DELETE FROM public.spam_dictionary WHERE words LIKE '%FROM%';
END
$BODY$;

How to use data (rather than an identifier) to grant postgres permissions

I want to use the following function (as a trigger on a table's inserts):
CREATE OR REPLACE FUNCTION insert_authid_fn() RETURNS trigger AS $$
BEGIN
GRANT ALL ON DATABASE testdb TO NEW.username;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
I get the error:
ERROR: syntax error at or near "."
LINE 3: GRANT ALL ON DATABASE testdb TO NEW.username;
because New.username is value, rather than an identifier.
How can I achieve this GRANT?
syntactically:
CREATE OR REPLACE FUNCTION insert_authid_fn() RETURNS trigger AS $$
BEGIN
execute format ('GRANT ALL ON DATABASE testdb TO %I',NEW.username);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
But I doubt it is a good idea in general

PostgreSQL: No function matches the given name and argument types

I have the following procedure:
DROP FUNCTION presAdress();
CREATE FUNCTION presadress() RETURNS VARCHAR(100) AS $$
DECLARE studioName text;
BEGIN
RETURN (
SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (
SELECT presC#
FROM Studio
WHERE name = studioName)
);
END;
$$ LANGUAGE plpgsql;
I try to run the procedure:
select presadress('Paramount');
But I get the following error message:
ERROR: function presadress(text) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 294
I suspect that this is because there is some kind of error regarding the in parameters of the procedure, but I have been unable to find a solution.
Use a function parameter, like #Gordon demonstrates, but you don't need plpgsql for this at all. And the query can simplified (shorter, faster):
CREATE FUNCTION presadress(_studioname text)
RETURNS text AS
$$
SELECT m.address
FROM studio s
JOIN movieexec m ON m.cert# = s.presc#
WHERE s.name = _studioname
$$ LANGUAGE sql STABLE;
Function volatility can be STABLE.
Related:
How do IMMUTABLE, STABLE and VOLATILE keywords effect behaviour of function?
Difference between language sql and language plpgsql in PostgreSQL functions
PostgreSQL Stored Procedure Performance
I think you want a declaration more like this:
CREATE FUNCTION presadress (v_studioName text)
RETURNS VARCHAR(100) AS $$
BEGIN
RETURN(SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (SELECT presC#
FROM Studio
WHERE name = v_studioName)
);
END;
$$ LANGUAGE plpgsql;

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;

Error with NEW to create a function for a trigger

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';