These are the tables:
SQL> DESC pais;
Name Null? Type
----------------------------------------- -------- ----------------------------
COD_PAIS NOT NULL NUMBER(4)
NOMBRE VARCHAR2(30)
CAPITAL VARCHAR2(20)
EXTENSION NUMBER(10)
MONEDA VARCHAR2(20)
NUM_HAB NUMBER(10)
PIB NUMBER(20,2)
CONTINENTE VARCHAR2(20)
CASCOS CHAR(1)
SQL> DESC pertenece_a;
Name Null? Type
----------------------------------------- -------- ----------------------------
COD_ORGANIZACION NOT NULL NUMBER(10)
COD_PAIS NOT NULL NUMBER(4)
SQL> DESC organizacion;
Name Null? Type
----------------------------------------- -------- ----------------------------
COD_ORGANIZACION NOT NULL NUMBER(10)
NOMBRE VARCHAR2(80)
SIGLAS VARCHAR2(6)
I need to update the value cascos to S if siglas is ONU . If not, it has to be updated to N . This is my code. SQL Developer doesn't report any errors, however the C1 cursor change isn't updating. I must to use the cursors.
SET SERVEROUTPUT ON;
DECLARE
CURSOR C1 IS SELECT cascos FROM pais P, organizacion O, pertenece_a PE WHERE P.cod_pais=PE.cod_pais AND O.cod_organizacion=PE.cod_organizacion AND O.siglas='ONU' FOR UPDATE;
CURSOR C2 IS SELECT cascos FROM pais WHERE cascos IS NULL FOR UPDATE;
registro1 C1%ROWTYPE;
registro2 C2%ROWTYPE;
BEGIN
IF NOT C1%ISOPEN THEN
OPEN C1;
END IF;
IF NOT C2%ISOPEN THEN
OPEN C2;
END IF;
LOOP
FETCH C1 INTO registro1;
EXIT WHEN C1%NOTFOUND;
UPDATE pais SET cascos='S' WHERE CURRENT OF C1;
END LOOP;
LOOP
FETCH C2 INTO registro2;
EXIT WHEN C2%NOTFOUND;
UPDATE pais SET cascos='N' WHERE CURRENT OF C2;
END LOOP;
CLOSE C1;
CLOSE C2;
END;
/
SELECT * FROM pais WHERE cascos='S';
The SQL Developer output just says:
PL/SQL procedure successfully completed.
no rows selected
What could be the mistake? Could the problem be that a row of pais can be related to more than one row (siglas) of organizacion? For example:
NOMBRE SIGLAS
------------------------------ ------
Venezuela ONU
Venezuela OEA
Venezuela MS
Venezuela OPEP
Estados Unidos ONU
Estados Unidos OTAN
Estados Unidos OEA
Estados Unidos APEC
Estados Unidos OCDE
Estados Unidos OSCE
Estados Unidos TLCAN
Thank you.
It seems you want to update all pais
rows. Those with an ONU match get cascos = 'S'
, the others get cascos = 'N'
. You can use a mere update statement for this, which is even faster than using PL/SQL.
For instance:
update pais
set cascos =
case when cod_pais in (
select pe.cod_pais
from pertenece_a pe
join organizacion o using (cod_organizacion)
where o.siglas = 'ONU'
)
then 'S'
else 'N'
end;
can you please try this using two UPDATE statements.
UPDATE pais P SET cascos='S' WHERE EXISTS ( SELECT 1 FROM pais P, organizacion O, pertenece_a PE WHERE P.cod_pais=PE.cod_pais AND O.cod_organizacion=PE.cod_organizacion AND O.siglas='ONU');
UPDATE pais P SET cascos='N' WHERE nvl(cascos,'S')<>'S';
`
If all values of cascos
are null to begin with, then the updates in the second loop will overwrite the changes made in the first loop. The quick fix would be to open c2
after completing the first loop, instead of before it.
However, you could simplify the code as follows:
begin
for r in (
select p.cod_pais
from pais p
join pertenece_a pe on pe.cod_pais = p.cod_pais
join organizacion o on o.cod_organizacion = pe.cod_organizacion
where o.siglas = 'ONU'
and nvl(p.cascos,'?') <> 'S'
for update
)
loop
update pais set cascos = 'S'
where cod_pais = r.cod_pais;
end loop;
update pais set cascos = 'N' where cascos is null;
end;
A further refactoring would be to rewrite the whole thing as a single update
or merge
, and not have any explicit cursor handling or loops. It would also be more efficient because a single SQL statement is better than one per row, and you could avoid making two passes through pais
, although perhaps if this is a very small table it doesn't matter much.
By the way, you don't need to check IF NOT C1%ISOPEN
, because you've just declared c1
and not opened it, so it cannot possibly be open. Also it is good practice to use ANSI-style explicit join syntax, as it is harder to miss join conditions.
Also, you should be using the standard string type, varchar2
, for all character columns, and never char
. It is a common mistake to think that char
has some special advantage for short values, but it does not and using nonstandard types only leads to bugs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.