How to dbms_output.put_line in Oracle - oracle

The result doesn't show the command ROUND(SYSDATE - V_FECHA,1) by dbms_output.put_line, I have this script:
SET SERVEROUTPUT ON
DECLARE
v_fecha v$database.created%TYPE;
BEGIN
CASE
WHEN ( SYSDATE - v_fecha <= 50 ) THEN
dbms_output.put_line('LA FECHA DE CREACION DE LA BASE DE DATOS ES <= 50 DÍAS');
WHEN ( SYSDATE - v_fecha > 50 AND SYSDATE - v_fecha <= 100 ) THEN
dbms_output.put_line('LA FECHA DE CREACIÓN ES MAYOR QUE 50 DÍAS O <= 100 DÍAS');
ELSE
dbms_output.put_line('LA FECHA DE CREACIÓN ES IGUAL A '
|| round(SYSDATE - v_fecha,1)
|| ' DÍAS');
END CASE;
END;
/
OUTPUT:
LA FECHA DE CREACIÓN ES IGUAL A DÍAS.
Oracle Version: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
IDE: SQL DEVELOPER - Versión 4.1.1.19
Thanks.

The output of the command ROUND(SYSDATE - V_FECHA,1) is not shown, because V_FECHA is still NULL in your code. You can verify that with
SELECT ROUND(SYSDATE - NULL) FROM DUAL;
which doesn't show anything, too. Nearly every operation in SQL will output NULL if the input contains NULL values, and DBMS_OUTPUT shows then an empty string.
As #Kaushik suggested, if you add the SELECT to your code, and maybe something that catches NULL values, everything should be fine:
DECLARE
v_fecha v$database.created%TYPE;
delta NUMBER;
BEGIN
SELECT created INTO v_fecha FROM v$database;
delta := v_fecha - SYSDATE;
CASE WHEN delta <= 50 THEN
dbms_output.put_line('LA FECHA DE CREACION DE LA BASE DE DATOS ES <= 50 DÍAS');
WHEN delta > 50 AND delta <= 100 THEN
dbms_output.put_line('LA FECHA DE CREACIÓN ES MAYOR QUE 50 DÍAS O <= 100 DÍAS');
WHEN delta IS NULL THEN
dbms_output.put_line('LA FECHA DE CREACIÓN ES DESCONOCIDA');
ELSE
dbms_output.put_line('LA FECHA DE CREACIÓN ES IGUAL A '
|| NVL(round(SYSDATE - v_fecha,1), 0)
|| ' DÍAS');
END CASE;
END;
/
I put in two options, WHEN delta IS NULL and NVL to show you different possibilities.
Furthermore I try to call SYSDATE only once, as every call of SYSDATE might be slightly later than the previous one. (The difference is of course very little, but I am trying to prevent errors which occur very rarely but are then very difficult to find.)

You probably want to fetch from v$database. Add this after BEGIN
SELECT
created
INTO v_fecha
FROM
v$database;

Related

PLS-00049: bad bind variable 'X_VARIABLE'

