Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Apuntes PLSQL Nuevos Del Otro Sitio PDF
Apuntes PLSQL Nuevos Del Otro Sitio PDF
PL/SQL provee una manera muy cmoda de relacionar los conceptos de bases de datos y
manejarlos mediante ciertas estructuras de control, dentro del contexto de una herramienta
netamente de programacin.
Operadores aritmticos
La siguiente tabla presenta los operadores aritmticos ms comunes utilizados en PL/SQL.
Operador Significado
+ Suma
* Multiplicacin
** Exponenciacin
- Sustraccin
/ Divisin
Operadores relacionales
La siguiente tabla muestra los operadores relacionales de PL/SQL.
Operador Significado
<> Distinto de
^= Distinto de
> Mayor que
= Distinto de
< Menor que
= Igual
Smbolos especiales
Los siguientes smbolos se emplean para la programacin con PL/SQL. Esta tabla muestra una
lista parcial de los smbolos; incluye los smbolos ms comunes, que debemos conocer.
1
Smbolo Significado Ejemplo
() Separadores de lista and NAME in (Jose, Juan, Pedro)
; Fin de orden procedure_name(arg1, arg2)
. Separador select * from account.table_name
Cadena de caracteres if var1= Jose ...
:= Asignacin reg := reg+1
|| Concatenacin nombre := Juan || Perez
-- Comentario en una lnea -- Esto es un comentario
/* y */ Comentario en varias lneas /* esto es un comentario */
varchar2
Es un tipo de dato alfanumrico de longitud variable. En PL/SQL puede tener hasta una
longitud de 32.767 bytes. La definicin en la seccin declare se termina con un punto y coma (;)
y todas las definiciones se hacen as.
nombre_variable varchar2(longitud);
donde la longitud debe ser un entero positivo. Tambin tenemos la posibilidad de inicializar su
valor, usando la sintaxis:
number
Este tipo de dato se usa para representar los datos numricos. La declaracin es:
date
Este tipo de dato se usa para almacenar fechas de longitud fija. La declaracin no tiene
calificadores y se expresa as:
campo date;
boolean
Este tipo de datos es un conmutador que puede almacenar los estado true y false.
campo boolean;
2
Uso de %TYPE
El atributo %TYPE define el tipo de una variable utilizando una definicin previa de otra variable
o columna de la base de datos. Ejemplo:
DECLARE
credito REAL(7,2);
debito credito%TYPE;
Tambin se podra declarar una variable siguiendo el tipo de un campo de alguna tabla, como
por ejemplo en:
debito cuenta.debe%TYPE;
La ventaja de esta ltima forma es que no es necesario conocer el tipo de dato del campo
debe de la tabla cuenta, manteniendo la independencia necesaria para proveer ms
flexibilidad y rapidez en la construccin de los programas.
Uso de %ROWTYPE
El atributo %ROWTYPE precisa el tipo de un registro (record) utilizando una definicin previa
de una tabla o vista de la base de datos. Tambin se puede asociar a una variable como del
tipo de la estructura retornada por un cursor. Ejemplo:
DECLARE
emp_rec emp%ROWTYPE;
CURSOR c1 IS SELECT deptno, dname, loc FROM dept;
dept_rec c1%ROWTYPE;
En este ejemplo la variable emp_rec tomar el formato de un registro completo de la tabla emp
y la variable dept_rec se define por una estructura similar a la retornada por el cursor c1.
Estructura de bloque
Los programas PL/SQL se escriben en bloques de cdigo que disponen de secciones
independientes para las declaraciones de variables, el cdigo ejecutable y el tratamiento de
excepciones. Los fragmentos de cdigo PL/SQL se pueden almacenar en la base de datos
como un subprograma con nombre, o bien, codificarse directamente en la ventana de
SQL*Plus como un bloque annimo sin nombre.
DECLARE
...
BEGIN
...
EXCEPTION
END;
3
Ejemplo de bloque sin nombre que procesa pedidos de raquetas de tenis, recupera la cantidad
en stock, si es mayor que 0 actualiza la venta, si no, inserta un mensaje de alerta:
DECLARE
qty_on_hand NUMBER(5);
BEGIN
SELECT quantity INTO qty_on_hand FROM inventory
WHERE product = 'TENNIS RACKET'
FOR UPDATE OF quantity;
IF qty_on_hand > 0 THEN -- check quantity
UPDATE inventory SET quantity = quantity - 1
WHERE product = 'TENNIS RACKET';
INSERT INTO purchase_record
VALUES ('Tennis racket purchased', SYSDATE);
ELSE
INSERT INTO purchase_record
VALUES ('Out of tennis rackets', SYSDATE);
END IF;
COMMIT;
END;
/
IF THEN
Este es el modo ms simple y consiste en asociar una condicin con una secuencia de
sentencias encerradas entre las palabras reservadas THEN y END IF (no ENDIF). Ejemplo:
IF condicin THEN
secuencia_de_sentencias
END IF;
IF condicin THEN
calcular_bonus (emp_id)
UPDATE sueldos SET pago = pago + bonus WHERE emp_no = emp_id;
END IF;
IF THEN ELSE
Esta segunda modalidad de la sentencia IF tiene una nueva palabra clave: ELSE, seguida por
una secuencia alternativa de acciones:
IF condicin THEN
secuencia_de_sentencias_1
ELSE
secuencia_de_sentencias_2
END IF;
4
La secuencia de sentencias en la clusula ELSE es ejecutada solamente si la condicin es
falsa o nula. Esto implica que la presencia de la clusula ELSE asegura la ejecucin de alguna
de las dos secuencias de sentencias. En el ejemplo siguiente el primer UPDATE es ejecutado
cuando la condicin es verdadera, en el caso que sea falsa o nula se ejecutar el segundo
UPDATE:
IF tipo_trans = CR THEN
UPDATE cuentas SET balance = balance + credito WHERE
ELSE
UPDATE cuentas SET balance = balance debito WHERE
END IF;
Las clusulas THEN y ELSE pueden incluir estamentos IF, tal como lo indica el siguiente
ejemplo:
IF tipo_trans = CR THEN
UPDATE cuentas SET balance = balance + credito WHERE
ELSE
IF nuevo_balance >= minimo_balance THEN
UPDATE cuentas SET balance = balance debito WHERE
ELSE
RAISE fondos_insuficientes;
END IF;
END IF;
IF THEN ELSIF
Algunas veces se requiere seleccionar una accin de una serie de alternativas mutuamente
exclusivas. El tercer modo de la sentencia IF utiliza la clave ELSIF (no ELSEIF) para introducir
condiciones adicionales, como se observa en el ejemplo siguiente:
IF condicin_1 THEN
secuencia_de_sentencias_1
ELSIF condicin_2 THEN
secuencia_de_sentencias_2
ELSE
secuencia_de_sentencias_3
END IF;
Si la primera condicin es falsa o nula, la clusula ELSIF verifica una nueva condicin. Cada
sentencia IF puede poseer un nmero indeterminado de clusulas ELSIF; la palabra clave
ELSE que se encuentra al final es opcional.
Las condiciones son evaluadas una a una desde arriba hacia abajo. Si alguna es verdadera, la
secuencia de sentencias que corresponda ser ejecutada. Si cada una de las condiciones
analizadas resultan ser falsas, la secuencia correspondiente al ELSE ser ejecutada:
BEGIN
IF sueldo > 50000 THEN
bonus : = 1500;
ELSIF sueldo > 35000 THEN
bonus : = 500;
ELSE
bonus : = 100;
END IF;
INSERT INTO sueldos VALUES (emp_id, bonus, ... );
END;
5
Si el valor de sueldo es mayor que 50.000, la primera y segunda condicin son verdaderas, sin
embargo a bonus se le asigna 1500, ya que la segunda condicin jams es verificada. En este
caso slo se verifica la primera condicin para luego pasar el control a la sentencia INSERT.
Existen tres modalidades para esta instruccin: LOOP, WHILE LOOP y FOR LOOP.
LOOP
El modo bsico (o infinito) de LOOP encierra una serie de acciones entre las palabras clave
LOOP y END LOOP, como en el siguiente ejemplo:
LOOP
secuencia_de_instrucciones
END LOOP;
Con cada iteracin del ciclo las sentencias son ejecutadas. Para terminar estos ciclos de
ejecucin se utiliza la palabra clave EXIT. Es posible ubicar innumerables EXIT dentro del loop,
obviamente ninguno fuera de l. Existen dos modalidades para utilizar esta sentencia: EXIT y
EXIT WHEN.
EXIT
La clusula EXIT obliga al loop a concluir incondicionalmente. Cuando se encuentra un EXIT
en el cdigo, el loop es completado inmediatamente y pasa el control a la prxima sentencia.
LOOP
IF ranking_credito < 3 THEN
EXIT; --Termina el loop inmediatamente
END IF;
END LOOP;
Es necesario recordar que esta sentencia debe estar dentro del loop. Para completar un bloque
PL/SQL antes de que su final natural sea alcanzado, es posible utilizar la instruccin RETURN.
EXIT WHEN
Esta sentencia permite terminar el loop de manera condicional. Cuando se encuentra un EXIT
la condicin de la clusula WHEN es evaluada. Si la condicin es verdadera el loop es
terminado y el control es pasado a la prxima sentencia. Ejemplo:
LOOP
FECTH c1 INTO
EXIT WHEN c1%NOTFOUND; -- termina el loop si la
-- condicin es verdadera
END LOOP;
CLOSE c1;
Hasta que la condicin no sea verdadera el loop no puede completarse, esto implica que
necesariamente dentro de las sentencias el valor de la condicin debe ir variando. En el
ejemplo anterior si la ejecucin de FETCH retorna una fila la condicin es falsa. Cuando
FETCH falla al retornar una fila, la condicin es verdadera por lo que el loop es completado y el
control es pasado a la sentencia CLOSE.
6
IF count > 100 THEN | EXIT WHEN count > 100;
EXIT; |
END IF; |
Ambos cdigos son equivalentes, pero el EXIT WHEN es ms fcil de leer y de entender.
WHILE - LOOP
Esta sentencia se asocia a una condicin con una secuencia de sentencias encerradas por las
palabras clave LOOP y END LOOP, como sigue:
Antes de cada iteracin del ciclo se evala la condicin. Si sta es verdadera se ejecuta la
secuencia de sentencias y el control se devuelve al inicio del loop. Si la condicin en falsa o
nula, el ciclo se rompe y el control se transfiere a la prxima instruccin, fuera del loop.
FOR - LOOP
En las instrucciones anteriores el nmero de iteraciones es desconocido, mientras no se evala
la condicin del ciclo. Con una instruccin del tipo FOR-LOOP, la iteracin se efecta un
nmero finito (y conocido) de veces. La sintaxis de esta instruccin es la siguiente:
El contador no necesita ser declarado porque por defecto se crea para el bloque que involucra
el ciclo y luego se destruye.
Por defecto, la iteracin ocurre en forma creciente, es decir, desde el menor valor aportado
hasta el mayor. Sin embargo, si se desea alterar esta condicin por defecto, se debe incluir
explcitamente en la sentencia la palabra REVERSE.
Los lmites de una iteracin pueden ser literales, variables o expresiones, pero que deben
evaluarse como nmeros enteros.
Un contador de loop tiene validez slo dentro del ciclo. No es posible asignar un valor a una
variable contadora de un loop, fuera de l. Ejemplo:
La sentencia EXIT tambin puede ser utilizada para abortar la ejecucin del loop en forma
prematura. Por ejemplo, en el siguiente trozo de programa la secuencia normal debera
completarse despus de 10 veces de ejecutarse, pero la aparicin de la clusula EXIT podra
hacer que sta termine antes:
7
Manejo de cursores
Los cursores permiten manejar grupos de datos que se obtienen como resultado de una
consulta SQL que retorna una o ms filas.
PL/SQL utiliza dos tipos de cursores: implcitos y explcitos. Siempre declara un cursor implcito
para cualquier sentencia de manipulacin de datos, incluyendo aquellas que retornan slo una
fila.
Sin embargo, para las consultas que retornan ms de una fila, usted debe declarar un cursor
explcito para ser usado en una instruccin FOR.
No se pueden usar sentencias de control para cursores implcitos, como en el caso de los
cursores explcitos, por lo que no lo veremos.
Los cursores explcitos son aquellos que devuelven cero, una o ms filas, dependiendo de los
criterios con que hayan sido construidos. Un cursor puede ser declarado en la primera seccin
de un programa PL/SQL (declare).
Existen tres comandos para controlar un cursor: OPEN, FETCH y CLOSE. En un principio, el
cursor se inicializa con la instruccin OPEN. Enseguida, se utiliza la instruccin FETCH para
recuperar la primera fila o conjunto de datos. Se puede ejecutar FETCH repetidas veces hasta
que todas las filas hayan sido recuperadas. Cuando la ltima fila ya ha sido procesada, el
cursor se puede liberar con la sentencia CLOSE.
Declaracin de Cursores
Los cursores deben ser declarados antes de ser utilizados en otras sentencias. Cuando se
declara un cursor, a ste se le da un nombre y se asocia con una consulta especfica usando la
sintaxis siguiente:
DECLARE
CURSOR nombre_cursor [ (parmetro1 [, parmetro2]) ]
[RETURN tipo_de_retorno] IS sentencia_select ;
Donde tipo_de_retorno debe representar a un registro o una fila en una tabla de la base y los
parmetros siguen la siguiente sintaxis:
DECLARE
CURSOR c1 IS SELECT empno, ename, job, sal
FROM emp WHERE sal>1000 ;
CURSOR c2 RETURN dept%ROWTYPE IS SELECT *
FROM dept WHERE deptno = 10 ;
Un cursor puede recibir parmetros, los cuales deben ser declarados con la clusula IN para
formalizar su incorporacin. Los parmetros pueden ser inicializados con algn valor, pero
estos pueden ser cambiados en cualquier oportunidad.
El alcance de los parmetros es local al cursor, lo que significa que ellos slo pueden ser
referenciados dentro de la consulta especificada en la declaracin del mismo. Estos valores
son utilizados por la query cuando el cursor se abre.
8
Apertura de un Cursor
Al abrir un cursor se ejecuta inmediatamente la consulta e identifica el conjunto resultado, el
que contiene todas las filas que concuerdan con el criterio de seleccin de ste. Para los
cursores que se abren con la clusula For Update, la sentencia de apertura del cursor
adems bloquea esas filas retornadas. Un ejemplo es el siguiente:
DECLARE
CURSOR c1 IS SELECT ename, job FROM emp WHERE sal > 3000;
BEGIN
OPEN c1;
END;
Paso de Parmetros
Se utiliza tambin la sentencia OPEN para pasar los parmetros al cursor, en caso de que ste
los requiera. Por ejemplo:
DECLARE
emp_name emp.name%TYPE;
salary emp.sal%TYPE;
CURSOR c1 (name VARCHAR2, salary NUMBER) IS SELECT
Recuperacin de Filas
La sentencia FETCH permite recuperar los conjuntos de datos de uno en uno. Despus de
cada recuperacin y carga de un set de datos el cursor avanza a la fila siguiente. Ejemplo:
Para cada columna retornada en un cursor y especificada en la declaracin del mismo debe
existir una variable compatible en tipo en la lista INTO.
LOOP
FETCH c1 INTO mi_registro;
EXIT WHEN c1%NOTFOUND;
--- se procesa el registro
END LOOP;
9
Uso de %FOUND
Despus de abrir un cursor, pero antes de recuperar la primera fila el valor del atributo
%FOUND es nulo. A continuacin, tomar el valor TRUE cada vez que obtenga una fila del set
de resultados (en cada FETCH que se haga) y slo alcanzar el valor FALSE cuando ya no
existan ms filas para mostrar en el set de resultados. Ejemplo:
LOOP
FETCH c1 INTO
IF c1%FOUND THEN -- fetch exitoso
ELSE -- fetch fall; se sale del loop
EXIT;
END IF;
END LOOP;
Uso de %NOTFOUND
Es el opuesto lgico de %FOUND. Cada vez que una sentencia FETCH retorne una fila vlida,
este atributo devolver FALSO. Slo alcanzar el valor TRUE cuando no haya ms filas en un
cursor y se ejecute la sentencia FETCH (sin xito por lo tanto). Ejemplo:
LOOP
FETCH c1 INTO
EXIT WHEN c1%NOTFOUND;
END LOOP;
Uso de %ISOPEN
Este atributo toma el valor verdadero (TRUE) cuando un cursor se encuentra abierto. De otra
manera, retorna FALSO.
Uso de %ROWCOUNT
Cuando un cursor es abierto, este atributo es puesto a 0 (cero). En adelante, cada vez que se
recuperen filas exitosamente con un FETCH, este valor se ir incrementando en uno. Por tanto,
no es el nmero total, sino las que llevamos recuperadas hasta el momento.
Cuando se utiliza con cursores implcitos, este atributo devuelve el total de filas afectadas por
una instruccin del tipo INSERT, UPDATE o DELETE.
Cierre de un Cursor
La sentencia que deshabilita un cursor, CLOSE, se utiliza de la siguiente manera:
CLOSE c1;
Una vez que un cursor ya ha sido cerrado, es posible volverlo a abrir sin tener que declararlo
otra vez. Cualquier otra operacin que se desee efectuar sobre un cursor no operativo
(cerrado) provocar una excepcin del tipo invalid_cursor.
Excepciones
En PL/SQL una advertencia o condicin de error es llamada una excepcin. Estas pueden ser
definidas en forma interna (en tiempo de ejecucin de un programa) o explcitamente por el
usuario. Ejemplos de excepciones definidas en forma interna son la divisin por cero y la falta
de memoria en tiempo de ejecucin. Estas mismas condiciones excepcionales tienen sus
nombres propios y pueden ser referenciadas con ellos: zero_divide y storage_error.
10
Cuando ocurre un error se alcanza la excepcin, esto quiere decir que se ejecuta la porcin del
programa donde sta se encuentra implementada, transfirindose el control a ese bloque de
sentencias. Las excepciones definidas por el usuario deben ser alcanzadas explcitamente
utilizando la sentencia raise.
Con las excepciones ser pueden manejar los errores cmodamente sin necesidad de mantener
mltiples chequeos por cada sentencia escrita. Tambin provee claridad en el cdigo desde el
momento en que permite mantener las rutinas correspondientes al tratamiento de los errores
en forma separada de la lgica de la aplicacin.
Excepciones predefinidas
Las excepciones predefinidas no necesitan ser declaradas. Simplemente se utilizan cuando
estas son lanzadas por algn error determinado.
11
La conversin de una cadena de caracteres
SYS_INVALID_ROWID hacia un tipo rowid fall porque la cadena no -1410
representa un nmero
Se excedi el tiempo mximo de espera por un
TIMEOUT_ON_RESOURCE -51
recurso en Oracle
Una sentencia SELECT INTO devuelve ms de
TOO_MANY_ROWS -1422
una fila
Ocurri un error aritmtico, de conversin o
truncamiento. Por ejemplo, sucede cuando se
VALUE_ERROR -6502
intenta calzar un valor muy grande dentro de
una variable ms pequea
El programa intent efectuar una divisin por
ZERO_DIVIDE -1476
cero
Declaracin
DECLARE
error_01 EXCEPTION;
Reglas de Alcance
Una excepcin no puede ser declarada dos veces en un mismo bloque. Tal como las variables,
una excepcin declarada en un bloque es local a ese bloque y global a todos los sub-bloques
que comprende.
La sentencia RAISE
La sentencia RAISE permite lanzar una excepcin en forma explcita. Es factible utilizar esta
sentencia en cualquier lugar que se encuentre dentro del alcance de la excepcin. Ejemplo:
DECLARE
out_of_stock EXCEPTION; -- declaracin de la excepcin
total NUMBER(4);
BEGIN
IF total < 1 THEN
RAISE out_of_stock; -- llamada a la excepcin
END IF;
EXCEPTION
WHEN out_of_stock THEN
-- manejar el error aqu
WHEN OTHERS THEN
END;
12
Subprogramas
Los subprogramas son bloques de instrucciones de PL/SQL que pueden ser invocados por
otros y recibir parmetros. En PL/SQL existen dos tipos de subprogramas: Los Procedimientos
y las Funciones. Por regla general, se utiliza un procedimiento para ejecutar una accin
especfica y una funcin para calcular un valor.
Procedimientos
Un procedimiento es un subprograma que ejecuta una accin especfica. La sintaxis para
construirlos es la siguiente:
Esta sentencia es invlida, ya que debera decir slo param01 CHAR, sin especificar el
tamao del carcter.
13
Sin embargo, si es absolutamente necesario restringir el largo de una cadena como la del
ejemplo, se puede corregir la situacin codificando la llamada al procedimiento xxx de la
siguiente manera:
DECLARE
temp CHAR(5);
SUBTYPE Char5 IS temp%TYPE;
PROCEDURE xxx (param01 Char5) IS
El cuerpo del procedimiento comienza con la palabra reservada IS y termina con END,
seguido opcionalmente por el nombre del procedimiento.
Funciones
Una funcin es un subprograma que calcula un valor. La sintaxis para construir funciones es la
siguiente:
El cuerpo comienza con la palabra IS y termina con la palabra END, es decir, incluye las
secciones de declaraciones, sentencias ejecutables y una parte opcional de manejo de
excepciones. Ejemplo:
Esta misma funcin de ejemplo puede ser llamada desde una sentencia PL/SQL que reciba un
valor booleano, como por ejemplo, en:
14
DECLARE
renta_actual REAL;
codcargo CHAR(10);
BEGIN
IF revisa_salario (renta_actual, codcargo) THEN
La funcin revisa_salario acta como una variable de tipo booleano, cuyo valor depende de los
parmetros recibidos.
La sentencia RETURN
Esta sentencia termina inmediatamente la ejecucin de un programa, retornando el control al
bloque de programa que lo llam. No se debe confundir con la clusula return de las funciones,
que especifica el tipo de dato devuelto por ella.
La sintaxis para los procedimientos es simple, slo se necesita la palabra RETURN. Sin
embargo, en el caso de las funciones, esta sentencia debe contener un valor, que es aquel que
se va a devolver al programa que la llam. La expresin que sigue a la sentencia puede ser tan
compleja como se desee pero siempre debe respetar el tipo de datos que est definido en la
cabecera (especificacin) de la funcin.
Una funcin debe contener como mnimo una sentencia RETURN, de otra manera, al no
encontrarla, PL/SQL generar la excepcin PROGRAM_ERROR.
Creacin de paquetes
Un paquete es un esquema u objeto que agrupa tipos de PL/SQL relacionados, tems y
subprogramas. Los paquetes se constituyen de dos partes: la especificacin y el cuerpo.
La especificacin es la interfaz con las aplicaciones. En ella es posible declarar los tipos,
variables, constantes, excepciones, cursores y subprogramas disponibles para su uso
posterior.
Es posible depurar y modificar cuantas veces se desee el cuerpo de un paquete sin necesidad
de alterar por ello la especificacin del mismo.
15
PROCEDURE hire_employee (
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER) IS
BEGIN
INSERT INTO emp VALUES (empno_seq.NEXTVAL, ename, job, mgr,
SYSDATE, sal, comm, deptno);
END hire_employee;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;
END emp_actions;
16
Ejemplos para probar con SQL*PLUS de PL/SQL
Las tablas con las que vamos a trabajar son:
drop table accounts
/
create table accounts(
account_id number(4) not null,
bal number(11,2))
/
create unique index accounts_index on accounts (account_id)
/
drop table action
/
create table action(
account_id number(4) not null,
oper_type char(1) not null,
new_value number(11,2),
status char(45),
time_tag date not null)
/
drop table bins
/
create table bins(
bin_num number(2) not null,
part_num number(4),
amt_in_bin number(4))
/
drop table data_table
/
create table data_table(
exper_num number(2),
n1 number(5),
n2 number(5),
n3 number(5))
/
drop table emp
/
create table emp(
empno number(4) not null,
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2))
/
drop table inventory
/
create table inventory(
prod_id number(5) not null,
product char(15),
quantity number(5))
/
drop table journal
/
create table journal(
account_id number(4) not null,
action char(45) not null,
17
amount number(11,2),
date_tag date not null)
/
drop table num1_tab
/
create table num1_tab(
sequence number(3) not null,
num number(4))
/
drop table num2_tab
/
create table num2_tab(
sequence number(3) not null,
num number(4))
/
drop table purchase_record
/
create table purchase_record(
mesg char(45),
purch_date date)
/
drop table ratio
/
create table ratio(
sample_id number(3) not null,
ratio number)
/
drop table result_table
/
create table result_table(
sample_id number(3) not null,
x number,
y number)
/
drop table sum_tab
/
create table sum_tab(
sequence number(3) not null,
sum number(5))
/
drop table temp
/
create table temp(
num_col1 number(9,4),
num_col2 number(9,4),
char_col char(55))
/
18
/
delete from action
/
insert into action values
(3,'u',599,null,sysdate)
/
insert into action values
(6,'i',20099,null, sysdate)
/
insert into action values
(5,'d',null,null, sysdate)
/
insert into action values
(7,'u',1599,null, sysdate)
/
insert into action values
(1,'i',399,null,sysdate)
/
insert into action values
(9,'d',null,null,sysdate)
/
insert into action values
(10,'x',null,null,sysdate)
/
delete from bins
/
insert into bins values (1, 5469, 650)
/
insert into bins values (2, 7243, 450)
/
insert into bins values (3, 5469, 120)
/
insert into bins values (4, 5469, 300)
/
insert into bins values (5, 6085, 415)
/
insert into bins values (6, 5469, 280)
/
insert into bins values (7, 8159, 619)
/
delete from data_table
/
insert into data_table values
(1, 10, 167, 17)
/
insert into data_table values
(1, 16, 223, 35)
/
insert into data_table values
(2, 34, 547, 2)
/
insert into data_table values
(3, 23, 318, 11)
/
insert into data_table values
(1, 17, 266, 15)
/
insert into data_table values
(1, 20, 117, 9)
/
delete from emp
19
/
insert into emp values
(7369,'SMITH','CLERK',7902,TO_DATE('12-17-00','MM-DD-YY'),
800,NULL,20)
/
insert into emp values
(7499,'ALLEN','SALESMAN',7698,TO_DATE('02-20-01','MM-DD-YY'),
1600,300,30)
/
insert into emp values
(7521,'WARD','SALESMAN',7698,TO_DATE('02-22-01','MM-DD-YY'),
1250,500,30)
/
insert into emp values
(7566,'JONES','MANAGER',7839,TO_DATE('04-02-01','MM-DD-YY'),
2975,NULL,20)
/
insert into emp values
(7654,'MARTIN','SALESMAN',7698,TO_DATE('09-28-01','MM-DD-YY'),
1250,1400,30)
/
insert into emp values
(7698,'BLAKE','MANAGER',7839,TO_DATE('05-1-01','MM-DD-YY'),
2850,NULL,30)
/
insert into emp values
(7782,'CLARK','MANAGER',7839,TO_DATE('06-9-01','MM-DD-YY'),
2450,NULL,10)
/
insert into emp values
(7788,'SCOTT','ANALYST',7566,SYSDATE-5,3000,NULL,20)
/
insert into emp values
(7839,'KING','PRESIDENT',NULL,TO_DATE('11-17-01','MM-DD-YY'),
5000,NULL,10)
/
insert into emp values
(7844,'TURNER','SALESMAN',7698,TO_DATE('09-8-01','MM-DD-YY'),
1500,0,30)
/
insert into emp values
(7876,'ADAMS','CLERK',7788,SYSDATE-1,1100,NULL,20)
/
insert into emp values
(7900,'JAMES','CLERK',7698,TO_DATE('12-3-01','MM-DD-YY'),
950,NULL,30)
/
insert into emp values
(7902,'FORD','ANALYST',7566,TO_DATE('12-3-01','MM-DD-YY'),
3000,NULL,20)
/
insert into emp values
(7934,'MILLER','CLERK',7782,TO_DATE('01-23-02','MM-DD-YY'),
1300,NULL,10)
/
delete from inventory
/
insert into inventory values
(1234, 'TENNIS RACKET', 3)
/
insert into inventory values
20
(8159, 'GOLF CLUB', 4)
/
insert into inventory values
(2741, 'SOCCER BALL', 2)
/
delete from journal
/
delete from num1_tab
/
insert into num1_tab values (1, 5)
/
insert into num1_tab values (2, 7)
/
insert into num1_tab values (3, 4)
/
insert into num1_tab values (4, 9)
/
delete from num2_tab
/
insert into num2_tab values (1, 15)
/
insert into num2_tab values (2, 19)
/
insert into num2_tab values (3, 27)
/
delete from purchase_record
/
delete from ratio
/
delete from result_table
/
insert into result_table values (130, 70, 87)
/
insert into result_table values (131, 77, 194)
/
insert into result_table values (132, 73, 0)
/
insert into result_table values (133, 81, 98)
/
delete from sum_tab
/
delete from temp
/
commit
/
1.- En la tabla emp incrementar el salario el 10% a los empleados que tengan una
comisin superior al 5% del salario.
BEGIN
UPDATE EMP
SET SAL = SAL+SAL*(10/100)
WHERE COMM > (SAL*5/100);
END;
/
21
2.- Aadir la columna total2 y en ella escribir la suma del salario y la comisin de los
empleados con comisin distinta de 0.
DECLARE
CURSOR CURSOR2 IS SELECT COMM,SAL FROM EMP
WHERE COMM<>0
FOR UPDATE;
BEGIN
FOR REG IN CURSOR2 LOOP
UPDATE EMP
SET TOTAL2 = SAL+COMM
WHERE CURRENT OF CURSOR2;
END LOOP;
END;
/
DECLARE
comm emp.comm%type;
sal emp.sal%type;
CURSOR CURSOR2 IS SELECT COMM,SAL FROM EMP
WHERE COMM IS NOT NULL AND COMM<>0;
BEGIN
open cursor2;
loop
fetch cursor2 into comm, sal;
exit when cursor2%NOTFOUND;
UPDATE EMP
SET TOTAL2 = SAL+COMM
WHERE comm = emp.comm AND sal = emp.sal;
end loop;
END;
/
Alternativa:
3.- Insertar un empleado en la tabla EMP. Su nmero ser superior a los existentes y la
fecha de incorporacin a la empresa ser la actual.
DECLARE
NUM_EMPLEADO EMP.EMPNO%TYPE;
FECHA EMP.HIREDATE%TYPE;
BEGIN
SELECT MAX(EMPNO) INTO NUM_EMPLEADO FROM EMP;
SELECT SYSDATE INTO FECHA FROM DUAL;
NUM_EMPLEADO:=NUM_EMPLEADO +1;
INSERT INTO EMP
VALUES (NUM_EMPLEADO,'PEDRO','MATEMATIC',7839, 22
FECHA,3000,NULL,20,NULL);
END;
/
4.- Realizar un procedimiento para cambiar la fecha por el nmero de ao.
DECLARE
FECHA VARCHAR2(4);
CURSOR CURSOR1 IS SELECT TO_CHAR(HIREDATE,'YYYY') FROM EMP FOR
UPDATE;
BEGIN
OPEN CURSOR1;
LOOP
FETCH CURSOR1 INTO FECHA;
EXIT WHEN CURSOR1%NOTFOUND;
UPDATE EMP
SET HIREDATE='FECHA' WHERE CURRENT OF CURSOR1;
END LOOP;
CLOSE CURSOR1;
END;
/
5.- Aadir un nuevo empleado en la tabla emp. El nmero de empleado ser el del ltimo
+ 10. La fecha la actual, el departamento el 40.
DECLARE
EMPLEADO EMP.EMPNO%TYPE;
FECHAA EMP.HIREDATE%TYPE;
BEGIN
EMPLEADO := TRANSFORMACION1;
FECHAA := TRANSFORMACION2;
EJERCICIO_5(FECHAA,EMPLEADO,40);
END;
/
23
6.- Buscar todos los empleados que tienen un salario + comisin superior a 2000 y
asignarles como nuevo salario esta suma. Slo para los que tienen comisin.
DECLARE
PROCEDURE ACTUALIZAR IS
CURSOR C1 IS SELECT ENAME,SAL,COMM FROM EMP
WHERE SAL+COMM>2000 FOR UPDATE;
REGISTRO C1%ROWTYPE;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO REGISTRO;
EXIT WHEN C1%NOTFOUND;
UPDATE EMP
SET SAL=SAL+COMM WHERE CURRENT OF C1;
END LOOP;
CLOSE C1;
END ACTUALIZAR;
BEGIN
ACTUALIZAR;
END;
/
COMMIT;
END;
/
24
Disparadores de base de datos
25