How to browse an query id not follow PostgreSQL - sql

I need your help about an modification of my actual code. Here it is :
\timing on
DO $$
BEGIN
DECLARE
i INT := 1; -- valeur de départ à changer pour la range d'id
j INT := i + 1;
numberUsers INT; -- Changer valeur numberUsers pour fin de la range d'id
commonSkills INT;
random INT;
idSphere INT := 2;
BEGIN
SELECT COUNT(*) INTO numberUsers FROM "WU_Users"; -- si numberUSers est modifié, commentez la ligne
WHILE i < numberUsers LOOP
WHILE j <= numberUsers LOOP
IF i !=j THEN
SELECT floor(random() * 10 + 35)::INT INTO random;
INSERT INTO "WU_MatchingUsers"("IDWU_User1", "IDWU_User2", "MatchingScore")
VALUES(i, j, random)
ON CONFLICT ("id")
DO
UPDATE SET "MatchingScore" = EXCLUDED."MatchingScore";
ELSE
RAISE NOTICE 'Same Users';
END IF;
j := j + 1;
END LOOP;
j := i + 1;
RAISE NOTICE 'i: %', i;
i := i + 1;
END LOOP;
END;
END $$;
\timing off
So this code take two id, and with two loops "browse" from i to numberUsers and insert into another table a random matching score, now I need to add this :
SELECT "IDWU_Users_WU_Users" FROM "WU_UsersSpheres" WHERE "IDWU_UsersSpheres" = idSphere;
This line return me a list of id from another table that I need to match, like the script above I match in this order :
1/2
1/3
etc etc
But now this new line can return me id like that :
532
1426
3236
84697
And I need to make the same matching system than before so like that :
532/1426
532/3236
532/84697
Kind Regards !

Related

How to fix LOOP error PostgreSQL while trying to Select

Here is the code I'm Testing :
DO $$
DECLARE
i INT := 0;
BEGIN
WHILE i <= numberUsers
BEGIN
SELECT COUNT(*) FROM "Users";
SET i := i + 1;
END;
END $$;
But when I try to execute it it return me this error :
ERREUR: « LOOP » manquant à la fin de l'expression SQL
LIGNE 7 : SELECT COUNT(*) FROM "Users";
Kind Regards !
You have considerable structural errors in your code block:
DO $$
DECLARE
i INT := 0;
BEGIN
WHILE i <= numberUsers --<<< numberUsers is undefined and uninitialized
BEGIN --<<< this starts a nested block should be LOOP
SELECT COUNT(*) FROM "Users"; --<<< in a block you must tell plpgsql what to do with the result
SET i := i + 1; --<<< assignment does not use SET in plpgsql
END; --<<< terminated nested block, should terminate loop
END $$;
Correcting all the points from the block becomes:
do $$
declare
i int := 0;
numberusers int;
begin
select count(*)
into numberusers
from "users";
while i <= numberusers
loop
i := i + 1;
end loop;
end $$;
Per:
https://www.postgresql.org/docs/current/plpgsql-control-structures.html#PLPGSQL-CONTROL-STRUCTURES-LOOPS
WHILE boolean-expression LOOP
statements
END LOOP [ label ];
You need the LOOP END ... LOOP portions of the statement.
The error message tells you that something is missing from the expression, which is a clear indication that you have a syntax error. Try this code:
DO $$
DECLARE
i INT := 0;
BEGIN
WHILE i <= numberUsers LOOP
BEGIN
SELECT COUNT(*) FROM "Users";
SET i := i + 1;
END LOOP;
END $$;
Read more here: https://www.postgresqltutorial.com/plpgsql-while-loop/
DO $$
BEGIN
DECLARE
i INT := 0;
BEGIN
WHILE i <= numberUsers LOOP
SELECT COUNT(*) FROM "WU_Users";
i := i + 1;
END LOOP;
END $$;
But it's returning me this now :
psql:matching.sql:12: ERREUR: label de fin « matching » spécifié pour un bloc sans label
LIGNE 12 : END matching $$;

ORA-06502: PL/SQL: numeric or value error: character string buffer too small only three numbers

create or replace FUNCTION "FNC_CALCULATE_MOD11" (P_VALOR IN NUMBER)
return number is
Result number;
begin
DECLARE
-- LOCAL VARIABLES HERE
V_PROCESSO VARCHAR2(30);
V_PESO NUMBER := 2;
V_SOMA NUMBER := 0;
V_RESTO NUMBER := 0;
BEGIN
V_PROCESSO := TO_CHAR(P_VALOR);
WHILE LENGTH(V_PROCESSO) < 6 --Popular com zeros no inicio até 6
LOOP
V_PROCESSO := '0'||V_PROCESSO;
END LOOP;
--accuses error on this line
FOR I IN REVERSE 1 .. LENGTH(V_PROCESSO)
LOOP
V_SOMA := TO_CHAR (V_SOMA) + TO_NUMBER(SUBSTR(V_PROCESSO,i,1))*V_PESO;
IF V_PESO = 9 THEN --repetir peso se for necessario
V_PESO := 2;
ELSE
V_PESO := V_PESO + 1;
END IF;
END LOOP;
V_RESTO := MOD(V_SOMA, 11);
Result := 11 - V_RESTO;
IF ((Result = 0) OR (Result = 1) OR (Result >= 10)) THEN
Result := 1;
END IF;
END;
return(Result);
end FNC_CALCULATE_MOD11;
Try to change V_PROCESSO to a bigger size, for example V_PROCESSO VARCHAR2(300);