I'm getting the following error when I trying to get a record from a table, in this case, is (SERVICIOENDIAS)/SERVICETIMEINDAYS and I don't know why I'm getting that errr :
Trigger TRG_CONTROL_SERVICIO compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
20/11 PLS-00049: bad bind variable 'NEW.V_SERVICIODIAS'
Errors: check compiler log
I'm a dummy with Oracle and possibly I may do a lot of mistakes and bad practices, so I'll appreciate it if you can say me that.
CREATE OR REPLACE TRIGGER TRG_CONTROL_SERVICIO
BEFORE
INSERT OR UPDATE
ON SERVICIO
FOR EACH ROW
DECLARE
V_SERVICIODIAS INT;
CURSOR C_SERVICIODIAS IS
SELECT TIEMPOSERVICIODIAS INTO V_SERVICIODIAS
FROM SERVICIO;
BEGIN
FOR R_SERVICIODIAS IN C_SERVICIODIAS LOOP
IF INSERTING THEN
IF :NEW.FECHAREGISTRO > SYSDATE THEN
LOG_AUDIT( USER,
SYSDATE,
'SERVICIO',
'INSERT FECHA INCORRECTA',
'SE EJECUTO EL TRG_CONTROL_SERVICIO');
RAISE_APPLICATION_ERROR(-20000, 'FECHA INCORRECTA, INTENTE DE NUEVO');
ELSE
DBMS_OUTPUT.PUT_LINE('INSERTANDO UN SERVICIO');
END IF;
IF :NEW.V_SERVICIODIAS <= 60 THEN
DBMS_OUTPUT.PUT_LINE('INSERTANDO UN SERVICIO');
ELSE
LOG_AUDIT( USER,
SYSDATE,
'SERVICIO',
'NO SE PUEDE UN SERVICIO MAYOR A 60 DIAS',
'SE EJECUTO EL TRG_CONTROL_SERVICIO');
RAISE_APPLICATION_ERROR(-20000, 'NO SE PUEDE REGISTRAR EL SERVICIO, MUCHAS HORAS',TRUE);
END IF;
ELSIF UPDATING THEN
IF :NEW.FECHAREGISTRO <> :OLD.FECHAREGISTRO AND :NEW.FECHAREGISTRO > SYSDATE THEN
LOG_AUDIT( USER,
SYSDATE,
'SERVICIO',
'PROHIBIDO UPDATE FECHAREGISTRO',
'SE EJECUTO EL TRG_CONTROL_SERVICIO');
RAISE_APPLICATION_ERROR(-20000, 'FECHA INCORRECTA, NO SE PUEDE MODIFICAR ESTA FECHA',TRUE);
ELSE
DBMS_OUTPUT.PUT_LINE('ACTUALIZANDO UN EMPLEADO');
END IF;
END IF;
END LOOP;
END;
In your program V_SERVICIODIAS INT; is a declared variable, so you have to use it syntactically as a variable.
The correct if statement is the following, please try to use it:
IF V_SERVICIODIAS <= 60 THEN
As has been pointed out, V_SERVICIODIAS is a local variable so it's not part of the :NEW pseudorecord. You'd use
IF V_SERVICIODIAS <= 60 THEN
Once you do that, the next issue is that nothing is actually populating that local variable so the if statement can never be true. That's because there is a syntax error in your cursor definition. You use an into clause if you have a select statement that returns a single row not when you're defining a cursor that you plan on looping over
CURSOR C_SERVICIODIAS IS
SELECT TIEMPOSERVICIODIAS
FROM SERVICIO;
Once you fix the cursor definition error, you'd get rid of the local variable entirely and just reference the column from the cursor.
IF R_SERVICIODIAS.TIEMPOSERVICIODIAS <= 60 THEN
Having done all that, however, you're going to encounter a mutating table runtime error because a row-level cursor on the SERVICIO isn't going to be able to query the SERVICIO table. And, unfortunately, at that point it's not obvious how to resolve the problem because it's not obvious why the cursor exists in the first place. Why would you want to loop over every row in the table every time you insert a new row into the table? That doesn't really make any sense.
One possibility is that you don't actually want to loop over every row in the table. Perhaps you want to remove the V_SERVICIODIAS local variable and the cursor definition and the loop and just reference the TIEMPOSERVICIODIAS from the current row.
IF :NEW.TIEMPOSERVICIODIAS <= 60 THEN

PLSQL Block fails with "into"

So I made this plsql block but I can't find why into fails
DECLARE
numero_llibres number := 0;
numero_pagines number :=0;
BEGIN
select count(estat) into numero_llibres, sum(pagines) into numero_pagines from llibres where estat = 'pendent';
DBMS_OUTPUT.PUT_LINE('El numero de llibres que queden per llegir és'||numero_llibres);
DBMS_OUTPUT.PUT_LINE('El numero de pàgines que falten per llegir és'||numero_pagines);
END;
The syntax is:
SELECT column1, column2, ....
INTO variable1, variable2, ...
FROM ...
So your code should be:
DECLARE
numero_llibres number;
numero_pagines number;
BEGIN
select count(estat), sum(pagines)
into numero_llibres, numero_pagines
from llibres
where estat = 'pendent';
DBMS_OUTPUT.PUT_LINE('El numero de llibres que queden per llegir és'||numero_llibres);
DBMS_OUTPUT.PUT_LINE('El numero de pàgines que falten per llegir és'||numero_pagines);
END;

pl/sql oracle how to check or how to store the current value of a sequence

