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

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

Related

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;

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

PostgreSQL IF-THEN-ELSE control structure

Why do I always get the following error from Postgres?
syntax error at or near "IF"
I read PostgreSQL: Documentation: 8.3: Control Structures. First I tried to execute a difficult query (with subquery), but then I tried to execute a simple one like this:
IF 2 <> 0 THEN select * from users; END IF;
The error is still the same. What am I doing wrong?
IF 2 <> 0 THEN select * from users; END IF;
You cannot use PL/pgSQL statements outside plpgsql functions. And if this fragment is from plpgsql function, then it is nonsense too. You cannot directly return result of query like T-SQL does.
CREATE OR REPLACE FUNCTION test(p int)
RETURNS SETOF users AS $$
BEGIN
IF p = 1 THEN
RETURN QUERY SELECT * FROM users;
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
When you would get some result from function, you have to use RETURN statement - plpgsql knows only function, it doesn't support procedures - so unbounded SELECT has not sense.
You're not enclosing that PL/pgSQL control structure in an anonymous block or a PL/pgSQL function.
For the SQL version of this control structure see the docs for CASE.
You're not enclosing that PL/pgSQL. They need to be enclosed with anonymous code block. Example for your code:
DO $$ BEGIN
IF 2 <> 0 THEN select * from users; END IF;
END$$;