access denied you need (at least one of) the super privilege(s) for this operation - cpanel

DELIMITER $$ -- -- Procedures -- CREATE DEFINER=vipmarke_user#localhost PROCEDURE getcat (IN cid INT) SELECT * FROM categories WHERE cat_id=cid$$ DELIMITER ;

Related

Procedure (unknown) does not exist PostgreSQL

I'm new to PostgreSQL, and trying to learn about stored procedure with PostgreSQL. Here are the steps I followed.
Installed pgAdmin4
Created the Database
Created the table "Users" under public schema
Created the procedure "GetUserByEmail"
CREATE OR REPLACE PROCEDURE GetUserByEmail
(
Email Varchar(100)
)
LANGUAGE plpgsql AS
$$
BEGIN
Select * from public."Users" where "Email" = Email
END
$$;
When calling it from query tool, I get an error.
CALL public.GetUserByEmail('d#d.com')
ERROR: procedure public.getuserbyemail(unknown) does not exist LINE
1: CALL public.GetUserByEmail('d#d.com')
^ HINT: No procedure matches the given name and argument types. You might need to add explicit type casts. SQL state: 42883
Character: 6
Checked the permission, and the user has execution rights.
Tried different ways but not sure what is wrong.
Are PostgreSQL column names case-sensitive?
if you create table "users"(a int...) then you stick with "users" every time you select/update/delete "users" table.
You can easily imitate 38.5.9. SQL Functions Returning Sets(https://www.postgresql.org/docs/current/xfunc-sql.html)
CREATE FUNCTION getusers(text) RETURNS SETOF "users" AS $$
SELECT * FROM "users" WHERE email = $1;
$$ LANGUAGE SQL;
SELECT * FROM getusers('hi') AS t1;
stored procedure versus function
demo

only one AS items needed for language "plpgsql";

I am trying to run a copy command inside a stored procedure.
This copy command copies from aws s3 to a table in aws redshift
This is the copy command
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
I am trying to add it into a stored proc, which now looks like this.
here i am trying to create a temp table which contains all the data from s3, which is being copied to temp table using a copy command.
CREATE OR REPLACE PROCEDURE proc_test() LANGUAGE plpgsql
AS
'
BEGIN
drop table if exists
schema1_ghsheet.ghseet_temp
;
create table
schema1_ghsheet.ghseet_temp(emp_id int, emp_name varchar(100),hrly_rate int,mod_timestamp timestamp)
;
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
drop table if exists
schema1_ghsheet.ghseet_main
;
create table
schema1_ghsheet.ghseet_main
as
select h1.emp_id,h1.emp_name,h1.hrly_rate,h1.mod_timestamp
from schema1_ghsheet.ghseet_hstry h1
inner join (
select emp_id ,emp_name , max(mod_timestamp ) mod_timestamp
from schema1_ghsheet.ghseet_hstry
group by 1,2
) h2
on h1.emp_id=h2.emp_id
and h1.mod_timestamp=h2.mod_timestamp
group by 1,2,3,4
;
END;
'
But this throws the error :
only one AS items needed for language "plpgsql";
So , how to add a copy command inside a stored procedure or do i need to call the copy command separately ?
COPY is an allowed DML statement within a stored procedure.
It looks like the error is referring to the AS keyword. As far as I know, the syntax in the documentation requires the script after AS to be wrapped in $$ and the LANGUAGE plpgsql designation should come after the script body . Example given in the documentation is:
CREATE OR REPLACE PROCEDURE test()
AS $$
BEGIN
SELECT 1 a;
END;
$$
LANGUAGE plpgsql
;
/
so you should change the order of the script like follows (I cannot test this locally at this time)
CREATE OR REPLACE PROCEDURE proc_test()
AS
$$
BEGIN
drop table if exists
schema1_ghsheet.ghseet_temp
;
create table
schema1_ghsheet.ghseet_temp(emp_id int, emp_name varchar(100),hrly_rate int,mod_timestamp timestamp)
;
copy schema1_ghsheet.ghseet_temp
from
''''s3://root2/rawfiles/''''
iam_role ''''arn:aws:iam::743:role/redshift''''
csv DELIMITER ',' IGNOREHEADER 1 TRUNCATECOLUMNS;
drop table if exists
schema1_ghsheet.ghseet_main
;
create table
schema1_ghsheet.ghseet_main
as
select h1.emp_id,h1.emp_name,h1.hrly_rate,h1.mod_timestamp
from schema1_ghsheet.ghseet_hstry h1
inner join (
select emp_id ,emp_name , max(mod_timestamp ) mod_timestamp
from schema1_ghsheet.ghseet_hstry
group by 1,2
) h2
on h1.emp_id=h2.emp_id
and h1.mod_timestamp=h2.mod_timestamp
group by 1,2,3,4
;
END;
$$
LANGUAGE plpgsql;

Creating stored procedure in redshift

When creating stored procedure in redshift like below:
CREATE OR REPLACE PROCEDURE sp_test()
AS '
BEGIN
TRUNCATE TABLE TABLE_1;
INSERT INTO TABLE_1
SELECT COL1, COL2
FROM TABLE_2
WHERE CONDITION='SAMPLE';
END;
'
LANGUAGE plpgsql;
This gives an error syntax error near 'SAMPLE' because single quotes is already used for stored procedure begin and end. Also, here we would not be able to replace single quotes in INSERT query to double because redshift will consider it to be a column.
Few other posts suggests to use $$ for stored procedure, however $$ is not supported in sql workbench.
Any work around for this. Thanks.
Have you tried double-quoting the string?
WHERE CONDITION=''SAMPLE'';
Data Sample
CREATE TABLE t (id int, status text);
INSERT INTO t VALUES (42,'foo');
Procedure
CREATE OR REPLACE PROCEDURE sp_test()
AS'
BEGIN
TRUNCATE TABLE t;
INSERT INTO t
SELECT 8,''new record'';
END;'
LANGUAGE plpgsql;
Test procedure
CALL sp_test();
SELECT * FROM t
id | status
----+------------
8 | new record
(1 Zeile)

Best way to create a stored procedure that takes about 30 columns as arguments ? in postgres

What would be the best way to create a stored procedure to apply changes to the database that has about 30 arguments (columns) to be changed?
Right now I'm playing on creating a huge insert query inside the stored procedure that list all the arguments that are passed by the user. Is that the only way or is there a better way for stored procedures this big?
Example:
CREATE OR REPLACE FUNCTION "applyntunesettings"(val1,val2....val30)
RETURNS void AS
BEGIN
INSERT INTO calibrationstable (col1,col2........col20) Values (val1,val2.....val20);
INSERT INTO devicestable (col1,col2,.....col10) values (val21,val22,....val30);
END
Sometimes, row type variables can be convenient. Assuming the tables are "calibrations" and "devices" we can write:
CREATE OR REPLACE FUNCTION applyntunesettings (
_device_name TEXT
, _some_value TEXT
, _other_value TEXT
-- and so on
) RETURNS void AS $$
DECLARE
_calibration calibrations;
_device devices;
BEGIN
_device.name := _device_name;
INSERT INTO devices SELECT _device.*;
_calibration.some_value := _some_value;
_calibration.other_value := _other_value;
INSERT INTO calibrations SELECT _calibration.*;
END $$ LANGUAGE plpgsql;

PostgreSQL unexpected trigger behavior

The Situation:
I have a function fn_SetFoo() that inserts records into table TableFoo.
I also have a trigger function that runs after each insert into TableFoo. It takes the new primary key TableFooID from the newly inserted row and inserts it into a second table TableFooBar (with a foreign key constraint).
I created a trigger that runs AFTER INSERT ON TableFoo FOR EACH ROW EXECUTE PROCEDURE fn_SetFooBar();
If I call fn_SetFoo() directly then everything works as expected.
However, I have a separate function fn_NormalizeFoo() that processes some data and then calls fn_SetFoo() for each record it has processed.
If I call fn_NormalizeFoo() then the only the first record is processed and the function stops.
The Question:
Why would the process stop after the first record when called from fn_NormalizeFoo() when the entire process runs when the contents of fn_NormalizeFoo() is run directly?
Some Code:
--------------------------------------------------------
-- Insert Into TableFoo --
--------------------------------------------------------
CREATE OR REPLACE FUNCTION "example"."fn_SetFoo" (
IN "Foo1" INTEGER,
IN "Foo2" INTEGER,
IN "Foo3" INTEGER
) RETURNS "void" AS
$$
BEGIN
INSERT INTO
"example"."TableFoo"(
"Foo1",
"Foo2",
"Foo3"
)
VALUES
(
$1,
$2,
$3
);
RETURN;
EXCEPTION WHEN "unique_violation" THEN
-- DO NOTHING
END;
$$
LANGUAGE plpgsql;
--------------------------------------------------------
-- Insert Into TableFooBar --
--------------------------------------------------------
CREATE OR REPLACE FUNCTION "example"."fn_SetFooBar" (
IN "FooPK" INTEGER,
IN "BarPK" INTEGER
) RETURNS "void" AS
$$
BEGIN
INSERT INTO
"example"."TableFooBar"(
"FooPK",
"BarPK"
)
VALUES
(
$1,
$2
);
RETURN;
EXCEPTION WHEN "unique_violation" THEN
-- DO NOTHING
END;
$$
LANGUAGE plpgsql;
--------------------------------------------------------
-- Trigger Function --
--------------------------------------------------------
CREATE OR REPLACE FUNCTION "example"."tr_SetFooBar"() RETURNS TRIGGER AS
$$
BEGIN
PERFORM
"example"."fn_SetFooBar"(
"TableFoo"."FooPK",
"TableBar"."BarPK"
)
FROM
"example"."TableFoo" JOIN
"example"."TableBar" ON [SOMETHING TRUE]
WHERE
NEW.SOMECOLUMN = SOMETHING AND
[MORE STUFF IS TRUE];
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
--------------------------------------------------------
-- Trigger --
--------------------------------------------------------
CREATE TRIGGER "SetFooBar" AFTER INSERT ON "example"."Foo" FOR EACH ROW EXECUTE PROCEDURE "example"."tr_SetFooBar"();
--------------------------------------------------------
-- Normalize Foo --
--------------------------------------------------------
CREATE OR REPLACE FUNCTION "example"."fn_NormaliseFoo" (
IN "Param1" VARCHAR,
IN "Param2" VARCHAR,
IN "Param3" VARCHAR
) RETURNS "void" AS
$$
SELECT
"example"."fn_SetFoo" (
"Foo1",
"Foo2",
"Foo3"
)
FROM
[TABLES]
WHERE
[STUFF IS TRUE]
$$
LANGUAGE SQL;
As you can see, this is a bit more complex then I originally posted. The general idea is to create a many to many relationship as each record is added.
Just to reiterate, running "example"."fn_NormaliseFoo" fails after the first row; however, manually running the contents works as expected.
fn_NormalizeFoo() is described as:
a separate function fn_NormalizeFoo() that processes
some data and then calls fn_SetFoo() for each record it has processed.
However, the code shown for fn_NormaliseFoo is declared in the SQL language so it's not procedural, and therefore it can't do what is claimed. It can just run one query and returns its results (or nothing if no results). Such code has to be compatible with inlining into the calling query.
So the first problem is that fn_NormaliseFoo is declared as returning void but it's not compatible with the fact that it's a SELECT. Normally the function creation shouldn't even be accepted by the interpreter of the sql language.
Example:
CREATE FUNCTION f(int) returns void as 'select $1;' language sql;
This fails with:
ERROR: return type mismatch in function declared to return void
DETAIL: Actual return type is integer.
A second problem would be that fn_SetFoo is likely to be called only once, which is what I understand from the question's "the process stop after the first record". Despite the call being in the select list of a query with some joined tables that presumably produce N rows, there's no reason that can be seen here for the SQL engine to call it N times. Better for it call it only once and affect the same result to every row formed as the output of the query.
It looks a bit like you're using sql in spite of plpgsql. To make sure that a function is call N times, loop N times in procedural code and that will be guaranteed to work.