I am trying to show the record after insert it on the table. However my primary key is a substring with a sequence, so I cant find a way to save this value ...this is my code
SET SERVEROUTPUT ON
ACCEPT MARQUE PROMPT "Entrez la marque de la moto "
ACCEPT ANNEE PROMPT "Entrez l annee de la moto: "
ACCEPT PRIX PROMPT "Entrez le prix de la moto: "
DECLARE
myMarque VARCHAR2(50):='&MARQUE';
myAnnee VARCHAR2(6):='&ANNEE';
myPrix NUMBER(6,2):=&PRIX;
lecode VARCHAR2(12);
BEGIN
IF myAnnee = 2013 THEN
INSERT INTO MOTO (CODE, MARQUE, ANNEE, PRIX) VALUES (UPPER(SUBSTR(myMarque, 1,3)||MASEQ.nextval), myMarque, myAnnee, myPrix);
COMMIT;
ELSIF myAnnee = 2014 THEN
INSERT INTO MOTO (CODE, MARQUE, ANNEE, PRIX) VALUES (UPPER(SUBSTR(myMarque, 1,3)||MASEQ.nextval), myMarque, myAnnee, myPrix);
COMMIT;
ELSIF myAnnee = 2015 THEN
INSERT INTO MOTO (CODE, MARQUE, ANNEE, PRIX) VALUES (UPPER(SUBSTR(myMarque, 1,3)||MASEQ.nextval), myMarque, myAnnee, myPrix);
COMMIT;
ELSIF myAnnee = 2016 THEN
INSERT INTO MOTO (CODE, MARQUE, ANNEE, PRIX) VALUES (UPPER(SUBSTR(myMarque, 1,3)||MASEQ.nextval), myMarque, myAnnee, myPrix);
COMMIT;
ELSE
DBMS_OUTPUT.PUT_LINE('Annee invalide SVP VERIFIEZ');
END IF;
END;
/
In short what I need is to show the record after commit , any ideas? I tried to save the value in the variable lecode but it didnt work.
Use the RETURNING clause on your INSERTS, e.g.:
DECLARE
strLast_code MOTO.CODE%TYPE;
BEGIN
INSERT INTO MOTO
(CODE, MARQUE, ANNEE, PRIX)
VALUES
(UPPER(SUBSTR(myMarque, 1,3)||MASEQ.nextval), myMarque, myAnnee, myPrix)
RETURNING CODE INTO strLast_code;
END;
sequence_name.currval will give the current value of sequence.
just like sequence_name.nextval you can get sequence_name.currval
Another solution would be to select directly from the database's metadata:
select last_number from all_sequences where sequence_name='MASEQ';

internal error [phdite:node kind] / looping chain of synonyms

I am getting these errors when executing my code, can anyone give me a solution please?
create or replace procedure old_candidate (ID_M1 candidate.ID_M1%type,ID_M2 candidate.ID_M2%type,ID_M3 candidate.ID_M3%type,ID_M4 candidate.ID_M4%type,nombre_masterss candidate.nombre_masters%type,Lname candidate.Lname%type,Fname candidate.Fname%type,Fname_father candidate.Fname_father%type,mother candidate.mother%type,sex candidate.sex%type,DOB candidate.DOB%type,POB candidate.POB%type,Nat candidate.Nat%type,ncivil candidate.ncivil%type,Cir candidate.Cir%type,building candidate.building%type,street candidate.street%type,region candidate.region%type,nhood candidate.nhood%type,tel_m candidate.tel_m%type,tel_f candidate.tel_f%type,email candidate.email%type,Hschool candidate.Hschool%type,description candidate.description%type,diploma1 candidate.diploma1%type,desc_d1 candidate.desc_d1%type,Diploma2 candidate.Diploma2%type,desc_d2 candidate.desc_d2%type,Diploma3 candidate.Diploma3%type,desc_d3 candidate.desc_d3%type,motivation_m1 candidate.motivation_m1%type,motivation_m2 candidate.motivation_m2%type,motivation_m3 candidate.motivation_m3%type,motivation_m4 candidate.motivation_m4%type)
is
IDs students.ID%type;
pre master.prerequis%type;
test number;
begin
select ID
into IDs
from students
where ID_u=get_current_user_ID;
if nombre_masterss>0 then
select prerequis
into pre
from master
where ID_master=ID_m1;
if pre>0 then select count(*)
into test
from inscriptions
where master_ID=pre and succeeded='Y';
if test=0 then
raise_application_error(-20018,'vous ne pouvez pas s''inscrire au master1 avant de reussir son prerequis');
end if;
end if;
end if;
if nombre_masterss>1 then
select prerequis
into pre
from master
where ID_master=ID_m2;
if pre>0 then select count(*)
into test
from inscriptions
where master_ID=pre and succeeded='Y';
if test=0 then
raise_application_error(-20018,'vous ne pouvez pas s''inscrire au master2 avant de reussir son prerequis');
end if;
end if;
end if;
if nombre_masterss>2 then
select prerequis
into pre
from master
where ID_master=ID_m3;
if pre>0 then select count(*)
into test
from inscriptions
where master_ID=pre and succeeded='Y';
if test=0 then
raise_application_error(-20018,'vous ne pouvez pas s''inscrire au master3 avant de reussir son prerequis');
end if;
end if;
end if;
if nombre_masterss>3 then
select prerequis
into pre
from master
where ID_master=ID_m4;
if pre>0 then select count(*)
into test
from inscriptions
where master_ID=pre and succeeded='Y';
if test=0 then
raise_application_error(-20018,'vous ne pouvez pas s''inscrire au master4 avant de reussir son prerequis');
end if;
end if;
end if;
insert into candidate (ID_c,year,old_new,ID,ID_M1,ID_M2,ID_M3,ID_M4,nombre_masters,etat1,etat2,etat3,etat4,date_candidature,Lname,Fname,Fname_father,mother,sex,DOB,POB,Nat,ncivil,cir,building,street,region,nhood,tel_m,tel_f,email,Hschool,description,diploma1,desc_d1,diploma2,desc_d2,diploma3,desc_d3,motivation_m1,motivation_m2,motivation_m3,motivation_m4)
values(ID_C_seq.nextval,get_annee_scolaire,IDs,'O',ID_M1,ID_M2,ID_M3,ID_M4,nombre_masterss,'P','P','P','P',sysdate,Lname,Fname,Fname_father,mother,sex,DOB,POB,Nat,ncivil,cir,building,street,region,nhood,tel_m,tel_f,email,Hschool,description,diploma1,desc_d1,diploma2,desc_d2,diploma3,desc_d3,motivation_m1,motivation_m2,motivation_m3,motivation_m4);
exception
when no_data_found then
raise_application_error(-20017,'Vous n''etes pas un etudiant');
end;
/
This is the error message I am getting:
Errors for PROCEDURE OLD_CANDIDATE:
LINE/COL ERROR
-------- ---------------------------------------------
0/0 PLS-00801: internal error [phdite:node kind]
68/3 PL/SQL: SQL Statement ignored
69/110 PL/SQL: ORA-01775: looping chain of synonyms
72/4 PL/SQL: Statement ignored
I created some synonyms earlier and then dropped my tables and procedures and recreated them, I think this was the cause of the problem if I was not mistaken, can someone tell me how to fix this issue, or perhaps delete all synonyms? I tried dba_synonyms but I got that the table or view does not exist.