Creating a Procedure with Oracle

im trying to get a job (ORACLE SHEDULER) done in oracle every week.
The point is to loop through the 'Historico' table every week, and check every 'ID_Academista' that is linked to the
'Academista' Table. After that it should compare 'Valor_Atual' to see if its > 20 (it comes from the table 'Tecnologia')
If so, it decrements by 1, if not, it stays the same.
To put it in better english: Every 'Tecnologia' Is a technology, each technology has a individual grade(Valor_Atual)
That will be inside the 'Academista'(student)
Table Historico
Database
Here is the code :
CREATE OR REPLACE PROCEDURE notas
IS
contar INTEGER := 0;
contar2 INTEGER;
BEGIN
SELECT COUNT(*) INTO contar2 FROM Academista;
WHILE contar <= contar2
LOOP
SELECT h.Valor_Atual, h.Valor_Antigo, h.Id_academista FROM HISTORICO h
WHERE h.Id_academista = contar ;
IF
h.Valor_Atual > 20
THEN
UPDATE HISTORICO
SET Valor_Atual = Valor_Atual + 1
WHERE h.Id_academista = contar;
ELSE
UPDATE HISTORICO
SET Valor_Atual = Valor_Atual - 1
WHERE h.Id_academista = contar ;
SET contar := contar + 1;
END IF;
END LOOP;
END;
Errors
You can't use selects inside a pl/sql block without a variable.
CREATE OR REPLACE PROCEDURE notas
IS
contar INTEGER := 0;
contar2 INTEGER;
h_var HISTORICO%rowtype;
BEGIN
SELECT COUNT(*) INTO contar2 FROM Academista;
WHILE contar <= contar2
LOOP
SELECT h.* into h_var FROM HISTORICO h
WHERE h.Id_academista = contar ;
IF
h_var.Valor_Atual > 20
THEN
UPDATE HISTORICO
SET Valor_Atual = Valor_Atual + 1
WHERE h_var.Id_academista = contar;
ELSE
UPDATE HISTORICO
SET Valor_Atual = Valor_Atual - 1
WHERE h_var.Id_academista = contar ;
SET contar := contar + 1;
END IF;
END LOOP;
END;

Multiple FORALL in a orasql procedure

Im trying to both delete then update some data from a table inside a procedure. It is my understanding that both can't be done in the same FORALL statement and that I can do multiple FORALL using the same cursor. The problem is that the second FORALL does not seem to do anything. Is there something that im not getting? Here is the code :
cursor cPARTY is
SELECT /* +parallel(4) */ DISTINCT p.ID,
CASE WHEN sf.PARTYID is null THEN 'delete'
ELSE 'switch'
END AS action,
pa.SOURCESYSTEMLID as sources
FROM CV_CLAIMS_TRAVEL.EPUR_PARTY p
LEFT JOIN CV_CLAIMS_TRAVEL.STAR_FILE sf ON sf.PARTYID = p.ID
LEFT JOIN CV_CLAIMS_TRAVEL.PARTY pa ON pa.ID = p.ID;
type type_party is TABLE OF cPARTY%ROWTYPE INDEX BY PLS_INTEGER;
t_party type_party;
nLOT pls_integer := 1;
nbDeleted int :=0;
nbSwitched int := 0;
begin
p_tableName := 'PARTY(INDIVIDU)';
allBEGIN_TIMESTAMP := systimestamp;
open cPARTY;
loop
lotBEGIN_TIMESTAMP := systimestamp;
dbms_application_info.set_module('CV_CLAIMS_TRAVEL.PARTY',trim(to_char(nLOT * nLIMIT,'999G999G999')));
FETCH cPARTY BULK COLLECT
INTO t_party
limit nLIMIT;
exit when t_party.count = 0;
p_nbLinesTransfered :='Erreur: Suppression de données';
dbms_application_info.set_module('CV_CLAIMS_TRAVEL.PARTY - DELETING',trim(to_char(nLOT * nLIMIT,'999G999G999')));
FORALL i IN t_party.FIRST .. t_party.LAST
DELETE /*+parallel(4)*/ FROM CV_CLAIMS_TRAVEL.PARTY
WHERE ID = t_party(i).ID
AND t_party(i).action = 'delete';
nbDeleted := nbDeleted + sql%rowcount;
FORALL i IN t_party.FIRST .. t_party.LAST
UPDATE CV_CLAIMS_TRAVEL.PARTY
SET UPDATEDATE = sysdate, SOURCESYSTEMLID = 'SOURCE_SYSTEM:0000000000', UPDATEDBYUSERID = 'CV_CLAIM_INTEG'
WHERE ID = t_party(i).ID
AND t_party(i).sources='SOURCE_SYSTEM:0000000004'
AND t_party(i).action = 'switch';
nbSwitched := nbSwitched + sql%rowcount;
commit;
lotEND_TIMESTAMP :=systimestamp;
trc.trc_message('lotELAPSED '||to_char(nLOT * nLIMIT,'999G999G990')||' Rows. ELAPSED '|| replace(substr(to_char(lotEND_TIMESTAMP - lotBEGIN_TIMESTAMP, 'HH24:MI:SS.FF3'),1,20),'+000000 ','+'));
nLOT := nLOT + 1;
end loop;
close cPARTY;
commit;
gather_stats('CV_CLAIMS_TRAVEL', 'PARTY');

