Oracle SQL multiple PL-SQL - oracle18c

I am new to oracle sql and learning how to use PL-SQL.
Right now, I am trying to run two procedures to insert values into the table.
Each procedures run perfectly fine, inserting the value.
However, error occurs when I am running those two procedure at once.
It returns error of "ORA-06550" I am looking for the solution, yet have not found any
Declare
type array_p is varray(4) of varchar(30);
pArray array_p := array_p('pink', 'blue', 'midnight', 'starlight');
begin
for i in 1..pArray.count loop
insert into specifications
values(spec_seq.NextVal, 1, 'A15 Bionic', '128', '6.1', '5G', 173, pArray(i), 180, 10);
end loop;
end;
Declare
type array_p is varray(4) of varchar(30);
pArray array_p := array_p('pink', 'blue', 'midnight', 'starlight');
begin
for i in 1..pArray.count loop
insert into specifications
values(spec_seq.NextVal, 1, 'A15 Bionic', '256', '6.1', '5G', 173, pArray(i), 190, 10);
end loop;
end;
Is it bad to make multiple procedures and use it at once? I though procedures are like method in java.

Related

how to write select statement inside if in PostgreSQL

I'm trying to write select statement inside if in PostgreSQL but getting error like ERROR: syntax error at or near "SELECT" please help me to solve this error
LINE 39: SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
BEGIN
if p_mobile_no=usersdefotp_mobile_no
then
P_OTP :='123456'
else
SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
P_OTP :=LPAD(W_OTPNUM::TEXT, 6, '0');
INSERT INTO usersdefotp(P_OTP)
end if
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_OTP := NULL;
END;
You can use declarations in a Procedure as an Array on PostgreSQL, like this one:
do $$
declare
randoms text[];
begin
-- store data
randoms = ARRAY(SELECT random()*power( 10, 8 ) INTO STRICT W_OTPNUM;
P_OTP :=LPAD(W_OTPNUM::TEXT, 6, '0'));
if something
then
do something
else
return format("%s", randoms)
end if;
end
$$;
That way you can store your select and then use him when needed to return;

Wrong schema while importing data via with ogr2ogr into postgresql database and using dblink

I have the following issue:
I have a table on a PostgreSQL database which triggers its changes via dblink to another table in a different data base. The trigger funktion looks as follows:
CREATE OR REPLACE FUNCTION scheme.triggerfunctionname()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
str_execute text;
BEGIN
IF (TG_OP = 'INSERT') THEN
str_execute := dblink_build_sql_insert('schema.table'::text, '1', 1, ARRAY[NEW.gid]::text[], ARRAY[NEW.gid]::text[]);
ELSIF (TG_OP = 'UPDATE') THEN
str_execute := dblink_build_sql_update('schema.table'::text, '1', 1, ARRAY[NEW.gid]::text[], ARRAY[OLD.gid]::text[]);
ELSIF (TG_OP = 'DELETE') THEN
str_execute := dblink_build_sql_delete('schema.table'::text, '1', 1, ARRAY[OLD.gid]::text[]);
END IF;
PERFORM dblink_exec('map', str_execute);
RETURN NULL;
END; $function$
;
The triggering works well if I am doing the changes right at the database.
But now I have the case, that I want to insert data in the main table via ogr2ogr from a WFS service.
In this case the trigger function does not work correctly, because it does the INSERT on public.tablename and not on schema.tablename.
So the insert via ogr2ogr in the main table works well but after that the syncronisation via the trigger function goes wrong.
Any ideas how to deal with this? Is there a difference between "selfmade" inserts on the table and inserts which come from another place (in this case ogr2ogr)?
Thanks for any help!

Postgresql: Check if Value exists in a table through Trigger

I am getting acquainted with Triggers in (Postgre)sql.
What I have now is a table Verine (which is teams in german).
Vereine :{[team:string, punkte:int, serie:int]}
This is a very very small thing I wrote just to understand how creating tables, sorting stuff and views work and now I'm using it for triggers. Anyway, team is team obviously the name of the team and primary key, punkte means points and serie refers to the division of the team (just so you understand what the different domains mean).
Problem starts here:
So assume I have a team, let's say "Juventus", already in my table "Vereine". If I then want to insert another row/tuple that has the same key "Juventus", instead of wanting two entries for them, what I'd like is to update the values for key "Juventus" (replacing new values with old ones). In the example below I try to do that with points.
create table vereine(
team varchar(20) primary key,
punkte int not null,
serie int not null
)
--beispiel was die Aufgabe verlangt
create trigger prevent_redundancy
before insert on vereine
for each row
execute procedure update_points()
create or replace function update_points()
returns trigger as
$BODY$
begin
if (new.team in (old.team)) then
update vereine
set punkte = new.punkte
where team = new.team;
else
end if;
end;
$BODY$
LANGUAGE plpgsql;
--Was die aufgabe verlangt ist, dass keine bereits existierende ID eingefügt wird,
--sondern der entsprechende Modellname dann umgeändert wird
insert into vereine values('JuventusFC', 50, 1);
insert into vereine values('AS Roma', 30, 1);
insert into vereine values('ParmaCalcio1913', 25, 1);
insert into vereine values('Palermo', 37, 2);
insert into vereine values('Pescara', 32, 2);
insert into vereine values('Spezia', 26, 2);
insert into vereine values('Carrarese Calcio', 34, 3);
insert into vereine values('Virtus Entella', 31, 3);
insert into vereine values('Juventus U-23', 50, 3);
select *
from vereine
insert into vereine values('JuventusFC', 53, 1);
Here are my problems:
First of all: How would I check if a key already exists in the table? In queries, I would use things like case when, where in or just approach the problem differently. Do I need if statements here? In other words, how would you rewrite
if (new.team in (old.team)) then
so that it checks if it already exists in there?
Secondly: This may be related to the first problem: I get this when trying to insert any tuple:
Query execution failed
Reason:
SQL Error [54001]: ERROR: stack depth limit exceeded
Hint: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
Where: SQL statement "insert into vereine values(new.team, new.punkte, new.serie)"
How can I fix my code so that it does what I want it to do?
Sorry for being too wordy. I just want to make sure you understand how this is supposed to work. Yes, Ive asked a question before related to the same assignment but this is a whole different problem. Sorry for that as well.
What you basically want is an UPSERT syntax, as shown in this answer using a UNIQUE CONSTRAINT on team column. I would suggest you to use this for your insert operation in the relevant function, instead of a trigger.
If you still insist on using a trigger, you could write something like this.
create or replace function update_points()
returns trigger as
$BODY$
begin
if EXISTS (select 1 FROM vereine WHERE team = new.team ) then
update vereine
set punkte = new.punkte
where team = new.team;
RETURN NULL;
else
RETURN NEW;
end if;
end;
$BODY$
LANGUAGE plpgsql;
The difference between RETURN NULL; and RETURN NEW; in a Trigger returning procedure and a Before Insert Trigger is that RETURN NULL won't execute the triggering statement( i.e the main INSERT operation ), whereas RETURN NEW; continues with the intended INSERT statement execution normally.
Demo
Now, coming to your error SQL Error [54001]: ERROR: stack depth limit exceeded,
it appears that you have another trigger already created on the table that is triggered by the update operation or you have written another insert and returning NEW from the Trigger. You have to take a call on how to handle if it's another trigger( either to drop it or modify it, but that's beyond the scope of this question, and you should ask it separately if you have further issues)
You can check the existence of Triggers on the table by simply querying the information_schema.triggers or pg_trigger , Refer to this answer for more details.

