Created: 2024-09-08 dom 17:51
V$RESERVED_WORDS
$
, #
, pero no puede contener operadores +%=/*
select * from pepe where nombre='a';
SET SERVEROUTPUT ON;
begin
dbms_output.put_line('Hola');
END;
/
SET SERVEROUTPUT ON;
DECLARE
msg varchar(255);
BEGIN
msg := 'Hola';
dbms_output.put_line(msg);
END;
/
char
, varchar
number
, integer
, float
date
, timestamp
blob
, clob
bool
pls_integer
%type
: Tipo de un campo de una tabla%rowtype
: Tipo compuesto, referido a una fila de una tablacreate table cliente( id integer, nombre varchar(255) );
DECLARE
filacliente cliente%rowtype;
BEGIN
filacliente.id := 1;
filacliente.nombre := 'María';
insert into cliente values filacliente;
END;
/
DECLARE
numero integer := 1;
BEGIN
if( numero < 0 ) then
dbms_output.put_line( 'Menor que cero');
elsif( numero > 0 ) then
dbms_output.put_line( 'Mayor que cero');
else
dbms_output.put_line( 'Igual que cero');
end if;
END;
/
case
when vsalario<0 then
dbms_output.put_line('Incorrecto');
when vsalario=0 THEN
dbms_output.put_line('Gratis!');
when vsalario<10000 then
dbms_output.put_line('Salado!');
when vsalario<90000 then
dbms_output.put_line('Mas o menos');
else
dbms_output.put_line('Correcto');
end case;
case v_job_grade
when 1 THEN
dbms_output.put_line('Jefe!');
when 2 then
dbms_output.put_line('Jefecito');
when 3 then
dbms_output.put_line('Empleado regular');
ELSE
dbms_output.put_line('CEO');
end case;
case
Queremos implementar un servicio de traducción de español a inglés. El servicio no está disponible los lunes
case
como sentencia con un valordeclare
v varchar(100) := 'Hasta luego';
begin
if to_char(sysdate,'D')=1 then
dbms_output.put_line('es mi día libre' );
else
case v
when 'Hola' then
dbms_output.put_line('Hello' );
when 'Adiós' then
dbms_output.put_line('Bye' );
else
dbms_output.put_line('No traduction' );
end case;
end if;
end;
/
case
como sentencia con múltiples comparacionesdeclare
v varchar(100) := 'Hola';
begin
case
when to_char(sysdate,'D')=1 then
dbms_output.put_line('es mi día libre' );
when v='Hola' then
dbms_output.put_line('Hello' );
when v='Adiós' then
dbms_output.put_line('Bye' );
else
dbms_output.put_line('No traduction' );
end case;
end;
/
case
como expresión con múltiples comparacionesdeclare
v varchar(100) := 'Hola';
traduccion varchar(100);
begin
traduccion := case
when to_char(sysdate,'D')=1 then
'es mi día libre'
when v='Hola' then
'Hello'
when v='Adiós' then
'Bye'
else
'No traduction'
end;
dbms_output.put_line(traduccion);
end;
/
case
como expresión con un valordeclare
v varchar(100) := 'Hola';
traduccion varchar(100);
begin
if to_char(sysdate,'D')=1 then
traduccion := 'es mi día libre';
else
traduccion := case v
when 'Hola' then
'Hello'
when 'Adiós' then
'Bye'
else
'No traduction'
end;
end if;
dbms_output.put_line(traduccion);
end;
/
sql
select nombre, precioventa, case
when precioventa >= 100 then 'carísimo'
when precioventa >= 10 then 'caro'
else 'barato' end as rango
from productos
order by 3;
select nombre,precioventa, 'caro'
from productos
where precioventa >= 10
union
select nombre,precioventa, 'barato'
from productos
where precioventa < 10;
loop
LOOP
-- Instrucciones
IF (expresion) THEN
-- Instrucciones
EXIT;
END IF;
END LOOP;
while
WHILE (expresion) LOOP
-- Instrucciones
END LOOP;
for
DECLARE
c PLS_INTEGER DEFAULT 0;
BEGIN
FOR c IN REVERSE 1..10 LOOP
dbms_output.put_line ('Contador = '||c);
END LOOP;
END;
Imprime un rectángulo de tamaño 8x6
######## ######## ######## ######## ######## ########
Imprime un tablero de ajedrez de tamaño NxM (con la función MOD
)
# # # # # # # # # # # # # # # # # # # # # # # #
(youtube)
select to_date('01-01-01','dd-MM-yyyy') from dual;
select * from student where mod(studentid,2)=0;
sqrt, upper, substr, len, nvl...
CREATE OR REPLACE FUNCTION es_par(numero IN number)
RETURN boolean
IS
resto number;
BEGIN
resto := mod(numero,2);
if( resto = 0 ) then
return true;
else
return false;
end if;
END;
/
Las funciones pueden invocarse:
CREATE OR REPLACE FUNCTION es_par_varchar(numero IN number)
RETURN varchar
IS
BEGIN
-- AQUÍ SE INVOCA LA FUNCIÓN DEL APARTADO ANTERIOR
if( es_par(numero) ) then
return 'Sí es par';
else
return 'No es par';
end if;
END;
/
DECLARE
n number := 32;
BEGIN
dbms_output.put_line( 'El número ' || n || ' ' || es_par_varchar(n) );
END;
/
select empno, es_par_varchar(empno) from empleados;
select es_par_varchar(89) from dual;
select es_par(89) from dual;
ORA-00902: tipo de dato no válido
00902. 00000 - "invalid datatype"
replace |
sysdate |
lpad |
instr |
substr |
nvl |
trim |
trunc |
upper |
to_date |
mod |
length |
lower |
to_char |
decode |
|
rpad |
to_number |
to_date
y to_char
declare
fechaentexto varchar(255);
fecha date;
begin
fechaentexto := '11/may/18';
fecha := to_date(fechaentexto,'DD/MON/YY');
dbms_output.put_line( to_char(fecha,'DD "de" MONTH "de" YYYY'));
end;
/
declare
pi number(20,10) := 3.141597265;
begin
dbms_output.put_line( to_char(pi, 'B9999' ) );
end;
/
Imprime un listado con la inicial de los empleados y sus apellidos
A. Pérez F. González M. Ruiz
11/MAY/20
a fecha, e imprímela como 11 de Mayo de 2020
1
si un número es primo o 0
si es compuesto
paLABRa
debe devolver Palabra
capitalizar
create or replace function capitalizar( palabra varchar ) return varchar as
inicial char(1);
resto varchar(1024);
begin
inicial := substr(palabra,1,1);
resto := substr(palabra,2,length(palabra)-1);
return upper(inicial) || lower(resto);
end;
out
CREATE OR REPLACE PROCEDURE aumenta_salario(vempno IN number)
IS
BEGIN
update empleados
set salario=salario+100
where empno = vempno;
END;
/
in
in
se pasa por valorcreate or replace procedure suma_uno(n in numeric) is
begin
n := n +1;
end;
/
declare
numero numeric(10,0);
begin
numero := 3;
sumauno(numero);
dbms_output.put_line(numero);
end;
/
out
out
se pasa por referenciacreate or replace procedure suma_uno(n in out numeric) is
begin
n := n +1;
end;
/
declare
numero numeric(10,0);
begin
numero := 3;
sumauno(numero);
dbms_output.put_line(numero);
end;
/
select
update
insert
delete
(youtube)
select
select ... into ... from...
create table empleados( empno number(20), salario number(8,2), nombre varchar(255));
insert into empleados(empno,salario,nombre) values (1,2000,'María');
insert into empleados(empno,salario,nombre) values (2,1000,'Juan');
DECLARE
vempno NUMBER := 2;
vsalario NUMBER;
BEGIN
SELECT salario INTO vsalario FROM empleados WHERE empno=vempno;
dbms_output.put_line('El empleado ' || vempno || ' tiene un sueldo de '||vsalario||'€');
end;
/
v
%type
alter table
), el PLSQL sigue siendo válidoDECLARE
vempno empleados.empno%TYPE := 2;
vsalario empleados.salario%TYPE;
BEGIN
SELECT salario INTO vsalario FROM empleados WHERE empno=vempno;
dbms_output.put_line('El empleado ' || vempno || ' tiene un sueldo de '||vsalario||'€');
end;
/
%rowtype
alter table
), el PLSQL sigue siendo válidoDECLARE
vempno empleados.empno%TYPE := 2;
vempleado empleados%ROWTYPE;
BEGIN
SELECT * INTO vempleado FROM empleados WHERE empno=vempno;
dbms_output.put_line('El empleado ' || vempno || ' tiene un sueldo de '|| vempleado.salario ||'€');
dbms_output.put_line('El empleado ' || vempno || ' se llama '|| vempleado.nombre ||'€');
end;
/
create or replace function empleado_con_id(
p_empno empleados.empno%TYPE
)
return empleados%rowtype
as
empleado empleados%rowtype;
begin
select *
into empleado
from empleados
where empno=p_empno;
return empleado;
end;
/
insert
, update
, delete
declare
vempno number;
begin
vempno := 100;
insert into empleados(empno, salario, nombre)
values( vempno, 1000, 'Manolo');
update empleados
set salario = salario + 100
where empno = vempno;
delete from empleados where empno = vempno;
end;
/
%rowtype
en insert
%ROWTYPE
se puede usar en un insert
DECLARE
vempleado empleados%ROWTYPE;
BEGIN
vempleado.empno := 4;
vempleado.salario := 3000;
vempleado.nombre := 'Susana';
insert into empleados values vempleado;
end;
/
for
puede recorrer las filas de una consultafor
tiene el %ROWTYPE
de la consultaDECLARE
salariototal number := 0;
numeroempleados number := 0;
mediasalario number := 0;
begin
for empleado in (select * from empleados) loop
dbms_output.put_line(empleado.nombre || ' con salario ' || empleado.salario );
numeroempleados := numeroempleados + 1;
salariototal := salariototal +empleado.salario;
end loop;
dbms_output.put_line( 'Hay ' || numeroempleados || ' empleados ');
dbms_output.put_line( 'Sus sueldos suman ' || salariototal );
mediasalario := salariototal / numeroempleados;
dbms_output.put_line( 'La media de los sueldos es ' || mediasalario);
end;
/
DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
-- Excepcion
END;
(youtube)
DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Se ejecuta cuando ocurre una excepcion de tipo NO_DATA_FOUND
WHEN ZERO_DIVIDE THEN
-- Se ejecuta cuando ocurre una excepcion de tipo ZERO_DIVIDE
WHEN OTHERS THEN
-- Se ejecuta cuando ocurre una excepcion de un tipo no tratado
-- en los bloques anteriores
END;
create table empleados( empno number(20), salario number(8,2), nombre varchar(255));
insert into empleados(empno,salario,nombre) values (1,2000,'María');
insert into empleados(empno,salario,nombre) values (2,1000,'Juan');
DECLARE
unavariable varchar(255);
BEGIN
select nombre into unavariable from empleados;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('select...into ha devuelto más de una fila!');
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('select...into no ha devuelto ninguna fila!');
WHEN OTHERS THEN
dbms_output.put_line('Error no previsto:' || sqlcode || ': ' || sqlerrm );
END;
NO_DATA_FOUND |
TOO_MANY_ROWS |
ACCESS_INTO_NULL |
INVALID_NUMBER |
NO_DATA_FOUND |
VALUE_ERROR |
ROWTYPE_MISMATCH |
ZERO_DIVIDE |
https://www.techonthenet.com/oracle/exceptions/named_system.php
SQLCODE
y SQLERRM
SQLCODE
: Número de error (independiente del idioma)SQLERRM
:
sqlcode
DECLARE
result NUMBER;
BEGIN
SELECT 1/0 INTO result FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('Error:'||TO_CHAR(SQLCODE));
DBMS_OUTPUT.put_line(SQLERRM);
END;
select into
debe estar hecho para devolver como mucho una filaselect count()
con un if
para comprobar que devuelve una fila-20001
y 20999
when others
y comprobarse con SQLCODE
DECLARE
n number;
BEGIN
SELECT count(*) into n from empleados
if( n < 10 ) then
RAISE_APPLICATION_ERROR(-20001,'La empresa necesita al menos 10 empleados');
end if;
EXCEPTION
WHEN OTHERS THEN
if( sqlcode = -20001) then
dbms_output.put_line('Pocos empleados');
end if;
END;
CREATE [OR REPLACE] TRIGGER <nombre_trigger>
{BEFORE|AFTER}
{DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]
[OR {DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]...]}
ON <nombre_tabla>
[FOR EACH ROW [WHEN (<condicion>)]]
DECLARE
-- variables locales
BEGIN
-- Sentencias
[EXCEPTION]
-- Sentencias control de excepcion
END;
CREATE or replace TRIGGER personal_minimo
BEFORE DELETE ON empleados
declare
n number;
begin
SELECT count(*) into n from empleados;
if( n < 10 ) then
RAISE_APPLICATION_ERROR(-20001,'La empresa necesita al menos 10 empleados');
end if;
end;
/
Evento DML | |
---|---|
delete |
Borrado de una fila |
insert |
Insercción de una fila |
update |
Modificación de fila |
update of |
Modificación de un campo de una fila |
instead of |
Anula la orden, pero no provoca un error |
INSERTING
, UPDATING
y DELETING
sirven para diferenciar por qué se ha lanzadoCREATE or replace TRIGGER ejemplo_or
BEFORE DELETE OR UPDATE OR INSERT ON empleados
begin
case
when inserting THEN
dbms_output.put_line('Insertando empleados');
when updating then
dbms_output.put_line('Actualizando empleados');
when deleting then
dbms_output.put_line('Borrando empleados');
else
dbms_output.put_line('Inesperado');
end case;
end;
/
Evento DDL | |
---|---|
ALTER | Modificación de objetos |
COMMENT | |
CREATE | Creación de objetos |
DDL | |
DROP | Borrado de Objetos |
GRANT | Otorgar privilegios |
RENAME | |
REVOKE | Quitar privilegios |
TRUNCATE |
Evento DDL | |
---|---|
ANALYSE | |
ASSOCIATE STATISTICS | |
AUDIT | |
DISASSOCIATE STATISTICS | |
LOGON | Entrada de usuario |
LOGOFF | Salida de usuario |
NOAUDIT | |
RENAME | |
SERVERERROR | |
STARTUP | Servidor arrancado |
SHUTDOWN | Servidor parado |
SUSPEND |
for each row
for each row
, se lanza una vez por cada fila cambiadabefore
after
instead of
: No se ejecuta el SQL, sino otro alternativo. Útil para vistas modificables.:old
y :new
existen en los triggers tipo for each row
:old
: Variable tipo %rowtype
con los datos antiguos de la fila:new
: Datos nuevos de la filaMomento | Evento | :old |
:new |
---|---|---|---|
before |
delete |
Lectura | |
before |
insert |
Lectura/escritura | |
before |
update |
Lectura | Lectura/escritura |
after |
delete |
Lectura | |
after |
insert |
Lectura | |
after |
update |
Lectura | Lectura |
create sequence empleado_empno_seq;
CREATE or replace TRIGGER asignar_empleado_empno
BEFORE INSERT ON empleados
for each row
begin
if :new.empno is null then
:new.empno = empleado_empno_seq.nextval;
end if;
end;
/
create table empleados( empno number(20), salario number(8,2), nombre varchar(255));
insert into empleados(empno,salario,nombre) values (1,2000,'María');
insert into empleados(empno,salario,nombre) values (2,1000,'Juan');
alter table empleados add (
createdby varchar(255),
createddate timestamp,
modifiedby varchar(255),
modifieddate timestamp
);
createdXXXX
create or replace trigger audit_creacion_empleados
before insert
on empleados
for each row
begin
dbms_output.put_line('Empleado ' || :new.nombre || ' creado por:' || user );
:new.createdby := user;
:new.createddate := systimestamp;
end;
/
modifiedXXXX
create or replace trigger audit__modificacion_empleados
before update
on empleados
for each row
begin
dbms_output.put_line('Empleado ' || :new.nombre || ' modificado por:' || user );
:new.modifiedby := user;
:new.modifieddate := systimestamp;
end;
/
create or replace function MASA_SALARIAL return number
as
total number;
begin
select sum(salario) into total from empleados;
return total;
end;
/
create table cantidadesprecalculadas(nombre varchar(255), valor number(20,2));
create or replace trigger mantener_masa_salarial
after insert or update or delete
on empleados
for each row
begin
if inserting then
update cantidadesprecalculadas set valor=valor + :new.salario where nombre = 'masasalarial';
elsif deleting then
update cantidadesprecalculadas set valor=valor - :old.salario where nombre = 'masasalarial';
elsif updating then
update cantidadesprecalculadas set valor=valor - :old.salario + :new.salario where nombre = 'masasalarial';
end if;
end;
/
create or replace function MASA_SALARIAL_PRECALCULADA return number
as
total number;
begin
select valor into total from cantidadesprecalculadas where nombre='masasalarial';
return total;
end;
/
masasalarial
tiene un atributo calculado, que depende de otros datos
MASA_SALARIAL
set serveroutput off;
begin
for i in 1 .. 10000 loop
insert into empleados(empno,salario,nombre)
values(100+i, i, 'Nombre Inventado');
end loop;
end;
/
set serveroutput on;
declare
numero number;
begin
for i in 1 .. 1000 loop
select /*+ NO_RESULT_CACHE */ masa_salarial_precalculada into numero from dual;
end loop;
end;
/