Cursor in PL/SQL, my procedure doesnt work

i have a problem in my procedure...in this case i want to raisy the salary to employees(Empleado) that have been working 5 years or more inn the store "Bodega"(...sorry about my english,i speak spanish XD).
First, i was thinking about select the ID's of all the employees that satisfy the condition (in a cursor) and then compare them to the ID'S in the EMPLEADO TABLE, if the same(the ID'S) then UPDATE the salary...it doesn't work with the IF - END IF (i put in COMMENTS) but without it.
needing help...i am doing something wrong but dont know what it is.
CREATE OR REPLACE PROCEDURE aumento_empleado(idBodega IN CHAR)IS
CURSOR c_empl IS SELECT E.idEmpleado
FROM Empleado E, Bodega B
WHERE( MONTHS_BETWEEN(sysdate,E.fecha_contrato)>=5*12
AND E.id_Bodega=B.id_Bodega
AND B.id_Bodega=idBodega);
idEmpl Char(8);
NO_EMP EXCEPTION;
BEGIN
OPEN c_empl;
LOOP
FETCH c_empl INTO idEmpl;
EXIT WHEN c_empl%notfound;
IF c_empl%ROWCOUNT=0 THEN
RAISE NO_EMP;
END IF;
--IF (idEmpl=Empleado.idEmpleado) THEN
UPDATE Empleado
SET Empleado.Sueldo=Empleado.Sueldo + Empleado.Sueldo*0.05;
--END IF;
END LOOP;
CLOSE c_empl;
EXCEPTION
WHEN NO_EMP THEN
dbms_output.put_line('No hay empleados que cumplan con las condiciones pedidas para la bonificacion' ) ;
WHEN OTHERS THEN
dbms_output.put_line('Error: hubo un error durante la ejecucion del procedimiento' ) ;
END aumento_empleado;
This single statement should work for your purpose
UPDATE Empleado E
SET E.Sueldo=E.Sueldo + E.Sueldo*0.05
WHERE MONTHS_BETWEEN(sysdate,E.fecha_contrato)>=5*12
AND E.id_Bodega IN (SELECT B.id_Bodega FROM Bodega B)
Avoid using loops where they are not absolutely required.

Resources