PostgreSQL - finding text values that are not valid JSON

Casting a text value that doesn't contain valid JSON to JSON just bombs out the statement. I have no idea which row or value. How do I get this?
Fingers crossed that it doesn't involve a UDF... I really don't want to inject these into our stack. (We use Ruby Rails ActiveRecord for database migrations, and I'm almost certain UDFs will not be recorded into schema.rb.)
you an check values with exception to find rows, eg:
t=# do
$$
declare _r record;
begin
for _r in (with j as (select * from (values ('3'),('{"valid":true}'),('notValid') ) as son) select column1 v from j) loop
begin
perform _r.v::json;
exception when others then raise info '%',concat(_r.v,' ',SQLSTATE);
end;
end loop;
end;
$$
;
INFO: notValid 22P02
DO
t=# \e
INFO: test3 22P02
INFO: notValid 22P02
DO

Commit, savepoint, rollback to in PostgreSQL?

Can someone please explain to me why does COMMIT in this function returns EXCEPTION ?
DECLARE
XNar CURSOR (forDATE Varchar) IS
SELECT NARUCENO, ISPORUKA_ID FROM XDATA_NARUDZBE
WHERE TO_CHAR(XDATA_NARUDZBE.DATUM, 'DD.MM.YYYY') = forDATE;
LastDate DATE;
OutResult INTEGER;
curNAR NUMERIC;
curISP VARCHAR;
RXNar RECORD;
BEGIN
OutResult := 1;
SELECT MAX(DATUM) INTO LastDate FROM XDATA_NARUDZBE;
FOR RXNar IN XNar(TO_CHAR(LastDate, 'DD.MM.YYYY')) LOOP
IF (RXNar.NARUCENO <> 0) AND (RXNar.ISPORUKA_ID = 'R01') THEN
UPDATE NARUDZBE SET ISPORUCENO = RXNar.NARUCENO
WHERE NARUDZBE.PP_ID = RXNar.PP_ID
AND NARUDZBE.ART_ID = RXNar.ART_ID
AND NARUDZBE.ISPORUKA_ID = 'R01';
END IF;
END LOOP;
COMMIT; <--- ????
RETURN OutResult;
EXCEPTION
WHEN OTHERS THEN
OUTRESULT := 0;
RAISE;
RETURN OutResult;
END;
and why I can not use ROLLBACK TO SavePoint when EXCEPTION block exists in function?
You can't use COMMIT in a stored procedure, the entire procedure is a transaction of it's own.
You can't commit in a plpgsql stored function/procedure using plpgsql as Frank Heikens answered. You can however work around this issue by using dblink(http://www.postgresql.org/docs/9.0/interactive/contrib-dblink-connect.html) or another store procedure language such as plperl(untrusted). Check out this link where this talked about.
http://postgresql.1045698.n5.nabble.com/Re-GENERAL-Transactions-within-a-function-body-td1992810.html
The high level is you open a new connection using one of these methods and issue a separate transaction on that connection. Works for most cases not ideal because you are opening a new connection, but may work fine for most use cases.
Begin with PostgreSQL11 there is an procedure module.
Demo based on Manual.
CREATE OR REPLACE PROCEDURE insert_data_drop(_a integer, _b integer)
LANGUAGE plpgsql
AS $$
begin
INSERT INTO tbl(a) VALUES (_a);
INSERT INTO tbl(b) VALUES (_b);
Rollback;
INSERT INTO tbl(a) VALUES (_a);
end
$$;
Now CALL insert_data_drop(1, 2); will insert 1 to column a, 2 will not be saved.
However, SAVEPOINT seems not working. It will show error like:
ERROR: unsupported transaction command in PL/pgSQL
CONTEXT: PL/pgSQL function insert_data_drop(integer,integer) line 5 at SQL stateme