Documentos de Académico
Documentos de Profesional
Documentos de Cultura
2020-I
Base de Datos
PL/SQL
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Divide-by-zero error: can''t divide '
|| numerator || ' by ' || denominator);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Unexpected error.');
END inner_label;
END compute_ratio;
/
Bloque
DECLARE
cursor c1 (user varchar2) is
select table_name from all_tables
where owner = user;
BEGIN
for tabla IN c1('LIBRERIA')
loop
execute immediate 'drop table ' || usuario || '.' || tabla.table_name || ' cascade constraints';
end loop;
END;
/
Subprogramas
●
Procedimientos y funciones
●
Definido a nivel de:
– Paquete. (almacenado)
– Esquema(Standalone, almacenado)
– Bloque(Anidada, almacenado si que es anidada dentro de un subprograma de paquete o standalone).
●
Invocación: nombre_subprograma(parámetros), ejm:
– Result := factorial(5);
– dbms_output.put_line('Result= ' || result);
●
Los parámetros pueden ser
– In (por defecto)
– Out
– In out
●
Se pueden overloaded.
●
Para salir de un subprograma o bloque: return.
declare
cantidadAntes Number;
Subprogramas
cantidadDespues Number;
A que nivel están definidos?
function cantidadTabla(usuario varchar2) return number is Son almacenado?
cantidad Number;
begin
select count(*) into cantidad from all_tables Notas:
where owner = usuario;
return cantidad; 1.- Puede usar is o as
end;
2.- En las funciones pueden usar result_cache (se
procedure eliminarTablasDe(usuario varchar2) as invalidan cuando los fuentes cambian, o el tiempo
cursor c1 (user varchar2) is expira entre otros factores).
select table_name from all_tables 3.- Se puede declarar y definir mas
where owner = user; adelante(forward declaration, necesario en
begin
algunas situaciones).
for tabla IN c1(usuario)
loop
execute immediate 'drop table ' || usuario || '.' ||tabla.table_name || ' cascade constraints';
end loop;
end;
begin
cantidadAntes := cantidadTabla('TESTUSER');
eliminarTablasDe('TESTUSER');
cantidadDespues := cantidadTabla('TESTUSER');
dbms_output.put_line('Antes: ' || cantidadAntes || ', despues: ' || cantidadDespues);
end;
/
Subprogramas
Create or replace function cantidadTabla(usuario varchar2) return number is A que nivel están definidos?
cantidad Number;
Son almacenado?
begin
select count(*) into cantidad from all_tables Como se invoca?
where owner = usuario;
return cantidad;
end;
/
function nuevo(apellido varchar, nombre varchar, local_id number, cargo_id number) return number is
empId number;
Begin
select nvl(max(id),0)+1 into empId from empleado;
dbms_output.put_line('Ante de insertar: ' || empId);
insert into empleado(id, apellido, nombre, local_id, cargo_id) values (empId, apellido, nombre, local_id, cargo_id);
return (empId);
End;
End gestion_empleado;
Invocación
declare
empId number;
begin
empId := gestion_empleado.nuevo('Perez', 'Juan', 1, 1);
DBMS_OUTPUT.PUT_LINE('Se ha insertado un registro con id ' || empId);
gestion_empleado.darDeBaja(empId);
DBMS_OUTPUT.PUT_LINE('Se ha eliminado un registro con id ' || empId);
end;
Variables
declare
x number := 10;
y number := 20;
limite constant real := 5000.00;
max_num number; -- Si no se inicializa es null
apellido cliente.apellido%type; -- mismo tipo que una columna
nombre apellido%type; -- mismo tipo que otra variable
cliente_rec cliente%rowtype; -- un registro completo
Begin
If x > y then
max_num := x;
else
max_num := y;
end if;
cliente_rec.apellido := 'Perez';
select apellido, nombre into apellido, nombre from cliente where id = 1;
dbms_output.put_line('Valores:' || apellido || ', ' || nombre);
select * into cliente_rec from cliente where id = 1;
dbms_output.put_line('Valores:' || cliente_rec.id || ', ' || cliente_rec.apellido || ', ' || cliente_rec.nombre);
End;
Tipo de Datos SQL
●
Oracle built-in
– Carácter: char, varchar2, nchar, nvarchar2
– Numero: number, float, binary_float, binary_double
– Long y raw: long, long raw, raw
– Datetime: date, timestamp, interval year, interval day
– Large object: blob, clob, nclob, bfile
– Rowid: Rowid, urowid
●
ANSI suportado:
– Character, char, nchar, varchar, national(character y char)
– Numeric, decimal, dec, integer, int, smallint, float, double, real
●
User defined
●
Oracle supplied
– any_types
– xml_types
– spatial_types
– media_types
Tipo de Datos (escalar) PL/SQL
●
Tipo de Datos SQL SUBTYPE Balance IS NUMBER;
SUBTYPE Counter IS NATURAL;
●
Boolean SUBTYPE Balance IS NUMBER(8,2);
SUBTYPE Word IS CHAR(6);
●
PLS_INTEGER subtype REAL is FLOAT; -- FLOAT(63)
subtype "DOUBLE PRECISION" is FLOAT;
●
BINARY_INTEGER subtype INTEGER is NUMBER(38,0);
subtype INT is INTEGER;
subtype SMALLINT is NUMBER(38,0);
●
REF CURSOR
subtype DECIMAL is NUMBER(38,0);
subtype NUMERIC is DECIMAL;
●
Subtipo user-defined subtype DEC is DECIMAL;
Control de Flujo – selección
condicional
case grado
If x > y then when ‘A’ then dbms_output.put_line(‘Excelente’);
result := 1; when ‘B’ then dbms_output.put_line(‘Bueno’);
elsif x = y then else dbms_output.put_line(‘Deficiente’);
result := 0; end case;
else
result := -1; case
end if; when grado = ‘A’ then dbms_output.put_line(‘...’);
when grado = ‘B’ then dbms_output.put_line(‘...’);
else dbms_output.put_line(‘...’);
end case;
Notas:
Comparación de igualdad es =(no==)
Es elsif (no elseif)
Las sintaxis de las sentencias simple Case y searched case casi son idénticas a sus pares
en funciones.
Control de Flujo – Iterativas
1.- Básico 2.- For loop 4.- While loop
end;
/
Sql estático
declare
testvalor number;
testid number;
begin
--execute immediate 'create table temp1 (id number, valor varchar(10))';
--execute immediate 'create sequence temp1_seq start with 1';
testid := temp1_seq.currval;
select valor into testvalor from temp1 where id = testid;
2.- nexval, currval son seudocolumnas de una sequencia. Rowid, rownum son seudocolumnas de una fila arbitratia.
Sql estático
declare
●
select into cli cliente%rowtype;
cursor clienteConDni is
●
DML select * from cliente where doc_tipo = 'D';
begin
– Update
open clienteConDni;
– Insert loop
fetch clienteConDni into cli;
– Delete exit when clienteConDni%notfound;
– Merge DBMS_OUTPUT.PUT_LINE('Cliente: ' || cli.apellido || ' ' || cli.nombre );
end loop;
●
TCL close clienteConDni;
end;
– Commit /
– Rollback
Cual seria la versión usando for cursor?
– Savepoint Necesita hacer open, fetch y close?
– Set transaction
Desarrolle la versión con parámetro cursor
●
Cursor clienteConDoc (docTipo cliente.doc_tipo%type) is ...
– Implícito (SQL Cursor, se genera por cada select y DML)
– Explicito (declara y define, open, fetch, close) (atributos notfound,
rowcount, etc igual que SQL Cursor)
SQL Dinámico
●
Cuando usar?
– SQL cuyo texto se desconoce en tiempo de compilacion.
– SQL no soportado en SQL Estático (DDL por ejemplo).
●
Maneras de ejecutar.
– Nativa
●
Execute immediate.
●
Open for, fetch y close
– Paquete DBMS_SQL
Execute immediate
create or replace procedure crearEmpleado(newid in out number, apellido varchar2, nombre varchar2,
local_id number, cargo_id number) as
begin
newid := empleado_seq.nextval;
insert into empleado (id, apellido, nombre, local_id, cargo_id, usuario_id)
values (newid, apellido, nombre, local_id, cargo_id, null);
end;
/
declare
newid number;
apellido varchar2(50) := 'aaa';
nombre varchar2(50) := 'bbb';
local_id number := 1;
cargo_id number := 1;
sql_block VARCHAR2(500);
begin
sql_block := 'begin crearEmpleado(:a, :b, :c, :d, :e); end;';
execute immediate sql_block using in out newid, apellido, nombre, local_id, cargo_id;
DBMS_OUTPUT.PUT_LINE('id: ' || newid );
end;
Variables de Cursor declare
type clientecur is ref cursor return cliente%rowtype;
declare clientes clientecur;
type clientecur is ref cursor return cliente%rowtype; c cliente%rowtype;
clientes clientecur;
c cliente%rowtype; procedure imprimir(clie clientecur) as
begin
begin loop
open clientes for select * from cliente where doc_tipo = 'D'; fetch clie into c;
exit when clie%notfound;
loop DBMS_OUTPUT.PUT_LINE(c.apellido || ' ' || c.nombre );
fetch clientes into c; end loop;
exit when clientes%notfound; end;
DBMS_OUTPUT.PUT_LINE('Cliente: ' || c.apellido || ' ' || c.nombre );
end loop; begin
close clientes; open clientes for select * from cliente where doc_tipo = 'D';
imprimir(clientes);
open clientes for select ... close clientes;
open clientes for select * from cliente where doc_tipo = 'C';
end; imprimir(clientes);
/ close clientes;
Notas: end;
●
No se puede hacer for cursor para las variables de cursor. /
●
Pueden ser simplemente ref cursor o mas estricto ref cursor tipofila.
●
En oracle también puede usar cursor expresión para tener cursor anidado.
Execute immediate
q := 'begin select max(id) into :a from ' || tabla || '; end;';
execute immediate q using out testid;
BEGIN
– var3 var1%type friend.nombre.ape:= 'John';
friend.nombre.nom := 'Smith';
friend.fono := '1-650-555-1234';
DBMS_OUTPUT.PUT_LINE (
friend.nombre.ape || ' ' ||
friend.nombre.nom || ', ' ||
friend.fono
);