1. PROCEDIMIENTOS ALMACENADOS
1.1. Introduccion.
1.1 Introduccion a las bases de datos
1.1.1 Introduccion a sql y sql*plus
1.1.2 Sentencias sql y sql*plus
1.1.3. Funciones SQL
1.1.4 Join
1.1.5 Subquery
1.1.6 Interactive reports
1.1.7 DML
1.1.8 DDL
1.1.9 Constraints
1.1.10 Vistas
1.1.11 Objetos de las bases de datos

2.1 PL/SQL
2.1.1 Introduccion
2.1.2 Estructura basica
2.1.3 Variables
2.1.4 Funciones SQL en PL/SQL
2.1.5 Guia para programar en PL/SQL
2.1.6 Sentencia SELECT en PL/SQL
2.1.7 Sentencias DML
2.1.8 Cursor
2.1.9 Estructuras condicionales
2.1.10 Estructuras repetitivas
2.1.11 Tipos de datos Compuestos
2.1.11.1 Record
2.1.11.2 Table
2.1.12 Cursores
2.1.13 Excepciones
2.1.12
. Creacion de funciones y procedimientos almacenados.
2.1.12.1 Subprogramas
2.1.12.2 Paquetes
2.1.12.3 Triggers


Introduccion a las bases de datos

Que es una base de datos?
Una base de datos en un programa el cual se encuentra en memoria y el cual se encarga de manejar:
- E/S
- Protección
- Almacenamiento
- Elaboración
de la información que el usuario desea.

Tipos de bases de datos
Desde el punto de vista de la organización lógica tenemos:
- Jerarquicas (progress)
- Relacionales (oracle, access)

Desde el punto de vista del numero de usuarios
- Monousuario (dbase, access)
- Multiusuario cliente/servidor (oracle)

Componentes
Motor : se encarga de manejar la base de datos
Servicio de red : se encarga de establecer conexiones y realizar las transmisiones entre el cliente y el servidor
Listener : se encarga de recibir las llamadas que llegan a la bd por el servicio de red. Una vez las recibe se las pasa a la base de datos
Utilidades :Son las que se encargan de interpretar consultas, administrar la bd, realizar copias de seguridad y entre otras cosas monitorear el rendimiento.

A todo esto se le llama RDBMS (Relational Data Base Manager System) siendo su creador IBM. En 1979 se implemento en Oracle su primera versión comercial.

Modelo entidad relación

Es aquel modelo que nos ilustra las diferentes entidades que se encuentran en nuestro sistema y nos muestra la relación que existe entre ellos.

< en el no especificamos coma vamos a acceder a las tablas ni como las vamos a organizar físicamente>

Componentes
Entidad: Es algo sobre el cual debemos mantener información y el cual es parte importante de nuestro sistema.
Atributo: Es algo que describe la entidad
Relación: Es la asociación que existe entre entidades (vínculos entre las tablas)

Terminología
Tabla: Es una estructura lógica que sirve para almacenar todos los datos necesarios de lo que vamos a modelar
Esta contiene:
Filas : registros de la base de datos
Columnas : campos (información básica de c/u de los registros)

El orden en el cual se encuentren los registros no es importante, lo que vale es que los campos correspondan con la información del registro.
Cada registro debe estar identificado con un campo principal denominado llave primaria. Como condición dos registros no pueden tener la misma llave y no pueden tener un valor nulo.
Otro tipo de llave es la denominada llave foránea y con ella nos vamos a poder referira otras tablas o a la misma por medio de sus llaves foráneas.


1. PROCEDIMIENTOS ALMACENADOS
1.1. Introducción.

SQL
Nació por una publicación en el año 1970 por E.F. Codd llamada “A relational model of data for large shared data banks”.
IBM utilizo este modelo y creo SEQUEL – Structured QUEry Languaje.
En 1979 Oracle, en un comienzo Relational Software saco la primera implementación de SQL.
En 1992 fue acepatado por la ANSI y la ISO como el lenguaje estándar para bases de datos relacionales.

Utilizamos SQL para poder acceder y manipular bd relacionales. No existe otra manera de comunicarse con oracle.

SQL es:
- eficiente
- fácil de usar
- tiene funciones que permiten trabajar con la bd
- no se necesita mucha experiencia de programación

SQL y SQL*plus (interacción)
Como ya sabemos, SQL es un lenguaje de comandos para comunicaciones con el servidor Oracle desde cualquier aplicación.
Cuando se escribe una sentencia SQL esta se almacena en una parte de memoria llamada SQL buffer y se mantiene hasta que se digite una nueva sentencia.

SQL*plus es una herramienta de Oracle que reconoce y envía sentencias SQL al sevidor Oracle para su ejecución.

Características de SQL*plus
- Acepta entradas SQL que vengan de un archivo
- Nos provee un editor para modificar las sentencias SQL
- Nos permite configurar el entorno
- Podemos generar los reportes y darles un formato
- Podemos acceder a bases de datos remotas y locales.
- Nos permite crear scripts, almacenarlos, cargarlos y volverlos mas adelante a utilizar.

SQL SQL*plus
- Es un lenguaje para comunicarse - reconoce sentencia SQL y las envias al con el servidor Oracle servidor
- Es un lenguaje estandarizado por - Es una herramienta de Oracle. Es la
la ANSI interfaz para ejecutar sentencias SQL
- Manipula datos en la bd - No manipula valores de la bd
- No puede ser abreviado - Puede abreviarse
- Usa un carácter de fin de sentencia - No usa un carácter de fin de sentencia
para poder ejecutarlo

Categorías de los comandos SQL*plus

- Ambiente : Afectar la forma del entorno donde vamos a introducir las sentencias
- Formato : Dar formato a los resultados de los querys
- Manipulación de archivos : cargar, guardar o ejecutar scrypts
- Ejecución : enviar sentencias SQL al servidor Oracle
- Edición : modificar sentencias SQL en el buffer
- Interacción : Me permite crear y pasar variables a las sentencias SQL, imprimirlas y mostrar mensajes por pantalla
- Varios :Realizar otros tipos de operaciones como conexión y manipulación del ambiente


Sentencias SQL*plus

Mostrando la estructura de una tabla.

Con el SQL*plus usted puede mostrar la estructura de una tabla utilizando el comando DESCRIBE. Con este comando vamos a poder mostrar los nombres de las columnas, los tipos de datos y aquellos que deben contener un valor.

DESC[RIBE] tabla

SQL> DESCRIBE tabla

Después de ejecutar este comando, se desplegarán estos tres tipos de información:

Name                        Null?                 Type

Name        nos indica el nombre que tiene nuestra columna

Null      nos indica si esa columna debe o no tener datos. Si aparece NOT NULL, esto nos indicara que esa columna si debe tener datos.

Type     Nos muestra el tipo de dato que debe trabajar en esta columna

Para visualizar el catalogo del usuario debemos ejecutar
la siguiente
sentencia:

SQL > SELECT *
2 FROM CAT;

Tipos de datos
NUMBER (p,s) P nos dice cual es el máximo número de dígitos
S nos indica el número de dígitos a la derecha del decimal
VARCHAR2 (s) S nos indica el tamaño de la variable
DATE Tipo de dato que nos representa una fecha
CHAR(s)

Comandos de edición
A[PPEND] text -- adiciona un texto al final de la línea
C[HANGE]/old/new -- Cambia un texto viejo por uno nuevo
C[HANGE]/text/ -- Borra el texto de la línea actual
CL[EAR]BUFF[ER] -- Borra todas las líneas del SQL buffer
DEL -- Borra la línea actual
I[NPUT] -- inserta un numero indefinido de líneas
I[NPUT]text -- Inserta líneas de texto
L[IST] -- Lista todas las líneas que se encuentren en el SQL buffer
L[IST]n -- Lista la línea n
L[IST]n m -- Lista un rango de líneas. El comprendido entre n y m
R[UN] -- Muestra y corre el la sentencia SQL que esta en el buffer
n -- Especifica la línea actual
n text -- Remplaza la línea n con el texto
0 text -- Inserta una línea antes de la línea 1

Comandos de archivo
SAV[E] filename [.ext] -- Salva el contenido actual del buffer
[RE[PLACE] APP[END]]  use append para añadir en uno que ya exista, replace para sobreescribir.
GET filename [.ext] -- Escribe el contenido del archivo en el buffer
STA[RT] filename [.ext] -- Corre un comando de archivo salvado
@ filename -- Corre un comando de archivo salvado
ED[IT] -- Invoca el editor y salva el contenido del buffer en afiedt.buf
ED[IT] [filename[.ext]] -- Invoca el editor para editar el contenido de un archivo
SPO[OL][filename[.ext]]|OFF|OUT] -- Guarda el query en un archivo. OFF cierra el archivo. OUT cierra el archivo y lo envía al sistema de impresión.
EXIT -- Sale de SQL*plus.

Comandos SET
ARRAYSIZE
COLSEP
FEEDBACK
HEADING
LINESIZE ; Nos especifica el máximo número de caracteres por linea
LONG
PAGESIZE ; Nos especifica el número de lineas en la página
PAUSE
TERMOUT

Comandos de Formatos
COLUMN ; Nos controla el formato que va a manejar la columna
TTITLE ; Nos especifica el encabezado que va a tener nuestro reporte
BTITLE ; Nos especifica el pie de página que debe aparecer en el reporte
BREAK

Para que estas variables nos queden definidas para
cada sesión, modificar el archivo login.sql, colocando en el
la configuración que queramos.

