Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
LENGUAJES
DEFINICION DE DATOS
DE
CONSULTA Y
3.7.1
3.7.2
3.7.3
3.7.4
3.7.5
3.7.6
3.7.7
3.7.8
3.7.9
3.7.10
3.7.11
3.7.12
3.7.13
3.7.14
3.1 Introduccin
El SQL es un lenguaje que permite expresar operaciones diversas, por ejemplo
aritmticas, combinatorias y lgicas, con datos almacenados en Bases de Datos
Relacionales, que son aquellas que se caracterizan porque la informacin est contenida
en estructuras, llamadas tablas, donde los datos estn dispuestos en filas y columnas.
SQL significa Structured Query Language (Lenguaje Estructurado de Consultas).
El concepto de Base de Datos Relacional arranca de un artculo publicado en 1970 por
Codd, empleado de IBM, donde se sentaban los conceptos bsicos de un modelo
relacional de datos y de un sublenguaje para acceder a ellos basado en el clculo de
predicados. La idea se desarroll en IBM, dando lugar a un primer prototipo llamado
System R que utilizaba un lenguaje llamado SEQUEL (que posteriormente dara lugar
al SQL).
El ANSI (American National Standards Institute) ha adoptado este lenguaje como
estndar, publicando y desarrollando unas especificaciones para este lenguaje, que has
sido posteriormente aceptadas por ISO (International Standards Organization). No
significa esto que los productos existentes sigan estrictamente esta norma,
principalmente porque el estndar no cubre todas las necesidades planteadas. Del mismo
modo, existen diferencias entre distintos productos comerciales.
Las peticiones de datos se expresan en SQL mediante sentencias que deben seguir las
normas sintcticas y semnticas del lenguaje. Estas sentencias se pueden escribir
directamente en la pantalla de un terminal interactivo, o pueden ser utilizadas
embebidas en programas, incorporndose as su capacidad expresiva a la lgica y
funciones de stos. A sta ltima forma de utilizar el SQL se le llama SQL dinmico o
embebido.
El SQL permite la realizacin de consultas y actualizaciones sobre datos almacenados
en tablas relacionales. Este es el principal uso que harn de l usuarios y programadores.
Pero tambin hay otras tareas que se pueden realizar mediante sentencias SQL, aunque
pertenecen ms a las responsabilidades de los administradores de las bases de datos
(DBA). Entre estas funciones adicionales se encuentran la definicin y destruccin de
objetos, y la gestin de autorizaciones de acceso.
Existen dos tipos de sentencias SQL:
Vamos a realizar una descripcin detallada del lenguaje SQL, y de aqu en adelante
consideraremos el SGBD ORACLE como el sistema relacional base para nuestros
ejemplos. Esto implica que no todas las sentencias SQL sern estndar, pero puesto que
ORACLE es la herramienta base en las prcticas de la asignatura, se ilustrar con mayor
Tema 3: Lenguajes de consulta y definicin de datos
3.2.2 Columnas
Cada columna de una tabla representa un (y slo un) atributo de la entidad. El nombre
de la columna debe indicar su naturaleza, en la medida de lo posible. Una columna se
identifica por su nombre, no por su posicin.
El orden interno de las columnas de una tabla carece de importancia. De hecho, jams
se conocer el orden fsico de las columnas. Se puede especificar el orden en el que
mostrar las columnas tras una seleccin, y por supuesto, esto no afectar al orden
interno de las columnas en la tabla.
3.2.4 Valor
Un valor es el dato referenciado por la interseccin de una fila y una columna
determinadas. Los valores pertenecen al tipo de datos al que pertenece la columna, y
pueden carecer de valor (NULL).
3.2.5 Vistas
Una vista es la representacin lgica de otra tabla o combinacin de tablas. Una vista
obtiene sus datos de las tablas en las que se basa, que se llaman tablas base. Estas tablas
base pueden ser tablas reales u otras vistas.
Las vistas se pueden utilizar casi de igual forma que las tablas. Sin embargo, las vistas
no contienen datos, sino que, como ya hemos dicho, los obtienen de las tablas base. Por
tanto, todas las operaciones realizadas sobre las vistas afectan realmente a las tablas
base.
Las vistas se utilizan para proporcionar diferentes representaciones de los datos que
residen en otras tablas o vistas. En general, las vistas se utilizan tambin con los
siguientes propsitos:
3.2.6 Indices
Los ndices se utilizan principalmente con dos propsitos:
Los ndices dan un acceso ms rpido a los datos para operaciones que devuelven una
pequea porcin de las filas de una tabla.
Una regla importante para determinar cuando es interesante indexar un atributo de una
tabla: Las consultas SQL que devuelven menos del 15% de las filas de una tabla pueden
ser realizadas ms rpidamente cuando se utilizan ndices.
Los ndices nicos tambin contribuyen a garantizar la no duplicidad de filas en una
tabla. Como regla general, siempre se debera crear un ndice sobre la clave primaria de
una tabla.
3.2.7 Clusters
El clustering es un medio de estructurar datos en una o ms tablas, de forma que las
filas estn fsicamente ms juntas. El clustering es beneficioso si una aplicacin
selecciona frecuentemente el mismo grupo de filas de una tabla o tablas.
El clustering puede mejorar el rendimiento de algunas operaciones; sin embargo,
tambin puede empeorar el de otras. Es conveniente asegurarse de las condiciones de
trabajo antes de decidir si se aplica o no clustering, y donde debe aplicarse
3.3 Expresiones
Por su importancia en los siguientes apartados, vamos a definir con cierta rigurosidad el
concepto de expresin. Su importancia es tal que una expresin forma parte de las
funciones SQL que ms se utilizan en el trabajo cotidiano.
Existen varias formas de identificar una expresin:
Tema 3: Lenguajes de consulta y definicin de datos
3.4.2 LONG
Es un tipo de datos que se utiliza para almacenar cadenas de hasta 65,535 caracteres.
Funciona exactamente igual que el VARCHAR, pero no se puede utilizar en las
clusulas WHERE, GROUP BY, ORDER BY, CONNECT BY y DISTINCT, ni como
ndices ni dentro de funciones.
3.4.3 NUMBER
Se utiliza para almacenar nmeros con una precisin mxima de 38 dgitos (lo que
incluye nmeros desde 1.0E-129 hasta 9.99E124), y una escala que va desde 84 hasta
127.
La sintaxis para este tipo es NUMBER[(precisin [, escala])]. Algunos ejemplos:
7,456,123.89
7,456,123.89
7,456,123.89
7,456,123.89
7,456,123.89
NUMBER
NUMBER(9)
NUMBER(9,1)
NUMBER(9,2)
NUMBER(9,-2)
7,456,123.89
7,456,123
7,456,123.9
7,456,123.89
7,456,100
Otros tipos de datos vlidos que se incluyen por compatibilidad son DECIMAL,
INTEGER, SMALLINT, FLOAT, REAL, y DOUBLE_PRECISION. Algunos ejemplos
de datos numricos: 7, 255, 29K, 6M, 3.56, 7E5, 3e-2.
3.4.4 DATE
Se usa para almacenar informacin de fechas y horas. Almacena informacin de siglo,
ao, mes, da, hora, minuto y segundo. Por defecto se toma la hora 00:00:00, y el
formato de fecha por defecto es DD-MON-YY. Existen funciones TO_DATE y
TO_CHAR para convertir entre distintos formatos.
Por ejemplo, TO_DATE(13-NOV-85 10:56 A.M., DD-MON-YY HH:MI A.M.)
3.4.6 NULL
No se trata de un tipo de datos concreto. Es ms bien un valor que indica la ausencia de
cualquier valor para un determinado literal (o columna).
Para comparar valores con NULL slo se pueden usar los operadores IS NULL o IS
NOT NULL.
3.5.1 Operadores
3.5.1.1 Operadores aritmticos
()
+*/
+-
Operador de precedencia
Denota un nmero positivo o negativo
Multiplicar o dividir
Sumar o restar
Comparacin
Distinto
Mayor que, menor que
Mayor o igual que, menor o igual que
Pertenencia a un conjunto (equivalente a =ANY)
Compara un valor con cada valor devuelto en una lista o subconsulta.
Debe ir precedido de los operadores =, !=, >, >=, <, <=.
Compara un valor con todos los devueltos por una lista o subconsulta.
Debe ir precedido de los operadores =, !=, >, >=, <, <=.
Entre x e y.
Cierto [Falso] si la subconsulta devuelve al menos una fila.
Patrn de comparacin. Los caracteres universales son % (*) y _(?).
Se usa para comprobar si un valor es o no nulo.
3.5.2 Funciones
ABS(n)
CEIL(n)
FLOOR(n)
MOD(m,n)
POWER(m,n)
SQRT(n)
CHR(n)
LOWER(char)
LPAD(char1,n [,char2])
UPPER(char)
ASCII(char)
LENGTH(char)
AVG([DISTINCT|ALL] n)
COUNT([DISTINCT|ALL] expr)
MAX([DISTINCT|ALL] expr)
MIN([DISTINCT|ALL] expr)
SUM([DISTINCT|ALL] n)
RPAD(char1,n [,char2])
LTRIM(char1[,char2])
RTRIM(char1[,char2])
Ejemplo:
CREATE TABLE EMP
(EMPNO NUMBER NOT NULL PRIMARY KEY,
ENAME CHAR(10) NOT NULL CHECK(ENAME=UPPER(ENAME)),
DEPTNO NUMBER(2),
FOREIGN KEY (DEPTO) REFERENCES DEPT(DEPTNO));
Ejemplo:
CREATE VIEW ROSTER (ID, DEPTNO)
AS SELECT EMPNO, DEPTNO FROM EMP
WHERE DEPTNO IN (SELECT DISTINCT DEPTNO FROM DEPT)
WITH CHECK OPTION CONSTRAINT WCO;
(La opcin with check option impide insertar una fila cuyo numero de departamento no
exista en la tabla DEPTNO. La fila ser realmente insertada en la tabla EMP slo si se
cumple la condicin.)
10
Ejemplo:
CREATE UNIQUE INDEX I_EMP$EMPNO ON EMP (EMPNO);
Ejemplo:
DROP TABLE MY_TEST
DROP VIEW MY_VIEW
DROP INDEX MY_INDEX
Ejemplo:
DESCRIBE EMP;
11
Eliminar restricciones
Indicar que se ha realizado un backup de la tabla
Sintaxis:
ALTER TABLE [user.]table
[ADD ( {column_element | table_constraint}
[,{column_element | table_constraint} ] ) ]
[MODIFY (column_element [,column_element] ) ]
[DROP CONSTRAINT constraint]
[BACKUP]
Ejemplo:
ALTER TABLE EMP
ADD (THRIFTPLAN NUMBER(7,2), LOANCODE CHAR(1));
ALTER TABLE EMP
MODIFY (THRIFTPLAN NUMBER(9,2))
DROP CONSTRAINT ENAME_CNSTR;
Ejemplo:
RENAME DEPT TO EMP_DEPT;
CREATE TABLE TEMPORARY (NEWNAME)
AS SELECT OLDNAME FROM STATIC;
DROP TABLE STATIC;
RENAME TEMPORARY TO STATIC;
12
Ejemplo:
SELECT ENAME, SAL, JOB, DEPTNO
FROM EMP
WHERE DEPTNO = 30;
SELECT DEPTNO, MIN(SAL), MAX(SAL)
FROM EMP
WHERE JOB = CLERK
GROUP BY DEPTNO
HAVING MIN(SAL)>1000;
Ejemplo:
INSERT INTO EMP (EMPNO, ENAME, JOB, SAL, COMM, DEPTNO)
VALUES (7980, JINKS, CLERCK, 1.2E3, NULL, 40);
INSERT INTO BONUS
SELECT ENAME, JOB, SAL, COMM FROM EMP
WHERE COMM < 25 * SAL OR JOB IN (PRESIDENT, MANAGER);
Ejemplo:
DELETE FROM TEMP_ASSIGN;
DELETE FROM EMP
WHERE JOB = SALESMAN
AND COMM < 100;
13
Ejemplo:
UPDATE EMP
SET COMM = NULL
WHERENJOB = TRAINEE;
Ejemplo:
LOCK TABLE EMP IN EXCLUSIVE MODE NOWAIT
14
Sintaxis:
COMMIT [WORK]
WORK se usa por compatibilidad ANSI
Ejemplo:
COMMIT
Finaliza la transaccin
Deshace los cambios realizados durante la ltima transaccin
Elimina los savepoints de la transaccin
Elimina los bloqueos de la transaccin
Sintaxis:
ROLLBACK [WORK]
[TO [SAVEPOINT] savepoint]
Ejemplo:
ROLLBACK;
ROLLBACK TO SAVEPOINT SP5;
15
Ejemplo:
SAVEPOINT SP1;
Sintaxis:
GRANT dabase_priv [, databse_priv]
TO user [, user]
[IDENTIFIED BY password [, password] ]
Siendo database_priv = DBA | CONNECT | RESOURCE
GRANT RESOURCE [ (quota [k|m] ) ]
ON tablespace
TO { PUBLIC | user [, user] }
Siendo quota el espacio en bytes.
GRANT { object_priv [, object_priv] | ALL [PRIVILEGES] }
ON [user.]object
TO { user | PUBLIC } [, user]
[WITH GRANT OPTION]
Siendo object_priv = ALTER | DELETE | INDEX | INSERT | REFERENCES |
SELECT | UPDATE. Si se utiliza UPDATE o REFERENCES, se pueden
especificar columnas.
Ejemplo:
GRANT CONNECT, RESOURCE TO SCOTT IDENTIFIED BY TIGER;
GRANT RESOURCE (10M) ON FINANCE TO SCOTT;
GRANT ALL ON BONUS TO JONES WITH GRANT OPTION;
GRANT SELECT, UPDATE ON GOLF_HANDICAP TO PUBLIC;
16
Sintaxis:
REVOKE { [CONNECT] [, RESOURCE] [,DBA] }
FROM user [, user]
REVOKE space_privilege ON tablespace
FROM user [, user]
REVOKE {object_priv [, object_priv] | ALL [PRIVILEGES] }
ON [user.]object
FROM {user | PUBLIC} [,user]
Ejemplo:
REVOKE RESOURCE FROM SCOTT, JOLLY_ROGER;
REVOKE RESOURCE ON SYSTEM FROM SCOTT;
REVOKE ALTER, DELETE, INSERT, UPDATE ON DEPT10 FROM JONES;
Imponer que los valores de un atributo dado no pueden ser nulos (NOT
NULL)
Imponer que el valor de una columna debe ser nico en toda la tabla
(UNIQUE)
Identificar una columna o grupo de columnas como clave primaria de una
tabla.
Identificar el valor de una columna o conjunto de columnas como clave
ajena en otra tabla.
Obligar a que los valores de una columna satisfagan una expresin o estn
dentro de un conjunto de valores predeterminado.
Sintaxis:
Para una tabla:
[{UNIQUE | PRIMARY KEY} (column [, column] )
[CONSTRAINT constraint] ]
[FOREIGN KEY (column [, column] )
REFERENCES [user.]table [(column [, column] ) ]
[CONSTRAINT constraint]
[CHECK (condition) [CONSTRAINT constraint] ]
17
Ejemplo:
CREATE TABLE P_E
(PROJECT NUMBER,
EMPLOYEE NUMBER,
PRIMARY KEY ( PROJECT, EMPLOYEE));
o
CREATE TABLE p_e
(DEPTNO NUMBER PRIMARY KEY, );
CREATE TABLE EMP
(EMPNO NUMBER(5) NOT NULL CONSTRAINT NN_CONSTRNT);
Nota: Caso especial para la creacin de tablas. En ORACLE, cuando se desea mantener
completamente la integridad referencial con opciones, se puede utilizar lo siguiente:
Sintaxis:
FOREIGN KEY ()
REFERENCES ()
ON { DELETE | MODIFY } { RESTRICT | CASCADE | SET NULL }
18
3.7 PL/SQL
PL/SQL es un lenguaje de programacin avanzado de cuarta generacin (4GL). Es la
extensin procedural que proporciona Oracle al SQL. El objetivo de Oracle al
proporcionar este lenguaje fue ofrecer una herramienta de fcil uso para obtener un
acceso a la informacin almacenada en una base de datos Oracle, a travs de la
inclusin de sentencias SQL embebidas dentro de un lenguaje de programacin de alto
nivel.
La idea del SQL embebido no es nueva, ni se le debe a Oracle. El SQL embebido es un
mtodo de programacin que permite acceder a las bases de datos a travs de sentencias
SQL que se declaran dentro de un programa de alto nivel, y que permiten tanto obtener
informacin de la base de datos como actualizarla.
El modo de trabajo cuando se utiliza SQL embebido dentro de un programa es
ligeramente diferente al modo de proceder cuando se realiza un programa normal. Lo
habitual es realizar un programa cuyo cdigo fuente se compila y se obtiene un
ejecutable que realiza las tareas programadas. Sin embargo, cuando se utiliza SQL
embebido, el proceso consta de tres fases en lugar de dos: la primera es igual que en el
caso anterior, es decir, la creacin del cdigo fuente, esta vez con sentencias SQL
apropiadamente declaradas dentro del cdigo; la segunda es distinta, y en este caso
consiste en un proceso de pre-compilacin, donde todas las sentencias SQL se
convierten a cdigo del lenguaje de alto nivel que se est utilizando; la tercera y ltima
corresponde a la segunda fase del caso anterior, y no es ms que la compilacin final del
cdigo fuente resultado de la pre-compilacin, con lo que se obtiene un cdigo
ejecutable.
En particular, el procesamiento que se realiza de los programas PL/SQL por parte de
Oracle sigue la siguiente arquitectura:
19
Veamos ahora un ejemplo de un programa realizado en PL/SQL, lo que nos dar una
mejor idea del tipo de programacin que estamos definiendo:
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;
donde se aprecia un primer bloque para las definiciones que es opcional, un segundo
bloque que contiene el cdigo del programa, y un ltimo bloque, llamado de
excepciones, incluido en el bloque principal, que define las acciones a realizar en caso
de errores, y tambin es opcional.
20
NUMBER(4);
BOOLEAN;
En este caso, la variable bonus tomar el valor definido por el 10% del salario de un
empleado en concreto.
La declaracin de constantes se hace igual que la declaracin de variables, pero se
aade la palabra reservada CONSTANT y de forma inmediata se debe definir un valor
para dicha constante:
credit_limit CONSTANT REAL := 5000.00;
3.7.3 Cursores
Oracle utiliza reas de trabajo para ejecutar sentencias SQL y almacenar la informacin
que se va a procesar. Por ejemplo, cuando se desea utilizar una sentencia SQL que
recupere ms de un registro de una tabla, la informacin no se podr recuperar toda de
golpe, sino que se tendr que proceder registro a registro. Para ello se utilizan los
cursores, es decir, para reservar una zona de memoria donde se recibir la informacin
del registro, y poder procesar as todos los registros objeto de la consulta.
La definicin de cursores se realiza del siguiente modo:
DECLARE
CURSOR c1 IS
SELECT empno, ename, job FROM emp WHERE deptno = 20;
21
DECLARE
BEGIN
CURSOR c1 IS
SELECT ename, sal, hiredate, deptno FROM emp;
...
FOR emp_rec IN c1 LOOP
...
salary_total :=
END LOOP;
salary_total + emp_rec.sal;
Esta declaracin indica que la variable my_title es del tipo del atributo title de la tabla
books. Si lo que deseamos es, sin embargo, declarar una variable de tipo registro que
contenga todos los atributos de una tabla, lo haremos del siguiente modo:
dept_rec dept%ROWTYPE;
lo que indica en este caso que la variable dept_rec es un registro (contiene todos los
campos) de la tabla dept. En este caso, se utiliza una notacin de . para indicar los
campos de un registro (por ejemplo, dept_rec.deptno har referencia al campo deptno de
la tabla dept).
Las variables de tipo registro se suelen utilizar para recoger la informacin de una tabla
dentro de un cursor. El siguiente ejemplo muestra como se realizara esta accin:
DECLARE
CURSOR c1 IS
SELECT ename, sal, hiredate, job FROM emp;
emp_rec c1%ROWTYPE;
22
23
...
comm_missing EXCEPTION;
-- declaracin de la excepcin
...
IF commission IS NULL THEN
RAISE comm_missing; -- lanzar la excepcin
END IF;
bonus := (salary * 0.10) + (commission * 0.15);
EXCEPTION
WHEN comm_missing THEN ... -- procesar la excepcin
WHEN OTHERS THEN ... -- procesar cualquier otra excepcin
END;
3.7.7 Delimitadores
Los smbolos que se pueden utilizar como delimitadores en un programa PL/SQL son
los siguientes y tienen el siguiente significado:
SIMBOLO
+
%
.
/
(
)
:
,
*
=
<
>
;
:=
SIGNIFICADO
Operador suma
Indicador de atributo
Delimitador de cadenas o caracteres
Delimitador de componentes
Operador divisin
Delimitador de expresin
Delimitador de expresin
Indicador de variable husped
Separador de items
Operador multiplicacin
Delimitador de identificadores
Operador comparador igual que
Operador comparador menor que
Operador comparador mayor que
Final de sentencia
Operador resta
Operador asignacin
24
||
**
/*
*/
..
!=
<>
<=
>=
--
25
numricas, pero que tienen perfecto sentido dentro del mbito de trabajo en el que
estamos. A continuacin se presentan los principales operadores adicionales:
IS NULL variable. Operador que devuelve un valor booleano verdadero o falso segn
la variable sea nula o no nula.
variable LIKE valor. Operador que devuelve un valor booleano verdadero o falso segn
la cadena almacenada en variable sea igual al dato valor. No se debe confundir este
operador con el de igualdad, que aunque se puede aplicar a cadenas, no permite el uso
de caracteres universales (%, _).
variable BETWEEN valor1 AND valor2. Operador que devuelve un valor booleano
verdadero o falso segn la variable est o no comprendida entre los valores valor1 y
valor2
variable IN conjunto. Operador que devuelve un valor booleano segn el valor de la
variable se encuentre dentro de un conjunto de valores.
3.7.10 Funciones
PL/SQL permite la utilizacin de funciones predefinidas para trabajar con varios tipos
de datos: nmeros, caracteres, fechas, referencias de objetos, etc. Adems existe un
conjunto de funciones de propsito general y otro conjunto de funciones que permiten
realizar conversiones entre tipos de datos. Se presenta a continuacin una lista que
muestra un esquema de las funciones predefinidas del mbito de aplicacin de cada una
de ellas:
Funciones sobre errores: SQLCODE, SQLERRM.
Funciones sobre nmeros: ABS, ACOS, ASIN, ATAN, ATAN2, CEIL, COS, COSH,
EXP, FLOOR, LN, LOG, MOD, POWER, ROUND, SIGN, SIN, SINH, SQRT, TAN,
TANH, TRUNC.
Funciones sobre caracteres: ASCII, CHR, CONCAT, INITCAP, INSTR, INSTRB,
LENGTH, LENGTHB, LOWER, LPAD, LTRIM, NLS_INITCAP, NLS_LOWER, NLSSORT,
NLS_UPPER, REPLACE, RPAD, RTRIM, SOUNDEX, SUBSTR, SUBSTRB, TRANSLATE,
TRIM, UPPER.
Funciones de conversin: CHARTOROWID, CONVERT, HEXTORAW, RAWTOHEX,
26
27
donde el return_type debe representar un registro de una base de datos, y los parmetros
son tipos de datos vlidos SQL. Algunos ejemplos de declaraciones de cursores vlidas:
DECLARE
Un cursor puede aceptar parmetros, que pueden aparecer en la consulta asociada del
mismo modo que pueden aparecer constantes. Dicho de otro modo, es una forma de
pasar variables a las consultas SQL que ejecutan los cursores. Los parmetros slo
pueden ser de entrada, se especifican con la palabra IN, y no sirven para devolver
resultados de la ejecucin de una sentencia. La sintaxis de los parmetros es:
cursor_parameter_name [IN] datatype [{:= | DEFAULT} expression]
CURSOR c1 IS SELECT ename, job FROM emp WHERE sal < 3000;
...
OPEN c1;
...
28
BEGIN
emp_name emp.ename%TYPE;
salary
emp.sal%TYPE;
CURSOR c1 (name VARCHAR2, salary NUMBER) IS SELECT ...
...
...
OPEN c1(emp_name, 3000);
OPEN c1('ATTLEY', 1500);
OPEN c1(emp_name, salary);
Los cursores implcitos se abren para procesar cualquier sentencia SQL no asociada con
un cursor explcito. Con los cursores implcitos no se pueden utilizar las sentencias
OPEN, FETCH y CLOSE.
Los cursores (variables) tienen 4 atributos que se pueden utilizar para tener un mayor
control sobre el procesamiento de las consultas dentro de los bucles. Dichos parmetros
son:
%FOUND. Atributo que contiene el valor NULL despus de que se abre el cursor, pero
antes de realizar el primer FETCH. Despus de cada FETCH (incluido el primero), el
atributo toma el valor TRUE si se encontr algn registro que satisfaga la consulta
definida para el cursor, o FALSE en caso contrario. Ejemplo de uso:
LOOP
-- cursor is open
29
...
-- cursor is closed, so open it
OPEN c1;
END IF;
ELSE
Por ltimo, vamos a ilustrar el uso de los cursores con algunos ejemplos.
Ejemplo 1: El programa utiliza un cursor para obtener los valores de tres campos (n1,
n2 y n3) de la tabla data_table, y guarda el resultado en tres variables locales del
programa. Posteriormente, el programa inserta en otra tabla (temp) una serie de datos
que han sido calculados en la informacin obtenida con el cursor para el procesamiento
de la consulta anterior. Obsrvese la finalizacin del programa con la clusula
COMMIT, que valida todas las inserciones realizadas en la tabla temp de forma
conjunta, en lugar de hacer una validacin una a una.
DECLARE
BEGIN
END;
num1
num2
num3
result
CURSOR
Declare variables
having same types as
database columns
data_table WHERE exper_num = 1;
OPEN c1;
LOOP
FETCH c1 INTO num1, num2, num3;
EXIT WHEN c1%NOTFOUND;
result := num2/(num1 + num3);
INSERT INTO temp VALUES (result, NULL, NULL);
END LOOP;
CLOSE c1;
COMMIT;
30
Ejemplo 2: Este programa comprueba todos los contenedores que contienen el item
nmero 5469, retirando sus contenidos hasta acumular un total de 1000 unidades.
DECLARE
BEGIN
order
END;
31
donde los parmetros se definen de la siguiente forma (IN indica parmetro de entrada,
OUT indica parmetro de salidad, IN OUT indica parmetro de entrada/salida):
parameter_name [IN | OUT [NOCOPY] | IN OUT [NOCOPY]] datatype_name
[{:= | DEFAULT} expression]
Hay que destacar que los tipos de datos de los parmetros no se pueden restringir. Por
ejemplo, no se puede definir un tipo de datos CHAR(5), sino que se debe definir un tipo
de datos CHAR.
Un ejemplo de procedimiento sera el siguiente:
PROCEDURE raise_salary (emp_id INTEGER, amount REAL) IS
current_salary REAL;
salary_missing EXCEPTION;
BEGIN
SELECT sal INTO current_salary FROM emp
WHERE empno = emp_id;
IF current_salary IS NULL THEN
RAISE salary_missing;
ELSE
UPDATE emp SET sal = sal + amount
WHERE empno = emp_id;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO emp_audit VALUES (emp_id,'No such number');
WHEN salary_missing THEN
INSERT INTO emp_audit VALUES (emp_id,'Salary is null');
END raise_salary;
donde los parmetros, igual que en los procedimientos, se definen de la siguiente forma:
parameter_name [IN | OUT [NOCOPY] | IN OUT [NOCOPY]] datatype_name
[{:= | DEFAULT} expression]
32
Tanto los procedimientos como las funciones se pueden declarar dentro de la seccin de
declaracin de un programa PL/SQL, pero al final de la seccin, despus de la
declaracin del resto de items del programa. Es posible realizar una declaracin previa
de los procedimientos sin su definicin (para ser utilizada por el resto de procedimientos
que la necesiten), y declarar su definicin con posterioridad. Por ejemplo:
DECLARE
Tanto los procedimientos como las funciones permiten el polimorfismo, esto es, se
pueden definir varios subprogramas con el mismo nombre, pero con distinto nmero y/o
tipo de parmetros. Esto aporta enormes ventajas en el trabajo con subprogramas, pero
requiere especial atencin por parte del programador para no cometer errores y/o
mantener subprogramas obsoletos o sin uso. Las funciones, adems, pueden definirse de
forma recursiva.
33
Programa 1:
DECLARE
x NUMBER := 100;
BEGIN
FOR i IN 1..10 LOOP
IF MOD(i,2) = 0 THEN
-- i is even
INSERT INTO temp VALUES (i, x, 'i is even');
ELSE
INSERT INTO temp VALUES (i, x, 'i is odd');
END IF;
x := x + 100;
END LOOP;
COMMIT;
END;
Programa 2:
DECLARE
CURSOR c1 is
SELECT ename, empno, sal FROM emp ORDER BY sal DESC;
my_ename CHAR(10);
my_empno NUMBER(4);
my_sal
NUMBER(7,2);
BEGIN
OPEN c1;
FOR i IN 1..5 LOOP
FETCH c1 INTO my_ename, my_empno, my_sal;
EXIT WHEN c1%NOTFOUND; /* in case the number requested */
/* is more than the total
*/
/* number of employees
*/
INSERT INTO temp VALUES (my_sal, my_empno, my_ename);
COMMIT;
END LOOP;
CLOSE c1;
END;
Programa 3:
DECLARE
x NUMBER := 0;
counter NUMBER := 0;
BEGIN
FOR i IN 1..4 LOOP
x := x + 1000;
counter := counter + 1;
INSERT INTO temp VALUES (x, counter, 'outer loop');
/* start an inner block */
DECLARE
x NUMBER := 0; -- this is a local version of x
BEGIN
FOR i IN 1..4 LOOP
x := x + 1; -- this increments the local x
counter := counter + 1;
INSERT INTO temp VALUES (x, counter, 'inner loop');
END LOOP;
END;
END LOOP;
COMMIT;
END;
34
Programa 4:
DECLARE
CURSOR c1 IS
SELECT account_id, oper_type, new_value FROM action
ORDER BY time_tag
FOR UPDATE OF status;
BEGIN
FOR acct IN c1 LOOP -- process each row one at a time
acct.oper_type := upper(acct.oper_type);
/*----------------------------------------*/
/* Process an UPDATE. If the account to */
/* be updated doesn't exist, create a new */
/* account.
*/
/*----------------------------------------*/
IF acct.oper_type = 'U' THEN
UPDATE accounts SET bal = acct.new_value
WHERE account_id = acct.account_id;
IF SQL%NOTFOUND THEN -- account didn't exist. Create it.
INSERT INTO accounts
VALUES (acct.account_id, acct.new_value);
UPDATE action SET status =
'Update: ID not found. Value inserted.'
WHERE CURRENT OF c1;
ELSE
UPDATE action SET status = 'Update: Success.'
WHERE CURRENT OF c1;
END IF;
/*--------------------------------------------*/
/* Process an INSERT. If the account already */
/* exists, do an update of the account
*/
/* instead.
*/
/*--------------------------------------------*/
ELSIF acct.oper_type = 'I' THEN
BEGIN
INSERT INTO accounts
VALUES (acct.account_id, acct.new_value);
UPDATE action set status = 'Insert: Success.'
WHERE CURRENT OF c1;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- account already exists
UPDATE accounts SET bal = acct.new_value
WHERE account_id = acct.account_id;
UPDATE action SET status =
'Insert: Acct exists. Updated instead.'
WHERE CURRENT OF c1;
END;
/*--------------------------------------------*/
/* Process a DELETE. If the account doesn't */
/* exist, set the status field to say that
*/
/* the account wasn't found.
*/
/*--------------------------------------------*/
ELSIF acct.oper_type = 'D' THEN
DELETE FROM accounts
WHERE account_id = acct.account_id;
35
IF SQL%NOTFOUND THEN
-- account didn't exist.
UPDATE action SET status = 'Delete: ID not found.'
WHERE CURRENT OF c1;
ELSE
UPDATE action SET status = 'Delete: Success.'
WHERE CURRENT OF c1;
END IF;
/*--------------------------------------------*/
/* The requested operation is invalid.
*/
/*--------------------------------------------*/
ELSE -- oper_type is invalid
UPDATE action SET status =
'Invalid operation. No action taken.'
WHERE CURRENT OF c1;
END IF;
END LOOP;
COMMIT;
END;
36