Create multiple stored procedure by running Postgresql script - postgresql

I wanted to execute a Postgresql scripts file in my vm containing 3 stored procedure. But only the first one gets executed. Any workaround for this? Scripts file:
alter table ex add column if not exists json_column jsonb;
alter table im add column if not exists json_column jsonb;
alter table imag add column if not exists json_column jsonb;
create or replace procedure update_ex( //first stored procedure
js jsonb,
id bigint
)
language plpgsql
as $$
begin
update ex set json_column = js where ex_id=id;
end;$$ // error: SQL Error [42601]: ERROR: syntax error at or near "create"
create or replace procedure update_im( //second stored procedure
js jsonb,
id bigint
)
language plpgsql
as $$
begin
update im set json_column = js where im_set_id=id;
end;$$
create or replace procedure update_imag(
js jsonb,
id bigint
)
language plpgsql
as $$
begin
update imag set json_column = js where imag_id=id;
end;$$

You missing a ";" at the end.
end;$$;

Related

Argument not taking the value from Postgres function

I have a simple Postgres function where I want to take table_name as a parameter and pass it into an argument and delete the data from table by condition.
CREATE OR REPLACE FUNCTION cdc.audit_refresh(tablename text)
RETURNS integer AS
$$
BEGIN
delete from tablename where id<4;
RETURN(select 1);
END;
$$ LANGUAGE plpgsql;
select cdc.audit_refresh('cdc.adf_test');
But it throws out an error that tablename
ERROR: relation "tablename" does not exist in the delete statement.(refer snapshot)
What you want to achieve is to execute Dynamic SQL statements. You can do this with EXECUTE. See more here
CREATE OR REPLACE FUNCTION audit_refresh(tablename text)
RETURNS integer AS
$$
DECLARE
stmt TEXT;
BEGIN
stmt = 'delete from '||tablename||' where id<4;';
EXECUTE stmt;
RETURN 1;
END
$$ LANGUAGE plpgsql;

Calling the column in call method in PostgreSQL

Why is not working for executing the alter table in stored procedure? I tried everything but nothing is working
CREATE OR REPLACE PROCEDURE change_datatypes(columnname VARCHAR(255), datatype VARCHAR(255))
language plpgsql
as $$
BEGIN
EXECUTE
ALTER TABLE public.Sales_2019 ALTER COLUMN columnname TYPE datatype USING columnname :: datatype;
END $$;
CALL change_datatypes(Sales_2019.orderid, 'INTEGER') FROM Sales_2019;
UPDATED
CREATE OR REPLACE PROCEDURE change_datatypes(column_name VARCHAR(255), datatype VARCHAR(255))
language plpgsql
as $$
BEGIN
EXECUTE('ALTER TABLE Sales_2019 ALTER COLUMN'
|| quote_ident(column_name)
||'TYPE' || quote_literal(datatype) || 'USING '
||quote_ident(column_name) || '::'
||quote_literal(datatype));
END $$;
CALL change_datatypes(OrderID, INTEGER);

How to insert declared type variable into table | Postgress

I have been working on creating a store procedure that will select data from a table, do some modification to that data, and then I need to insert that modified data into the same table. Take an example my table name is student. My procedure looks like below:
create or replace procedure student_create(p_code varchar)
language plpgsql
as $$
declare
v_student public.student;
begin
select * into v_student from student where code = p_code and is_latest_version is true;
raise notice 'Value: %', v_student;
v_student.id = uuid_generate_v4();
v_student.version_created_at = now();
v_student.version_updated_at = v_student.version_created_at;
raise notice 'Value: %', v_student;
INSERT INTO public.student VALUES(v_student);
end;$$
I am getting errors while calling this procedure:
ERROR: column "id" is of type uuid but expression is of type hotel
LINE 1: INSERT INTO public.hotel VALUES(v_hotel)
I know I can make insert statements like I can get each value from the variable and set it like
INSERT INTO public.student VALUES(v_student.id, v_student.code, v_student.name);
But I don't want to do that because it will become tightly coupled and later if I add another column into the table then I need to add that column into this procedure as well.
Does anyone have idea how can I insert the declared type variable directly into table.
There is no table type, there is only row composite type. Check manual 43.3.4. Row Types.
use row type.
create or replace procedure student_create(p_code text)
language plpgsql
as $$
declare
v_student public.student
begin
for v_student in select * from student where code = p_code and is_latest_version is true
loop
v_student.id = uuid_generate_v4();
v_student.version_created_at = now();
v_student.version_updated_at = v_student.version_created_at;
v_student.is_latest_version = true;
v_student.code = p_code;
INSERT INTO student VALUES(v_student.*);
end loop;
end;$$;
call it: call student_create('hello');
3. use update clause directly.
create or replace procedure student_create_1(p_code text)
language plpgsql as $$
BEGIN
with a as ( select uuid_generate_v4() as id ,
now() as version_created_at,
now() as version_updated_at,
p_code as "code" from student
where code = p_code and is_latest_version is true)
INSERT INTO student(id, version_created_at, version_updated_at, code)
select a.id, a.version_created_at,a.version_updated_at,a."code" from a;
end
$$;
call it: call student_create_1('hello');
fiddle code: here

psql , creating stored procedure - converting string to schema type

I have a stored producedure that does this, my_schema is the name of the current schema I'm using in my db.
CREATE OR REPLACE myprocedure(data TEXT) LANGUAGE plpgsql AS $$
DECLARE
my_variable my_schema.my_table%ROWTYPE;
BEGIN
SELECT * FROM my_schema.my_table WHERE oid=3;
END;
$$;
But, I need this to be a bit more generic, and I'd like to use this for any schema I create in my db, so, I'd like to pass in the schema name instead like this, so that I won't have to create a procedure for every schema created in the future:
note I've used angle brackets for syntax I'm not sure of:
CREATE OR REPLACE myprocedure(data TEXT, my_schema_name <SOME_TYPE>) LANGUAGE plpgsql AS $$
DECLARE
my_variable <my_schema_name>.my_table%ROWTYPE;
BEGIN
SELECT * FROM <my_schema_name>.my_table WHERE oid=3;
END;
$$;
and then call it like this:
CALL myprocedure('SOMETHIGN', <MY_SCHEMA_NAME>);
what is the correct syntax to do this?
You can use the record type for a generic record, and you use dynamic SQL for the query. Here is an example:
CREATE PROCEDURE x(schema_name text) LANGUAGE plpgsql AS
$$DECLARE
q record;
BEGIN
EXECUTE format(
'SELECT * FROM %I.data WHERE id = 1',
schema_name
) INTO q;
RAISE NOTICE '%', q.id;
END;$$;

Create a new Table with pgsql

I want to create a new table with plpgsql, but I want that the user gives the name of the table.My code generate a table with the name of tbname
this is my code:
CREATE OR REPLACE FUNCTION "Object_gen"(tablename text)
RETURNS void AS
$BODY$DECLARE
tbname text;
BEGIN
tbname:=tablename;
CREATE TABLE tbname(Surrogat uuid);
END$BODY$
LANGUAGE plpgsql;
How can I solve my problem? somehow that the name of my table comes from the user
You need to use dynamic SQL:
CREATE OR REPLACE FUNCTION "Object_gen"(tablename text)
RETURNS void AS
$BODY$
BEGIN
execute 'CREATE TABLE '||tablename||' (Surrogat uuid)';
END
$BODY$
LANGUAGE plpgsql;