Reglas para trabajar en SQL

Palabras que maneja el tutoríal de Oracle.

<< Una keyword se refiere a un elemento individual de SQL: SELECT, FROM…>>
<< Una clause se refiere a una parte de una sentencia de SQL>>
<< Un statement se refiere a una combinación de una o mas clauses: SELECT * FROM>>

Para escribir sentencias que sean fáciles de leer y de editar, haga lo siguiente:

- Las sentencias se pueden escribir en una o muchas líneas
- Las keywords no pueden ser escritas de manera abreviada
- Las clauses se colocan en diferentes líneas, de este modo serán mas fáciles de leer y editar.
- Los tabuladores y la identación las debemos usar para hacer el código más legible.
- Con el SQL *plus entramos la sentencia directamente en el Prompt. Este es llamado el SQL buffer. Solamente una sentencia puede estar en el buffer a la vez.
- Cada una de las líneas del prompt están numeradas


Ejecutando las sentencias SQL

- Coloque un (;) al final de la última clause
- Coloque un slash en la última línea del buffer
- Coloque un slash en el prompt del SQL

Los caracteres de las columnas que sean números y sus datos están justificados a la derecha, de resto todos los demás están justificados a la izquierda. Además, estos aparecen en mayúsculas


Funciones SQL

Las funciones en SQL las utilizamos para:

- Mejorar el calculo de los datos
- Modificar datos
- Manipular la salida de grupos de filas
- Dar formato a las fechas y números para mostrarlos
- Convertir la columna de tipo de datos
Las funciones en SQL aceptan muchos argumentos y siempre retornan un valor.

Tipos de funciones

Una sola línea

Estas funciones trabajan con filas individuales y retornan un resultado por cada una de ellas. Son utilizadas para manipular ítems de datos. Aceptan uno o más argumentos como: Constantes, Variables, Nombre de una columna y expresiones. Y pueden ser usadas en el SELECT, WHERE y el ORDER BY

Su sintaxis es la siguiente:

Function_name ? Nombre de la función
Column ? Es el nombre de una columna de una tabla de la base de datos
Expresión ? Es una cadena de caracteres o una expresión a calcular
Arg1, arg2 ? Son los argumentos que debe usar la función.

Funciones de una sola línea

Estas son funciones: Carácter. Numero, Fechas, Conversión y generales.

1. Carácter: Funciones que aceptan un carácter como entrada y nos retorna ambos; el carácter y el valor numérico. Estas funciones son divididas en
a. Case conversión:
i. LOWER, se encarga de convertir un string en minúsculas
ii. UPPER, se encarga de convertir un string en mayúsculas
iii. INITCAP, se encarga de convertir la primera letra de cada palabra en mayúsculas. Las otras letras las deja en minúsculas.

Ejemplo:
SQL > SELECT ‘El cargo que tiene’
2 || INITCAP(nombre) || ’es’
3 LOWER(cargo) AS “Detalle de los empleados”
4 FROM empleo;


b. Character manipulation
i. CONCAT, función que se encarga de unir dos cadenas de caracteres. Solo puede manipular dos parámetros
Ejemplo:
CONCAT(‘Cadena’, ‘Pegada’) ? CadenaPegada

ii. SUBSTR, función que se encarga de extraer una cadena de caracteres de un tamaño determinado
Ejemplo:
SUBSTR(‘Cadena’,1,3) ? Str

iii. LENGHT, función que nos determina cual es el tamaño de una cadena de caracteres
Ejemplo:
LENGHT(‘Cadena’) ? 6

iv. INSTR, Encuentra la primera posición donde se encuentra un carácter dado.
Ejemplo:
INSTR(‘Cadena’, ‘n’) ? 5

2. Numero: Estas funciones aceptan una entrada numérica y nos retorna un valor numérico. Estas funciones son:
i. ROUND, función que se encarga de aproximar ciertos decimales dependiendo del parámetro dos.
Ejemplo:
ROUND(45.923,2) ? 45.92 // se redondea con 2 decimales a la derecha
ROUND(45.923,0) ? 46 //se redondea sin decimales
ROUND(45.923,-1) ? 50 //1 decimal a la izquierda

ii. TRUNC, función que se encarga de tomar un numero y dejarlo con el numero de decimales que se especifican en el parámetro.
Ejemplo:
TRUNC(45.923,2) ? 45.92 // se redondea con 2 decimales a la derecha

iii. MOD, función que se encarga de encontrar el residuo de tomar el parámetro1 dividido por el parámetro2.
Ejemplo:
MOD(1600,300) ? 100

3. Fechas: Oracle guarda fechas en un formato numérico interno el cual representa el siglo, año, mes, día, hora, minutos y segundos. El formato para una fecha es DD-MM-AA
i. SYSDATE, función que nos retorna la fecha del sistema.
ii. Aritmética con fechas, Desde que las bases de datos guardan la fecha como un numero, podemos realizar calculos sobre ellos utilizando los operadores aritméticos
Fecha + numero: adiciona numero de dias a la fecha
Fecha – numero: quita numero de dias a la fecha
Fecha – Fecha: me dice el numero de dias entre dos fechas
Fecha + numero/24: adiciona un numero de horas a la fecha
iii. MONTHS_BETWEEN: Numero de meses entre dos fechas MONTHS_BETWEEN(date1, date2)
iv. ADD_MONTHS: ADD_MONTHS(date, n)
v. NEXT_DAY: Me dice el dia que se encuentra después del dia especificado de la semana. NEXT_DAY(date, 'char')
vi. LAST_DAY LAST_DAY(date)
vii. ROUND: Me retorna la fecha redondeada al formato especifico ROUND(date[,'fmt'])
viii. TRUNC: TRUNC(date[, 'fmt']): Returns date with the time portion of the day truncated to the unit specified by the format model fmt. If the format model fmt is omitted, date is truncated to the nearest day.