PLSQL Printing prime numbers

I want to print prime numbers between 1 to 50. But I don't understand what I am doing wrong in my code. After BEGIN, SQLDeveloper says I had an error because it expected another sign and not = .
SET SERVEROUTPUT ON
DECLARE
i NUMBER;
counter NUMBER;
n NUMBER;
k NUMBER;
BEGIN
i := 2;
counter := 0;
n := 50;
k := n/2;
FOR i IN 1..k LOOP
IF (n%i := 0 ) THEN
counter := 1;
END IF;
IF (counter := 0) THEN
DBMS_OUTPUT.PUT_LINE(n||' is prime number');
END IF;
END LOOP;
END;
SET SERVEROUTPUT ON
DECLARE
i NUMBER;
counter NUMBER;
n NUMBER;
k NUMBER;
BEGIN
i := 2;
counter := 0;
n := 50;
k := floor(n/2);
FOR i IN 1..k LOOP
IF (mod(n, i) = 0 ) THEN
counter := 1;
END IF;
IF (counter = 0) THEN
DBMS_OUTPUT.PUT_LINE(n||' is prime number');
END IF;
END LOOP;
END;
k := n/2; -- added FLOOR (k is NUMBER, by default it's NUMBER(38, max_scale))
IF (n%i := 0 ) THEN -> IF (mod(n, i) = 0 ) THEN
Oracle has MOD function for remainder + to compare you need to use =,
:= is for assignment.
DECLARE
counter NUMBER;
k NUMBER;
BEGIN
FOR n IN 1..50 LOOP
counter := 0;
k := floor(n/2);
FOR i IN 2..k LOOP
IF (mod(n, i) = 0 ) THEN
counter := 1;
END IF;
END LOOP;
IF (counter = 0) THEN
DBMS_OUTPUT.PUT_LINE(n||' is prime number');
END IF;
END LOOP;
END;
In your IF clause you are assigning the value instead of comparison. You are using := operator, where you shd be using =
It shud be like (IF counter = 0) then
......
Also I dont think n%i would work, you could do IF (trunc(n) = n) then ... or IF (mod (n,i) =0) then ...
--this function is check prime number.
create or replace function prime_a(x number) return
varchar2 is
n integer;
ans varchar2(50);
begin
n:=(x/2);
for i in 2..n loop
if mod(x,i)=0
then ans:='not a prime';
exit;
else ans:='prime';
end if;
end loop;
return ans;
end;
/
step-1:
create table tob(prime number);
step-2:
create or replace procedure ro(m number,n number)
is
a integer;
co Boolean;
begin
for j in m..n loop
co:=false;
co:=(j=1 );
a:=(j/2);
for i in 2..a loop
co:=(mod(j,i)=0);
exit when co;
end loop;
if(not co) then
insert into tob values(J);
end if;
end loop;
commit;
end;
/
step-3:
exec ro(1,50);
step-4: check:-
select * from tob;
You should create or replace in your source code:
function prime_a(x number) return
varchar2 is
n integer;
ans varchar2(50);
begin
n:=(x/2);
for i in 2..n loop
if mod(x,i)=0
then ans:='not a prime';
exit;
else ans:='prime';
end if;
end loop;
return ans;
end;
/
Why don't you just check for previous prime divisibility?
create table prime (primeno bigint)
declare #counter bigint
set #counter = 2
while #counter < 1000000
begin
if not exists(select top 1 primeno from prime where #counter % primeno = 0)
insert into prime select #counter
set #counter = #counter + 1
end
select * from prime order by 1
You could certainly cap the numbers you are checking against in the where condition to reduce your overheads further.
declare
i number;
j number;
k number:=0;
begin
for i in 1..50
loop
for j in 2..i-1
loop
if mod(i,j)=0 then
k:=1;
exit;
end if;
end loop;
if k=0 then
dbms_output.put_line(i);
end if;
k:=0;
end loop;
end;
/
create or replace function prime_a(x number) return varchar2 is
n integer;
ans varchar2(50);
begin
n:=(x/2);
for i in 2..n loop
if mod(x,i)=0 then
ans:='not a prime';
exit;
else
ans:='prime';
end if;
end loop;
return ans;
end;
/