4. Conversión:
i. TO_CHAR, Nos permite convertir una fecha que esta escrita en la forma DD-MM-AA o un numero a un tipo de dato VARCHAR2 en una formato que el usuario defina.
1. El formato debe estar encerrado entre comillas simples
2. El formato debe incluir cualquier formato valido para fechas
TO_CHAR(number |date, [fmt],[nlsparams]
ii. TO_NUMBER, Convierte un carácter string que contiene digitos en el formato que el usuario especifique.
TO_NUMBER(char, [fmt],[nlsparams]
iii. TO_DATE, Convierte un carácter string que representa una fecha en una fecha acorde con el formato que el usuario desee.
TO_DATE(Char, [fmt],[nlsparams]


5. Generales:
i. NVL, Lo utilizamos para convertir un valor (fecha, carácter o número) NULL a un valor actual.
Su sintaxis es NVL (expr1, expr2)
expr1 ? es la expresión que puede contener NULL
expr2 ? es el Nuevo valor

El valor de retorno es del mismo tipo de dato que la expresión1.

Ejemplo:
SQL > SELECT nombre, sueldo, comision,
(sal*12)+NVL(comision,0)
2 FROM empleado

Todos los empleados que no tengan comisión se les llenará con el valor de cero.

6. DECODE, función que trabaja igual que un CASE o mejor IF-THEN-ELSE.
DECODE (col/expresión, search1, result1
Ejemplo:
SQL> SELECT cargo, sueldo,
2 DECODE (cargo, ‘VENDEDOR’, SUELDO*1.1,
3 ‘GERENTE’, SUELDO*1.15,
4 ‘PRESIDENTE’, SUELDO*1.2
5 SUELDO)
6 INCREMENTO
7 FROM empleo;

7. Funciones group:
Son aquellas que trabajan con un conjunto de filas y nos arroja un solo resultado por grupo.
i. AVG, Nos calcula el promedio
ii. COUNT, Cuenta el numero de filas que tiene la tabla
iii. MAX, Nos dice cual es el maximo valor
iv. MIN, Nos dice cual es el minimo valor
v. STDDEV, Calcula la desviación estandar
vi. SUM, suma todos los valores
vii. VARIANCE,

Clause Having: la utilizamos para especificar que grupo va a ser mostrado.

SELECT columna, group_function
FROM tabla
[WHERE condicion]
[GROUP BY expresión]
[HAVING condicion]
[ORDER BY column];

Ejemplo:
SELECT deptno, max(sal)
FROM emp
GROUP BY deptno
HAVING max(sal)>2900;


Join

Lo utilizamos cuando necesitamos datos de mas de una tabla. Las filas de una tabla se pueden ensamblar con las filas de otra tabla de acuerdo con valores comunes entre ellos. Usualmente son las que corresponden a las llaves primarias y foráneas.

SELECT tabla1.columna, tabla2.columna
FROM tabla1, tabla2
WHERE tabla1.columna1 = tabla2.columna2;

Para trabajar con la condición Join debemos:

- Insertarla en la clause del WHERE.
- Escribirla en la clause del SELECT precede al nombre de la tabla con el nombre de la columna
- Si existen varias tablas con el mismo nombre, el nombre de la columna debe estar precedida con el nombre de la tabla
- Para Join n tablas, se necesita un mínimo de (n-1) condiciones Join. Este caso no aplica si la tabla es la que contiene la llave primaria, en cuyo caso mas de una columna son requeridas.

En dado caso que una condición Join sea invalida u omitida por completo, el resultado de esta operación es un producto cartesiano en el cual se muestran todas las combinaciones de las filas de las tablas que a las cuales se les quería aplicar el Join.

Tipos de Joins

• Equijoins: Cuando los valores de ambas columnas son iguales. Frecuentemente este tipo de Joins involucran llaves primarias y foráneas. Son llamados también simple joins.

Ejemplo:
SQL > SELECT empleado.codigo, empleado.nombre,
2 empleado.deptno, departamento.deptno
3 FROM empleado, departamento
4 WHERE empleado.deptno = departamento.deptno;

Si queremos utilizar un alias para simplificar las cosas, debemos manipularlas de la siguiente manera:

SQL > SELECT e.codigo, e.nombre, e.deptno, d.deptno
2 FROM empleado e, departamento d
3 WHERE e.deptno=d.deptno;

En dado caso que queramos hacer un join entre varias tablas debemos colocar:

SQL > SELECT e.codigo, e.total, e.deptno, d.deptno, o.total
4 FROM empleado e, departamento d, item o
5 WHERE e.deptno=d.deptno
6 AND e.total = o.total;

• Non-equijoins: Cuando las columnas no corresponden directamente en ninguna de las dos tablas.

• Outer joins

Cuando una fila no satisface un join la fila no aparece en el resultado del Query.
Utilizamos el outerJoin para ver las filas que usualmente no cumplen con el Join.

El operador del outer-join es el + y lo debemos colocar en el lado del join que esta deficiente en información.

SELECT table1.column, table2.column
FROM table1,table2
WHERE table1.column(+) = table2.column;

- El simbolo + no puede poner en ambos lados de la clausula.
- La condición envuelta en el outertjoin no puede contener el operador IN o estar linkeado con otro condición por el operador OR.

• Self joins

Lo utilizamos cuando queremos unir una tabla consigo misma.


SUBQUERY
Un subquery es una sentencia SELECT la cual tiene dentro de ella otro query.

SELECT select_list
FROM table
WHERE expr operador
(SELECT select_list
FROM table);

Ejemplo:
SQL > SELECT ename
2 FROM emp
3 WHERE sal >
4 (SELECT sal
5 FROM emp
6 WHERE empno=7566);

Un subquery lo debemos encerrar entre paréntesis e identado hacia la derecha. Un subquery no puede contener la clause ORDER BY. Dos tipos de subquery son utilizados: single-row (>, =, <=, >=, <>), los multiple-row (IN, ANY, ALL) y los multiple-column (son los que retornan mas de una columna)

Ejemplo:
SQL > SELECT ename, job
2 FROM emp
3 WHERE job =
4 (SELECT job
5 FROM emp
6 WHERE empno=7369)
7 AND sal >
8 (SELECT sal
9 FROM emp
10 WHERE empno=7876);

Los subquerys se ejecutan primero. Oracle trae el resultado al query principal.

Tipos de subqueries

Single row - Son los que retornan solo una fila
Multiple row - Son los que retornan mas de una fila
Multiple column - Son los que retornan mas de una columna

Tambien se pueden poner subqueries en la clausula having


Interactive reports

Podemos hacer que el usuario sea el interactué con el sistema. El da sus valores y así, se restringen los datos a mostrar.

En SQL*plus utilizamos el carácter (&) para guardar temporalmente valores de las variables. Usted puede predefinir variables usando los comandos ACCEPT o el DEFINE .

Ejemplo:
SQL > SELECT empno, ename, sal, deptno
2 FROM emp
3 WHERE empno=&employee_num;


De este modo el sistema nos preguntara por el valor de esta variable. Una vez que la digitemos, el evaluará la sentencia.

Comando SET VERIFY ON

Utilizando este comando el sistema nos muestra el estado en el que se encuentra la variable antes y después de la sustitución.
También podremos especificar la columna que queremos consultar.

Ejemplo:
SQL > SELECT empno, &nombre_columna
2 FROM emp;

Enter value for nombre_columna :

Los podemos usar en el
* where
* ORDER BY
* nombre de una columna
* nombre de la tabla
* Select

Usando el &&

Lo utilizamos cuando queremos re usar el valor de la variable sin pedirla al usuario cada vez. El usuario solo la escribirá una vez.

Ejemplo:
SQL > SELECT empno, ename, job, &&variable
2 FROM emp
3 WHERE empno=&employee_num;

Definiendo variables antes de la ejecución

Usted puede predefinir variables del usuario antes de la ejecución del SELECT utilizando los comandos DEFINE y ACCEPT.
ACCEPT: lee una línea que el usuario ingresa y guarda la variable
DEFINE: crea y asigna el valor a la variable

ACCEPT variable [datatype] [FORMAT format]
[PROMPT text] [HIDE]

variable: nombre de la variable
datatype: tipo del dato
FORMAT: especifica el formato
PROMPT: muestre el texto antes de que el usuario digite
HIDE: esconde lo que el usuario digite

Ejemplo :
ACCEPT dept PROMPT ‘ Digite el nombre del departamento’
SELECT *
FROM Dep.
WHERE dname = UPPER (‘&dept’);

DEFINE:
Con esta función definimos variables y luego las usamos como cualquier otra.

Ejemplo:
SQL> DEFINE deptname=sales
SQL> DEFINE deptname

SQL > SELECT *
2 FROM dept
3 dname = UPPER’(&deptname’);

Las variables se mantienen mientras que no se
use el comando
- UNDEFINE
- Se salga de SQL*plus


DML – Data Manipulation Languaje

Las Utilizamos cuando queremos adicionar, actualizar o borrar datos de la base de datos. La unión de sentencias DML se le denomina una transacción.

INSERT

Función que se encarga de insertar nuevas filas a las tablas que se encuentren en la base de datos.

INSERT INTO table [(column [, column...])]
VALUES (value [, value…]);

Su sintaxis trabaja de la siguiente manera:
table, nombre de la tabla
column, es el nombre de la columna
value, es el correspondiente valor de la columna

Ejemplo:
SQL > INSERT INTO dept (deptno,dname,loc)
2 VALUES (50, ‘DEVELOPMENT’, ‘DETROIT’);

En dado caso de que no demos las lista de los campos, se insertará en el orden en el que aparece en la tabla.

Insertando un valor NULL

Si queremos insertar un valor nulo a la tabla, podemos encerrarlo de manera explicita colocándolo entre (‘ ‘) o colocando NULL, o de manera implícita omitiéndolo.

Insertando pidiendo los valores en ejecución

Ejemplo:
SQL > INSERT INTO dept (deptno,dname,loc)
2 VALUES (&id_dep, ‘&dept_name‘, ‘&location’);

UPDATE

Función que se encarga de realizar cambios a las filas de las tablas que se encuentren en la base de datos.

UPDATE table
SET column = value [, column = value, …]
[WHERE condition];

Su sintaxis trabaja de la siguiente manera:
table, nombre de la tabla
column, es el nombre de la columna
value, es el correspondiente valor de la columna
condition, identifica las filas que van a ser actualizadas

Debemos tratar de identificar la fila a actualizar por medio de su llave primaria. Si utilizamos otra columna, se nos pueden presentar errores.

Ejemplo:
SQL > update dept
2 set dname='ESTUDIANTE'
3 WHERE DEPTNO=88;

DELETE

Función que se encarga de borrar filas de las tablas que se encuentren en la base de datos.

DELETE [FROM] table
[WHERE condition];

Su sintaxis trabaja de la siguiente manera:
table, nombre de la tabla
condition, identifica las filas que van a ser borradas

Ejemplo:
SQL > DELETE FROM dept
2 WHERE DEPTNO=88;


Transacciones de bases de datos

El servidor de Oracle asegura la consistencia de los datos mediante transacciones. Estas nos dan más flexibilidad y control cuando realizamos cambios a los datos y nos da consistencia a los datos cuando el sistema falle.
Debido a que en las operaciones normales se puede dañar la información, todas las bases de datos tiene un sistema de control de transacción.

Transacción

Una transacción es ese espacio de tiempo que hay desde que se hace la primera sentencia DML (INSERT, UPDATE, DELETE) hasta que damos por finalizada la transacción implícitamente o explícitamente (se termina la sesión).

Tipos de transacciones

DML –
DDL –
DCL –

Cuando comienza y termina una transacción

Cuando se encuentra la primera declaración SQL y termina cuando ocurre lo siguiente:

· Una declaración COMMIT o ROLLBACK
· Una declaración DDL (como CREATE)
· Una declaración DCL
· El usuario sale de SQL*plus
· La maquina falla o el sistema se cae

Una vez que una transacción termina, la siguiente declaración SQL comienza la siguiente transacción.

Controlando las transacciones

Usted puede controlar la lógica de las transacciones usando el COMMIT, SAVEPOINT y el ROLLBACK.

COMMIT: Termina la transacción actual
Durante la transacción, todas las modificaciones que hagamos sobre la base de datos, no son definitivas. Estas se realizan sobre una segmento denominado RollBack Segment. Este tiene reservado un espacio para cada sesión activa en el servidor. Una vez que la transacción termina las modificaciones temporales almacenadas en el RBS se actualiza el tablespace donde se encuentra nuestra tabla.

Las sentencias de finalización son:
· COMMIT: la transacción termina correctamente, se escriben los datos en el tablespace original y se vacía el RBS
· ROLLBACK: se rechaza la transacción y se vacía el RBS

Además debemos hacer uso de la sentencia SAVEPOINT para establecer puntos de transacción. Ahora, cuando ocurra un COMMIT o un ROLLBACK lo podremos hacer hasta cierto punto:

SAVEPOINT nombrePunto;
COMMIT nombrePunto;
ROLLBACK nombrePunto;

Ejemplo:

SELECT;
SELECT;

/// COMIENZO DE LA TRANSACCION///

UPDATE;
SELECT;
INSERT;
COMMIT;

/// FIN DE LA TRANSACCION
/// COMIENZO DE LA TRANSACCION///

UPDATE;
SELECT;
SAVEPOINT uno;
INSERT;
SELECT;
DELETE;
ROLLBACK TO uno;
UPDATE;
INSERT;
COMMIT

/// FIN DE LA TRANSACCION

Si nos demoramos mucho en hacer el COMMIT, el RBS se llena por lo que perderemos los datos. Por eso debemos hacer un COMMIT cada vez que la base sea consistente.
En dado caso de que termine la sesión con una transacción pendiente, Oracle consultará el AUTOCOMMIT y si este en TRUE se hará el COMMIT de lo contrario se hará ROLLBACK

Read Consistency

Los usuarios de la base de datos hacen dos tipos de acceso a la base de datos.

· Operaciones de lectura
· Operaciones de escritura

Read consistency es una implementación automática. Este mantiene una copia parcial de la base de datos en un segmento rollback. Cuando se ejecuta una operación como INSERT, UPDATE o DELETE sobre la base de datos, El servidor de Oracle saca una copia de los datos antes de cambiarlos y los escribe en un segmento rollback.
Todos los usuarios, menos el que esta realizando el cambio, verán los datos como se encuentran en el segmento rollback.

Si la transacción falla (rolled back) los cambios se quitan y se vuelve a la versión anterior escrita en el segmento rollback para volverla a colocar en la tabla.

Locking

Es un mecanismo que previene una interacción destructiva entre dos transacciones que tratan de acceder al mismo tiempo una parte de código.
Esta operación Oracle la realiza de manera automática e implícita. Además Oracle utiliza dos modalidades para asegurar una base de datos multiusuario.

· Exclusive, La primera transacción es la única que puede alterarla, no se pueden compartir los datos
· Share lock, Permite compartir los datos, muchos usuarios acceden a los datos. Se mantiene share locks para prevenir accesos de escritura al tiempo.


Lenguaje de definición de datos. DDL

Es el conjunto de sentencias que esta orientadas a la creación, modificación y configuración de los objetos de la base de datos.

Las tablas pueden ser creadas en cualquier momento aunque estén siendo usadas en la base de datos. No necesitamos especificar el tamaño de ninguna tabla. La estructura de la tabla puede ser modificada en línea.

Las tablas y sus columnas deben comenzar con una letra y debe tener un tamaño de 1-30 caracteres. Los nombres deben contener únicamente caracteres A-Z, a-z, 0-9, _, $, y #. Estos nos pueden ser iguales a las palabras reservadas de Oracle y no pueden haber objetos con el mismo nombre.

Creando una tabla

Para crear una tabla en Oracle debemos invocar la sentencia de CREATE TABLE. Estas sentencia es parte de las sentencias DDL.

CREATE [GLOBAL TEMPORARY] TABLE [schema.]table
(column datatype [DEFAULT expr][, ...]);

table, es el nombre de la tabla
DEFAULT expr, especifica un valor por defecto en dado caso que el valor sea omitido en la sentencia del INSERT
column , es el nombre de la columna
datatype, es el tipo de dato de la columna

Ejemplo:
SQL > CREATE TABLE DEPT
2 (deptno NUMBER(2),
3 dname VARCHAR2(14),
4 loc VARCHAR2(13));


// falta definir llave primaria y foránea

Creando una tabla usando el query

CREATE TABLA table
[{column, column…)]
AS subquery;

Ejemplo:
SQL > CREATE TABLE dept30
2 AS
3 SELECT empno, sal*12 ANNSAL, hiredate
4 FROM emp
5 WHERE deptno=30;

Adicionando columnas a las tablas

Una vez se creen las tablas, talvez se necesite hacerle cambios en la estructura. Esto lo podemos hacer usando la sentencia ALTER TABLE con la cláusula ADD.

ALTER TABLE table
ADD (column datatype [DEFAULT exp.]
[, column datatype] ...);

table, es el nombre de la tabla
column, es el nombre de la nueva columna
datatype, es el tipo de dato y la longitud de la nueva columna
DEFAULT expr, especifica el valor por defecto de la nueva columna.

Ejemplo:
SQL > ALTER TABLE dept30
2 ADD (job VARCHAR2(9));

Esta nueva columna que adicionamos quedara de última. No podemos definir la posición en la que va a quedar.

Modificando una columna de una tabla

Usted podrá modificar la definición de una columna usando la sentencia ALTER TABLE con la clause MODIFY.

Ejemplo:
SQL > ALTER TABLE dept30
2 MODIFY (ename VARCHAR2(15));

Dropping a column

Usted puede drop a columna usando la sentencia ALTER TABLE con la clause DROP COLUMN. Para esto, la columna no podrá contener datos. Solo una columna podrá ser dropped al tiempo y por lo menos debe tener una columna después de dropped. Una vez que la droppe la columna, nunca mas podrá ser recuperada.

Podremos utilizar la opción SET UNUSED para marcar las columnas que no están siendo usadas. Una vez que las tenemos marcadas, hacemos uso de la opción DROP UNUSED COLUMNS la cual las removera.

SQL > ALTER TABLE dept30
2 SET UNUSED (ename);

SQL > ALTER TABLE dept30
2 DROP UNUSED COLUMNS;

Dropping a table

Se utiliza para remover una tabla y de este modo quita todas las relaciones que existían con otras. Una vez la apliquemos no habrá reversa.
- Se borran todos los datos de la tabla
- Solamente el creador podrá removerla

SQL > DROP TABLE dept30;

Cambiando el nombre de un objeto

Utilizando la sentencia RENAME podremos cambiar el nombre de una tabla, vista, secuencia o un sinónimo.

SQL > RENAME dep TO departament;
Para hacer esto debemos ser los creadores de este objeto.

Truncando una tabla

Se utiliza para quitar todas las filas de una tabla. Para hacer esta operación debemos ser los creadores.

SQL > TRUNCATE TABLE departament;


Constraints

Los utiliza el servidor Oracle para prevenir entrada no valida de datos. Entre ellas tenemos
NOT NULL
UNIQUE
PRIMARY KEY
FOREIGN KEY
CHECK

CREATE TABLE [schema.] table
(column datatype [DEFAULT expr]
[column_constraint],
...
[table_constraint][,...]);

schema : es el nombre del dueño
table : es el nombre de la tabla
DEFAULT expr: especifica un valor por defecto
column: es el nombre de la columna
datatype: es el tipo de dato de la columna

Definiendo contraints
columna
-------
column [CONSTRAINT constraint_name] constraint_type;

tabla
-----
[CONSTRAINT constraint_name] constraint_type
(column,...),

Constraint NOT NULL
Nos controla el acceso de valores nulos. Solo se puede especificar
a nivel de columna, no a nivel de la tabla.

CONSTRAINT tabla_columna_nn NOT NULL...


Constraint UNIQUE KEY
Requiere que cada valor en la columna sea unica. Dos filas no
pueden tener un valor duplicado.

CONSTRAINT tabla_columna_uk UNIQUE(columna)


Constraint PRIMARY
Se encarga de crear una llave primaria para la tabla. Solo se
puede crear una llave primaria procada tabla.

CONSTRAINT tabla_columna_pk PRIMARY KEY (columna)


Constraint FOREIGN KEY
Designa una columna como llave foranea y establece la relacion
entre la llave primaria o la llave unica en la misma tabla o
en tablas diferentes.

CONSTRAINT tabla_columnaprimaria_fk FOREIGN KEY (columnaprimaria)
REFERENCES tabla2 (columnaprimaria)

Adicionar un constraint

ALTER TABLE table
ADD [CONSTRAINT constraint] type (column);

table : es el nombre de la tabla
constraint : es el nombre del constraint
type: es el tipo de constraint
column: es el nombre de la columna afectada por el constraint

Borrando un constraint
Para remover un constraint de una tabla, utilice la funcion
drop constraint

ALTER TABLE tabla
DROP CONSTRAINT tabla_columna_tipo;

Desahabilitando un constraint
Se puede deshabilitar un constraint sin necesidad de borrarlo o
re definirlo. Para esto utilice la funcion disable

ALTER TABLE tabla
DISABLE CONSTRAINT tabla_columna_tipo CASCADE;

Habilitando un constraint
Se puede habilitar un constraint sin necesidad de borrarlo o
re definirlo. Para esto utilice la funcion enable

ALTER TABLE tabla
ENABLE CONSTRAINT tabla_columna_tipo;


View

Una vista se le puede asimilar con una tabla pero realmente no es mas que el resultado de una consulta SELECT, es como una tabla virtual.
Cuando una consulta se repite muchas veces, entonces mas bien podríamos guardarla en una vista y después hacer consultas sobre esta.

CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view
[(ALIAS [, alias]…)]
AS subquery
[WIDTH CHECK OPTION [CONSTRAINT constraint)]
[WIDTH READ ONLY]

Ejemplo:

SQL > CREATE VIEW empvu10
1 AS SELECT empno, ename,job
2 FROM emp
3 WHERE deptno=10;

Modificando una vista
Para modificar una vista debemos hacer uso de la opción OR REPLACE.

Ejemplo:

SQL > CREATE OR REPLACE VIEW empvu10
2 (employee_number, employee_name, job_title)
3 AS SELECT empno,ename,job
4 FROM emp
5 WHERE deptno=10;

Borrando una vista
Para borrar una vista hacemos uso de la opción DROP VIEW.

DROP VIEW vista;


Objetos de la base de datos

Index
La función CREATE INDEX se encarga de crear un índice sobre la tabla de la base de datos. Con este vamos a poder tener un acceso mas rápido y eficiente a las filas de la tabla. De este modo vamos a reducir las entradas y salidas a disco.

CREATE INDEX index
ON table (column [, column] ...);

Donde su sintaxis es:

Index: es el nombre del índice
Table: es el nombre de la tabla
Column: es el nombre de la columna en la tabla a indexar.

Ejemplo:

SQL > CREATE INDEX empleado_idx
2 ON emp(ename);

Oracle crea automáticamente un indice cuando se define la clave primaria. Ya que esta parte de la tabla es la que habitualmente mas se consulta.

Secuencia 
Una secuencia es un objeto de la base de datos que genera números secuenciales. Se utiliza para asignar valores a campos auto numéricos. Cada vez que se genera esta secuencia, se genera un número. Con esta podremos:

- Crear códigos
- Utilizarla en formularios en el momento de la inserción
- Son códigos no inteligentes, no me dicen ninguna información.

La secuencia no ve cual es el último número sino que el sigue adelante. Si se borra el 7 la secuencia no lo vuelve a colocar, este continúa con el 8.

SQL > CREATE SEQUENCE sequence
[INCREMENT BY n]
[START WIDTH n]
[{MAXVALUE n | NOMAXVALUE}]
[{MINVALUE n | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE n| NOCACHE}]

Una vez que se crea la secuencia, esta la podemos usar para generar secuencia de numeros los cuales los vamos a poder utilizar en las tablas.
Sobre esta secuencia vamos a poder utilizar la sentencia NEXTVAL para extraer valores sucesivos de esta secuencia. O podemos utilizar la sentencia CURRVAL para hacer referencia a un numero de esa secuencia.

INSERT INTO tabla (campo1, campo2...)
VALUES (secuencia.NEXTVAL,val2....);

SELECT secuencia.CURRVAL
FROM tabla;


Synonym
Un sinónimo es una redefinición del nombre de un objeto que se encuentra en la base de datos. De este modo no tendremos que colocar un prefijo antes de la tabla para referirnos al usuario que creo otra tabla.

CREATE [PUBLIC] SYNONYM synonym
FOR object;

Su sintaxis es:

PUBLIC, crea un sinónimo el cual es accesible por todos los usuarios
Synonym, es el nombre del sinónimo
Object, identifica el objeto por el cual se va a crear el sinónimo

Ejemplo:

SQL > CREAT SYNONYM d_sum
2 FOR dept_dum_vu;

Borrando un sinónimo

Para borrar un sinónimo hacemos uso de la opción DROP SYNONYM.
Secuence

DROP SYNONYM d_sum;



PL/SQL

Este lenguaje de la Corporación Oracle, es una extensión de SQL y sus siglas significan Procedural Lenguaje/SQL. Fue diseñado durante los años 70’s y 80’s.
Este nuevo lenguaje nos ofrece cosas como:

v Encapsulamiento
v Manejo de excepciones
v Información handing
v Orientado a objetos

Como sabemos, SQL es un lenguaje de comandos no es un lenguaje de programación típico. Entre otras, no tiene instrucciones de control de flujo. Por esto se invento (por parte de Oracle) un nuevo lenguaje de la 3era Generación el cual manejara la estructura típica de un lenguaje de programación aplicándole las sentencias SQL.


Estructura básica en PL/SQL

Cuando escribimos un programas, este queda limitado por lo que se denomina “bloques de código”. Este a su vez puede contener mas “bloques de código”. Un bloque de código es aquel que queda limitado por las palabras BEGIN y END.

Un bloque consiste de tres partes:
DECLARE (esta es opcional): esta contiene todas las variables, constantes, cursores.. etc.
EXECUTABLE (esta se requiere): contiene sentencias para manipular la base de datos y sentencias PL/SQL para manipular los datos del bloque.
EXCEPTION (esta es opcional): esta especifica las acciones que se deben tomar cuando ocurre un error.

DECLARE
Declaración de las variables;
BEGIN
Sentencias SQL y PL/SQL
EXCEPTION
Manejo de excepciones
END;

Tipos de bloques

Anonymous
[DECLARE]
BEGIN
---statements
[EXCEPTION]
END;

Procedure

PROCEDURE name
IS
BEGIN
---statements
[EXCEPTION]
END;

Function

FUNCTION name
RETURN datatype
IS
BEGIN
---statements
RETURN value;
[EXCEPTION]
END;


Variables

Usted puede declarar variables para usarlas en las sentencias SQL. Con ellas vamos a poder mantener valores para procesarlas mas tarde. Además las vamos a poder utilizar para realizar cálculos sin necesidad de acceder a la base de datos. Una vez las tenemos declaradas, podremos usarlas repetidamente.

Estas las declaramos en la parte de declaración en el bloque de PL/SQL, subprograma o paquete.

Pasando variables por parámetro

Existen 3 tipos de parámetros: IN, OUT, IN OUT.
IN, lo utilizamos cuando queremos pasarle un valor al subprograma que se esta llamando
OUT, lo utilizamos cuando queremos retornar valores de un subprograma
IN OUT, lo utilizamos cuando queremos que una variable que le pasamos al subprograma se actualice una vez que entra a este.

Tipos de variables

Todas las variables en PL/SQL tienen que tener un tipo de dato el cual especifica el formato de almacenamiento. Los tipos de variables que maneja son:

· scalar. Son VARCHAR2, NUMBER, DATE, CHAR, LONG, BOOLEAN
· composite, mantiene un grupo de campos para ser manipulados en bloque
· reference, llamados punteros
· LOB, llamados locators, los cuales especifican la localización de
objetos largos.

Declarando PL/SQL variables

Antes de hacer referencia a las variables debemos declararlas. Esto se hace de la siguiente manera:
Sintaxis

Declare
Identifier [CONSTANT] datatype [NOTNULL]
[:= | DEFAULT expr];

identifier - nombre de la variable
CONSTANT - la variable no puede cambiar de valor
datatype - tipo de dato
NOT NULL - no puede ser null

Ejemplo:

DECLARE
Var1 DATE;
Var2 NUMBER(2) NOT NULL := 10;
Var3 VARCHAR2(13) := ‘Atlanta’;
Var4 CONSTANT NUMBER:= 1400;

Esto lo debemos hacer en la sección de declaración, antes del BEGIN.
Podemos asignarle un valor inicial.

Asignando valor a las variables
identifier := expr;
// por default todos se inicializan con NULL,
// a no ser de que le demos un valor

DEFAULT lo utilizamos para variables con un tipico valor
var tipo[tam] DEFAULT val;

NOT NULL lo debemos utilizar cuando la variable debe tener un valor,
y esta no puede tener un valor NULL. Por eso debemos asignarle un
valor inicial.

var tipo[tam] NOT NULL := val;

Scalar datatype
Es aquella que mantiene un valor sencillo y estan clasificados en:
- VARCHAR2
- NUMBER
- DATE
- CHAR
- LONG
- BOOLEAN

%TYPE
Con esta declaración vamos a garantizar que el tipo de dato concuerda
con el tipo de dato previamente declarado. Es mas utilizado cuando
derivamos de otras tablas.

var tabla.campo%TYPE;

Datos compuestos
Son conocidos como colecciones y son TABLES, RECORD, NESTED TABLE y VARRAY

LOB datatypes
Objetos largos de mas de 4 GB de tamaño y son: text, graphic images,
video clips o sound wave.


Bind variables
Es una variable que se declara en un ambiente (host) para ser
utilizadas por diferentes programas PL/SQL.

VARIABLE var tipo(tam)

Para referenciar a una variable bind, debemos colocar el prefijo (:) de este modo vamos a poder mostrar su valor colocando el comando PRINT.

Ejemplo:
SQL> VARIABLE RES NUMBER
SQL> DECLARE
2 VAR1 NUMBER(2) := 5;
3 VAR2 NUMBER(2) := 5;
4 BEGIN
5 :RES := VAR1+VAR2;
6 END;
7 /

PL/SQL procedure successfully completed.

SQL> PRINT RES
RES
----------
10


Otra manera de mostrar información
Para poder hacer seguimiento a las variables o simplemente mostrar
su contenido, dentro de un bloque PL/SQL podemos colocar la siguiente
sentencia:

SET SERVEROUTPUT ON
VARIABLE mensaje VARCHAR2(20)
BEGIN
:mensaje :='MY PL/SQL';
DBMS_OUTPUT.PUT_LINE('mensaje' || :mensaje);
END;
/


Funciones SQL en PL/SQL
La mayoria de las funciones en Sl son validas en expresiones PL/SQL.
* Single row number
* Single row character
* datatype
* date
* GREATEST , LEAST

No son validas
* DECODE
* GROUP

Son solo validas en la sentencia SQL dentro del bloque PL/SQL

Operadores
- Lógicos - aritméticos - concatenación - exponencial (**)


Guía para programar en PL/SQL

· Como PL/SQL es una extensión de SQL, las reglas generales de sintaxis que se aplican a SQL también se aplican a PL/SQL.
· Las unidades léxicas pueden estar separadas por uno o mas espacios
· Las sentencias pueden estar en líneas separadas, lo que no pueden estarlo son las keywords.
· Los identificadores pueden contener mas de 30 caracteres
· Los identificadores deben empezar con un carácter alfabético.
· No utilice el mismo nombre que tienen las columnas para definir los identificadores
· Las palabras reservadas no pueden ser utilizadas como identificadores.
· Las palabras claves deben estar escritas en mayúsculas, para así facilitar la lectura.
· Un literal es un número, carácter, string o booleano
· Los comentarios pueden ser de mas de una línea /* */, o de una sola línea –-
· Muchas de las funciones son las mismas que estan definidas en SQL
· Los operadores son los mismo exceptuando el de exponencial (**)
· Utilice los comentarios para darle mas claridad al programa
· Idente el código para dar mayor claridad al programa
· La asignación se hace en PL/SQL con :=
· La asignación de una columna en SQL se hace con =


Interactuando con el servidor Oracle

Sentencia SELECT en PL/SQL
Vamos a utilizar la sentencia SELECT para consultar datos de la base de datos.

SELECT select_list
INTO { variable_name [, variable_name] … | record_name}
FROM table
WHERE condition;

Debemos tener variables para mantener los valores que nos retorne el SELECT. Este se debe colocar en la clause INTO entre las clauses SELECT y FROM.

Ejemplo:
DECLARE
v_deptno NUMBER(2);
v_loc VARCHAR(15);
BEGIN
SELECT deptno,loc
INTO v_deptno, v_loc
FROM dept
WHERE dnam=’SALES’;
END;


Sentencia Insert con PL/SQL

BEGIN
INSERT INTO emp(empno,ename,job,deptno)
VALUES (empno_sequence.NEXTVAL, ‘HARDING’,’CLERK’,10);
END;

Sentencia UPDATE con PL/SQL

Ejemplo:
DECLARE
V_sal_increase emp.sal%TYPE := 2000;
BEGIN
UPDATE emp
SET sal = sal + v_sal_increase
WHERE job = ‘ANALYST’;
END;

Sentencia DELETE con PL/SQL

Ejemplo:
DECLARE
V_deptno emp.deptno%TYPE := 10;
BEGIN
DELETE FROM emp
WHERE deptno = v_deptno;
END;


SQL Cursor

Donde sea que se trabaja con una sentencia SQL, el servidor de Oracle abre un espacio en memoria en donde se prueba y se ejecuta. Esta área se llama cursor.
Cuando la parte ejecutable de un bloque issues una sentencia SQL, PL/SQL crea un cursor implícito, el cual es el identificador SQL. PL/SQL maneja este cursor de manera automática. El programador de manera explícita declara y nombra un cursor. Por lo tanto, hay dos tipos de cursores los implícitos y los explícitos.

Atributos de un cursor

Usando estos atributos podemos evaluar que paso cuando el cursor la última vez que fue usado. Este solo lo podemos usar en la sentencias PL/SQL como funciones.

SQL%ROWCOUNT: Numero de filas afectadas por la última sentencia SQL
SQL%FOUND: Booleano que nos da Verdadero si la última sentencia afecta una o más filas.
SQL%NOTFOUND: Booleano que nos da Verdadero si la última sentencia no afectó ninguna fila.
SQL%ISOPEN: Siempre evalua falso ya que PL/SQL cierra los cursores implícitamente después de que son ejecutados.


Ejemplo:
VARIABLE rows_deleted VARCHAR2(30)
DECLARE
v_ordid NUMBER := 605;
BEGIN
DELETE FROM item
WHERE ordid = v_ordid;
:rows_deleted := (SQL%ROWCOUNT || ‘rows deleted.’);
END;


Escribiendo estructuras de control condicionales
Sentencias IF

Esta sentencia es similar a las estructuras IF que manejan en otros lenguajes.

IF CONDITION then
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;


Escribiendo estructuras de control iterativas

PL/SQL nos permite ejecutar sentencias de manera iterativa. Estas son:

· Basic loop, la cual se repite sin ninguna condición
· FOR, la cual se repite basado en un conteo
· WHILE, la cual se repite basado en una condición
· EXIT, sentencia para terminar el ciclo

BASIC LOOP

Sintaxis:
LOOP
Sentencia1;
. . .
EXIT [WHEN condition];
END LOOP;

Ejemplo:
DECLARE
v_ordid item.ordid%TYPE := 601;
v_counter NUMBER(2) := 1;
BEGIN
LOOP
INSERT INTO item(ordid,itemid)
VALUES (v_ordid, v_counter);
V_counter := v_counter +1;
EXIT WHEN v_counter > 10;
END LOOP
END;

FOR LOOP

Sintaxis:
FOR counter in [REVERSE]
lower_bound.. upper_bound LOOP
statement1;
statement2;
...
END LOOP;

Ejemplo:
DECLARE
v_lower NUMBER:=1;
v_upper NUMBER:=100;
BEGIN
FOR i IN v_lower..v_upper LOOP
...
END LOOP;
END;

WHILE LOOP

Sintaxis:
WHILE condition LOOP
sentencia1;
sentencia2;
...
END LOOP;


Tipos de datos compuestos

Existen dos nuevos tipos de datos: RECORD (estructuras) y TABLE (vectores).
Primero que todo debemos declarar este nuevo tipo antes de declarar variables de este tipo. Para hacerlo utilizamos la keyword TYPE.

Record

· Es una agrupación de variables, cada una con su tipo de dato(diferente o igual).
· Puede tener tantas variables como sea necesario
· A estas variables se les pueden asignar valores iniciales inclusive el valor NOT NULL
· Los valores que no tengan un valor inicial se les asigna NULL
· Para definir estos nuevos tipos de datos, los debemos hacer en la parte DECLARE del bloque, subprograma o paquete.
· Podemos tener RECORDs que sean parte de otros.

Su sintaxis es:

TYPE type_name IS RECORD
(field_declaration [, field_declaration]…);
identifier type_name;

donde field_declaration es:
field_name {field_type | variable%TYPE
|table.column%TYPE
|table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]

Ejemplo:
DECLARE
TYPE emp_record_type IS RECORD
(empno NUMBER(4) NOT NULL:=100,
job VARCHAR2(9),
ename emo.ename%TYPE);
emp_record emp_record_type;

Declarando RECORDs con el atributo %ROWTYPE

Para declarar un record basado en una colección de columnas de la tabla de la base de datos o vista, debemos utilizar el atributo %ROWTYPE. Loc campos del record tomaran los nombre y tipos de datos de las columnas de la tabla o vista.

Ejemplo:

DECLARE
emp_record emp%ROWTYPE

Accediendo a los campos del RECORD
Para hacer referencia a uno de los campos debemos:

Record_name.field_name


Table

Una tabla no es mas que una colección de elementos identificados por un índice. Son similares a los arreglos o vectores. Y deben contener dos componentes:

- Una llave primaria del tipo BINARY_INTEGER la cual nos permite indexar la tabla PL/SQL.
- Y una columna de un tipo de datos escalar o record los cuales almacenan los elementos de la tabla
- Puede incrementar su tamaño dinámicamente

Tenga en cuenta que las tablas PL/SQL no son las mismas tablas a las que se hace referencia en las bases de datos.

Su sintaxis es:

TYPE type_name IS TABLE OF
{column_type|variable%TYPE | table.column%TYPE} [NOT NULL]
[INDEX BY BINARY_INTEGER];

identifier type_name;

Creando la tabla

Como no existen tipos de datos tabla predefinidos en PL/SQL, primero debemos crear el tipo de dato y luego declarar un identificador que uso ese tipo de dato.

DECLARE
TYPE data_table_type IS TABLE OF DATE
INDEX BY BINARY_INTEGER;
date_table date_table_type;

BEGIN
END;

Haciendo referencia a los campos de la tabla
Para referirnos a los campos de la tabla debemos colocar:

PLSQL table_name (primary_key_value)

Métodos
Estos métodos operan sobre las tablas (TABLES PL/SQL):

EXISTS (n) --> Si el elemento n existe
COUNT --> Retorna el numero de elementos que contiene la tabla
FIRST --> Retorna el menor y mayor index
LAST
DELETE ---> Borra todos los elementos de la tabla
DELETE (n) --> Borra el elemento n de la tabla
DELETE (n,m) --> Borra los elementos en el rango m...n

Table of records
Nos incrementan la funcionalidad de los TABLES PL/SQL. Para referirnos a ellos
utilizamos:

table (index).campo

DECLARE
type dept_table_type IS TABLE OF dept%ROWTYPE
INDEX BY BINARY_INTEGER;

dept_table dept_table_type;


CURSORS
Los usamos para nombrar areas privadas SQL y así poder acceder a información almacenada.

* Implicitos: Son declarados por PL/SQL para todas las DML y PL/SQL SELECT,
incluidos los que retornan una sola linea
* Explicitos: Para queries que retornan mas de una linea, estos cursores son
manejados y manipulados por el programador. Los utilizamos para procesar de manera individual cada fila retornada por un SELECT de muchas filas. Estas son llamadas
active set (conjunto de filas retornadas) y este las se encarga de procesar
fila x fila.


Un programa PL/SQL

--> abre el cursor --> procesa las filas retornadas ---> cierra el cursor --> marca la posicion actual

Funciones
- Procesar fila por fila lo que retorna el query
- Mantiene la pista de cual es la fila que esta siendo procesada
- Permite al programador controlarlos en el bloque PL/SQL

Controlando cursores explicitos

Declare --> Open --> Fetch --> Empty --> yes --> close
                                  no <--

1. Declare el cursor
2. Abra el cursor, este ejecuta el query y toma la que esta siendo referenciada. Las
filas que estan identificadas por el query se llaman active set
3. Fetch datos del cursor, cargar la fila actual en las variables.

Despuees de hacer el fetch se evalua la existencia de mas filas. Si existen se devuelve
al fetch. Si no existen mas filas o procesos se debe cerrar el cursor.

4. Cerrar el cursor, liberar el active ser.

Debemos utilizar el OPEN, FETCH y CLOSE para controlar el CURSOR.

Declarando el cursor
DECLARE
CURSOR nombre_cursor IS
select_statement;
BEGIN
-
-
-
END;

Abriendo el cursor
Al ejecutar el Query identificamos el active set y al abrir el cursor, este nos apunta a la primera fila del active set.

OPEN nombre_cursor;

Fetching data
FETCH nombre_cursor INTO [var1,var2...] | RECORD name];

las variables son para guardar el resultado. Tomamos fila por fila y avanza a la
siguiente fila del activ set. Lee los datos de la fila actual en las variables PL/SQL.

- Incluya el mismo numero de variables en el INTO como columnas tenga la sentencia SELECT (asegura la compatibilidad de los datos)
- Evalue que el cursor tenga filas.

Cerrando
CLOSE nombre_cursor

Deshabilita el cursor. Despues de cerrarlo, no trate de hacer un fetch. Esto le ocasionara el error de INVALID_CURSOR.

Podemos definir un maximo de cursores por usuario, el cual lo definimos en el parametro del OPEN_CURSORS = 50

Atributos
%ISOPEN, verdadero si el cursor esta abierto
%NOTFOUND, Verdadero si el mas reciente FETCH no retorna una fila
%FOUND, Verdadero si el mas reciente FETCH retorna una fila
%ROWCOUNT, Evalua el total de numeros retornados.

Ejemplo:

DECLARE
v_empno emp.empno%TYPE; -->variables donde vamos
v_name emp.ename%TYPE; -->a hacer el fetch
CURSOR emp_cursor IS -->Declaracion del cursor
SELECT empno, ename -->
FROM emp; -->
BEGIN
OPEN emp_cursor --> abrimos el cursor
LOOP
FETCH emp_cursor INTO v_empno, v_name; --> procesamos la fila
EXIT WHEN emp_cursor%ROWCOUNT > 10 OR emp_cursor%NOTFOUND; -->controlamos la salida
.
.
END LOOP;
CLOSE emp_cursor; --> cerramos el cursor
END;

Podemos definir un RECORD basado en un cursor

DECLARE
CURSOR emp_cursor IS
SELECT empno, ename
FROM emp;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
.
.
END LOOP;
CLOSE emp_cursor; --> cerramos el cursor
END;


CURSOR FOR Loop

Procesa dilas en un cursor explicito
- Se abre el cursor
- Por cada iteración se hace un fetch
- Se cierra el cursor (automáticamente) cuando todas las filas han sido procesadas

FOR record_name IN cursor_name LOOP
sentencia1
sentencia2
.
.
.
END LOOP;

Guia
* No declare el record que controla el LOOP, solo es para el LOOP
* Evalue el cursor durante el LOOP


DECLARE
CURSOR emp_cursor IS
SELECT empno, ename
FROM emp;
BEGIN
FOR emp_record IN emp_cursor LOOP
IF emp_record.deptno = 30 THEN
.
.
END IF;
END LOOP;
END;

FOR LOOPS usando Subqueries
Gracias a esto, no tenemos la necesidad de declarar un cursor

BEGIN
FOR emp_record IN (SELECT ename, deptno FROM emp)
LOOP
IF emp_record.deptno = 30 THEN
.
.
.
END LOOP;
END;

Cursores con parámetros
Los parámetros nos permiten pasar valores al cursor, y asi usarlos en el query.
Esto permite abrir y cerrar un cursor explicito muchas veces en un bloque,
retornando un conjunto diferente en cada ocasión.

CURSOR cursor_name [(parameters_name datatype ...)]
IS
select_statement

Guia
* En el parametro no defina el tamaño de la variable

DECLARE
CURSOR emp_cursor (p_deptno NUMBER, p_job VARCHAR2) IS
SELECT empno, ename
FROM emp
WHERE deptno=p_deptno
AND job = p_job;
BEGIN
OPEN emp_cursor (10, 'CLERK');
.
.
END;

Cursores con parámetros utilizando FOR LOOP

DECLARE
CURSOR emp_cursor (p_deptno NUMBER, p_job VARCHAR2) IS
SELECT empno, ename
FROM emp
WHERE deptno=p_deptno
AND job = p_job;
BEGIN
FOR emp_record IN emp_cursor (10, 'CLERK') LOOP
.
.
END LOOP;
END;


Exceptions
Es un identificador en PL/SQL, lanzado en la ejecución de un bloque el
cual termina el programa.
Gracias a estos, vamos a poder reaccionar ante cualquier posible error
que se presente.

Lanzando excepciones
* Oracle dispara automáticamente cuando ocurre un error
* Nosotros podemos hacerlos explicitos dentro del bloque
DECLARE
BEGIN
EXCEPTIONS
// Cuando se lanza la excepcion se debe ir a la parte de codigo que lo
// maneja. Si PL/SQL captura de manera exitosa la excepción, no se va a la
// parte que cierra el bloque. El bloque termina con exito
END;

Atrapando excepciones
EXCEPTIONS
WHEN exception1 [OR exception2...] THEN
sentencia1;
sentencia2;
.
.
.
[WHEN exception1 [OR exception2...] THEN
sentencia1;
sentencia2;
.
.
.]
[WHEN OTHERS THEN
sentencia1;
sentencia2;
.
.
.]

Algunas excepciones predefinidas
NO_DATA_FOUND
TOO_MANY_ROWS
INVALID_CURSOR

Atrapando una excepcion no-predefinida
1. Declare el nombre de la excepción dentro del bloque en la parte del DECLARE
2. Utilice el PRAGMA EXCEPTION_INIT (exception, error_number)
3. Haga referencia a la excepción en la zona de EXCEPTION

DECLARE
nombre_excepción EXCEPTION;
PRAGMA EXCEPTION_INIT (nombre_excepción,numero);
.
.
.
EXCEPTION
WHEN nombre_excepción THEN
DBMS_OUTPUT.PUT_LINE('ERROR NO SE PUEDE...');
END;


Subprogramas

Son aquellos bloques PL/SQL que pueden tener parámetros y los cuales son
invocados. Estos son las funciones y los procedimientos.

Header //nos indica si es un procedimiento o una funcion
IS|AS
Declaration section //Sección de declaracion
BEGIN
Executable section //Acciones a ser ejecutadas
EXCEPTION
Exception section //Sección que captura errores
END;

Beneficios
- Vamos a poder modificar rutinas sin interferir con otros usuarios
- Controlar el acceso (indirecto) a la base de datos
- Reduce el numero de llamados a la base de datos, decrementando asi el tráfico
de la red


Procedures
Es un bloque con nombre el cual ejecuta una acción. Este puede contener parámetros y puede ser invocado por muchas otras aplicaciones.

CREATE [OR REPLACE] PROCEDURE nombre_procedimiento
[(parameter|[model]datatype1, parameter2...]
IS|AS
PL/SQL block;

Usando parámetros
IN - Default - El valor es pasado a un subrprograma, los parámetros actuan como una constante.

CREATE OR REPLACE PROCEDURE raise_salary (v_id IN emp.empno%TYPE)
IS
BEGIN
UPDATE emp
SET sal=sal*1.10
WHERE empno=v_id;
END raise_sal;
/

SQL> EXECUTE raise_salary(7369);

OUT - Deben especificarse - Son retornados por el bloque y deben ser variables.

CREATE OR REPLACE PROCEDURE query_emp (v_id IN emp.empno%TYPE, v_name OUT emp.ename%TYPE )
IS
BEGIN
SELECT ename
INTO v_name
FROM emp
WHERE empno=v_id
END query_emp;
/

>start query_emp
>VARIABLE g_name VARCHAR2(15)
>EXECUTE query_emp (7654,:g_name)
>PRINT g_name

Para ver los valores puede utilizar la función:
TEXT_IO.PUT_LIBNE(:var1);

INOUT - Deben especificarse - Se pasan a un subprograma y se retornan. Deben ser variables.
El valor que se paso es retornado como se paso o con un nuevo valor.

CREATE OR REPLACE PROCEDURE format_phone (v_phone_no INOUT VARCHAR2)
IS
BEGIN
v_phone_no:='('||SUBSTR(v_phone_no,1,3)||')'||SUBSTR(v_phone_no,4,3)||'-'||SUBSTR(v_phone_no,7);
END format_phone;

>VARIABLE g_phone_no VARCHAR2(15)
>BEGIN :g_phone_no:='0928233326';END;
>EXECUTE format_phone(:g_phone_no)
>PRINT g_phone_no

Invocando un procedimiento desde un bloque anónimo

DECLARE
v_id NUMBER:=7000;
BEGIN
procedimiento (v_id);
.
.
.
END;

Quitando un procedimiento
DROP PROCEDURE nombre_procedimiento;


Funciones

Es un bloque PL/SQL con nombre el cual retorna un valor. Por lo general
lo utilizamos para computar un valor.

CREATE [OR REPALCE] FUNCTION nombre_funcion [(parametro1 [mode1] datatype,...]
RETURN datatype
IS|AS
PL/SQL bloque;

Ejemp:

CREATE OR REPLACE FUNCTION getsal (v_id IN emp.empno%TYPE) RETURN NUMBER
IS
v_salary emp.sal%TYPE :=0;
BEGIN
SELECT sal
INTO v_salary
FROM emp
WHERE empno=v_id;
RETURN v_salary;
END getsal;

Ejecutando funciones
SQL> SART getsalary.sql
> VARIABLE g_salary NUMBER
> EXECUTE :g_salary:=getsal(7934);
> PRINT g_salary

Ventajas de las funciones
* Permite realizar cálculos muy complejos, o cálculos que no estan disponibles
en con SQL.
* Incrementa la eficiencia de los queries

CREATE OR REPLACE FUNCTION tax (v_value IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (v_value * 0,8);
END tax;
/

Restricciones de las funciones que se llaman desde SQL
- Solo las stored function pueden ser invocadas por sentencias SQL
- Las funciones deben ser de una sola fila
- Los tipos de datos deben ser los validos por SQL
- Solo pueden tomar valores IN
- No sirven BOOLEAN, RECORD, TABLES

Quitando una función
DROP FUNCTION nombre_funcion;

Procedimiento o funcion?
Usted crea un procedimiento para guardar una serie de acciones para
ejecutarse despues. Un procedimiento puede tener cero o mas parámetros,
pero no retorna ningun valor.

Usted crea una función cuando quiere computar un valor el cual debe
ser retornado. Puede contener cero o mas parámetros. Usted debera
declarar parámetros OUT y INOUT.


Paquetes

Son aquellos que agrupan PL/SQL types, items y subprogramas. Estos contienen dos partes:

- La especificación
- El cuerpo

No pueden ser invocados ni parametrizados, una vez que se compila, su contenido se puede compartir por muchas aplicaciones.

La especificaciónes la interface y en ella se declaran:
- tipos, variables, constantes, excepciones, cursores y subprogramas

El cuerpo define:
- cursores, subprogramas e implementa las especificaciones de la interface

Componentes de un paquete

Cree en el paquete
la especificación ---> Aca están los constructores públicos
                                        ---> estos se pueden referenciar desde cualquier
                                                servidor ORACLE

Public Package constructors: Son aquellos que son declarados en
la especificación y se definen en el cuerpo

Cree el cuerpo del
paquete ---> Acá estan todos los constructores privados

                           ---> estos se pueden referenciar por otros constructores
                                               que hacen parte del mismo paquete


Private Package constructors: Son aquellos que estan definidos en
el cuerpo.

Creando en un paquete su especificación

CREATE [OR REPLACE] PACKAGE nombre_paquete
IS|AS
public type and item declarations;
subprogram especifications;
END nombre_paquete;

Ejemplo:

CREATE OR REPLACE PACKAGE comm_package
IS
g_comm NUMBER:=10;
PROCEDURE reset_comm (v_comm IN NUMBER);
END comm_package;

Creando en un paquete su cuerpo

CREATE [OR REPLACE] PACKAGE BODY nombre_paquete
IS|AS
private type and item declarations;
subprogram bodies;
END nombre_paquete;

Ejemplo:

CREATE OR REPLACE PACKAGE BODY comm_package
IS
FUNCTION validate_comm (v_comm IN NUMBER) RETURN BOOLEAN
IS
   v_max_comm NUMBER;
BEGIN
-
-
-
END validate_comm;
PROCEDURE reset_comm (v_comm IN NUMBER)
IS
BEGIN
IF validate_comm (v_comm) THEN
     g_comm=v_comm;
ELSE
-
-
-
END reset_comm;
END comm_package;

Invocando un paquete

EXECUTE comm_package.reset_comm(15);


Usted puede crear variables publicas que van a existir mientras que el usuario este activo en la sesión.

También se puede crear una especificación de un paquete sin su cuerpo.

CREATE OR REPLACE PACKAGE global_vars IS
mile_2_kilo CONSTANT NUMBER := 1,6093;
kilo_2_mile CONSTANT NUMBER := 0,6214;
END global_vars;
/

Referenciando variables públicas desde otro procedimiento

CREATE PROCEDURE meter_to_yard (v_meter IN NUMBER, v_yard OUT NUMBER)
IS
BEGIN
v_yard := v_meter * global_vars.mile_2_kilo;
END global_vars;
/

Removiendo paquetes

DROP PACKAGE package_name;
DROP PACKAGE BODY package_name;

Sobrecarga de funciones o procedimientos

Nos permite el mismo nombre para diferentes subprogramas dentro del mismo paquete. La única condición es que los parámetros deben ser distintos en numero, orden o tipos de datos

Ejem:

CREATE OR REPLACE PACKAGE BODY over_pack
IS
PROCEDURE add_dept (v_deptno IN NUMBER, v_name IN VARCHAR2, v_loc IN VARCHAR2)
IS
BEGIN
-
-
-
END over_pack;
PROCEDURE add_dept (v_name IN VARCHAR2, v_loc IN VARCHAR2)
IS
BEGIN
-
-
END add_dept;
END over_pack;



Triggers

Es un bloque PL/SQL (procedimiento almacenado) que se ejecuta implicitamente cuando ocurre un evento sobre dicha tabla. Ya sea un INSERT, UPDATE, DELETE, el usuario se logea, el usuario sale de la base de datos.

Guia
- Se utilizan para garantizar que sobre una operacion se ejecute las acciones
- No las use para reemplazar la funcionalidad de lo que nos ofrece ORACLE
- Uselas solo cuando sea necesario

Creando un trigger
La operación básica que despierta el trigger se conoce como sentencia disparadora. Donde su ejecucion puede ser antes o despues de llevar a cabo la sentencia disparadora.

También debemos especificar si va a afectar a una o mas filas de una tabla y en cuales de las filas se debe ejecutar.

Cuando usuarlas
- Para evitar la ejecución de transacciones invalidas
- Para garantizar el cumplimiento de restricciones de integridad
- Para garantizar el cumplimiento de las reglas de negocio

No usar
- Disparadores recursivos, estos agotan la memoria
- muchas instrucciones dentro del trigger. En dado caso de que sea necesario, mejor meterlo en un procedimiento almacenado que lo invoque.

Creacion
CREATE [OR REPLACE] TRIGGER nombre
<BEFORE|AFTER> <sentencia disparadora> ON <tabla>
[FOR EACH ROW]
[WHEN (restriccion)]
BEGIN
<cuerpo>
END;

donde:
<BEFORE|AFTER> sentencia activadora
<sentencia disparadora> tipo de operación que despierta el disparador
<tabla> tabla asociada con el trigger
[FOR EACH ROW] Nos determina si es a nivel de filas, este se ejecuta de manera individual por cada fila
[WHEN (restriccion)] condición a evaluar por cada fila que afecta al disparador
<cuerpo> se ejecuta cuando se efectua la sentencia disparadora


Podemos incluir
* INSERTING
* DELETING
* UPDATING

Donde se presentan dos nombre de correlación para cada columna de la tabla; valor viejo :old.nomcol, valor nuevo :new.nomcol.

Ejemplo:
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT ON emp
BEGIN
IF (TO_CHAR(sysdate,'DY')IN('SAT','SUN')) OR (TO_CHAR(sysdate ,'HH24')NOT BETWEEN '08' AND '18')
THEN RAISE_APPLICATION_ERROR (-20500, 'solo dede ingresar en horas laborales');
EN IF;

SQL> INSERT INTO emp(empno,ename,deptno)
VALUES (7777,'ANDRES',40);

ERROR!!!

.
.
.
IF ... THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (...);
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (...);
ELSIF UPDATING ('columna') THEN
RAISE_APPLICATION_ERROR (...);
END IF;

Usando OLD and NEW qualifiers
Con ROW trigger, debemos referenciar el valor de la columna antes y despues colocando los
prefijos OLD y NEW.
OLD NEW
INSERT NULL Inserted value
UPDATE value before update value after update
DELETE value before delete NULL

Ejemplo:
CREATE OR REPLACE TRIGGER restrict_salary
BEFORE INSERT OR UPDATE OF sal ON emp
FOR EACH ROW
BEGIN
IF NOT (:NEW.JOB IN ('MANAGER','PRESIDENT')) AND :NEW.SAL >5000
THEN RAISE_APPLICATION_ERROR (-20202, 'el empleado no puede ganar ese salario');

Manejando triggers
ALTER TRIGGER name DISABLE|ENABLE
ALTER TABLE nombre DISABLE|ENABLE ALL TRIGGERS
ALTER TRIGGER name COMPILE

Cuando un trigger se crea por primera vez, este se habilita automáticamente.

Borrando un trigger
DROP TRIGGER name

Triggers de bases de datos
Son aquellos en los que el evento disparador puede ser una sentencia DDL (Alter - Drop - Create)
o un evento relacionado con la base de datos.

Triggers de eventos del sistema
- Cuando la base de datos se carga o se baja
- Cuando ocurre un error en la base de datos
- Cuando un usuario se logea o se sale

Indice de temas
                   
   
Apuntes Primer Previo
  Bases de datos II

 

 

 

 

 

 

 

 

 

 

 

 

 


   
 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Copyright 2005 Universidad del Cauca, J. Andres G. Flechas R.. All rights reserved.