lunes, 30 de junio de 2014

Tarea 9 - TRIGGERS.


Declaración de triggers

    Un trigger es un bloque PL/SQL asociado a una tabla, que se ejecuta como consecuencia de una determinada instrucción  SQL (una operación DML: INSERT, UPDATE o DELETE) sobre dicha tabla.
    La sintaxis para crear un trigger es la siguiente:

CREATE [OR REPLACE] TRIGGER <nombre_trigger>
{BEFORE|AFTER} 
               {DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]
           [OR {DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]...]}
ON <nombre_tabla>
[FOR EACH ROW [WHEN (<condicion>)]]
DECLARE
  -- variables locales
BEGIN  -- Sentencias[EXCEPTION]  -- Sentencias control de excepcion  
END <nombre_trigger>;
   
 El uso de OR REPLACE permite sobreescribir un trigger existente. Si se omite, y el trigger existe, se producirá, un error.
    Los triggers pueden definirse para las operaciones INSERT, UPDATE o DELETE, y pueden ejecutarse antes o después de la operación.   El modificador BEFORE AFTER indica que el trigger se ejecutará antes o despues de ejecutarse la sentencia SQL definida por DELETE INSERT  UPDATE. Si incluimos el modificador OF el trigger solo se ejecutará cuando la sentencia SQL afecte a los campos incluidos en la lista.
    El alcance de los disparadores puede ser la fila o de orden. El modificador FOR EACH ROW indica que el trigger se disparará cada vez que se realizan operaciones sobre una fila de la tabla. Si se acompaña del modificador WHEN, se establece una restricción; el trigger solo actuará, sobre las filas que satisfagan la restricción.

    La siguiente tabla resume los contenidos anteriores.
Valor
Descripción
INSERT, DELETE, UPDATEDefine qué tipo de orden DML provoca la activación del disparador.
BEFORE , AFTERDefine si el disparador se activa antes o después de que se ejecute la orden.
FOR EACH ROWLos disparadores con nivel de fila se activan una vez por cada fila afectada por la orden que provocó el disparo. Los disparadores con nivel de orden se activan sólo una vez, antes o después de la orden. Los disparadores con nivel de fila se identifican por la cláusula FOR EACH ROW en la definición del disparador.
   
 La cláusula WHEN sólo es válida para los disparadores con nivel de fila.
    Dentro del ambito de un trigger disponemos de las variables OLD y NEW . Estas variables se utilizan del mismo modo que cualquier otra variable PL/SQL, con la salvedad de que no es necesario declararlas, son de tipo %ROWTYPE y contienen una copia del registro antes (OLD) y despues(NEW) de la acción SQL (INSERT, UPDATE, DELTE) que ha ejecutado el trigger. Utilizando esta variable podemos acceder a los datos que se están insertando, actualizando  o borrando.
   
   El siguiente ejemplo muestra un trigger que inserta un registro en la tabla PRECIOS_PRODUCTOS cada vez que insertamos un nuevo registro en la tabla PRODUCTOS:
CREATE OR REPLACE TRIGGER TR_PRODUCTOS_01
  AFTER INSERT ON PRODUCTOS  
  FOR EACH ROW
DECLARE
  -- local variables 
BEGIN
  INSERT INTO PRECIOS_PRODUCTOS
  (CO_PRODUCTO,PRECIO,FX_ACTUALIZACION)
  VALUES
  (:NEW.CO_PRODUCTO,100,SYSDATE);
END ; 

    El trigger se ejecutará cuando sobre la tabla PRODUCTOS se ejecute una sentencia INSERT.
INSERT INTO PRODUCTOS
(CO_PRODUCTO, DESCRIPCION)
VALUES('000100','PRODUCTO 000100'); 


Orden de ejecución de los triggers
    Una misma tabla puede tener varios triggers. En tal caso es necesario conocer el orden en el que se van a ejecutar.
    Los disparadores se activan al ejecutarse la sentencia SQL.
  • Si existe, se ejecuta el disparador de tipo BEFORE (disparador previo) con nivel de orden.
  • Para cada fila a la que afecte la orden:
    • Se ejecuta si existe, el disparador de tipo BEFORE con nivel de fila.
    • Se ejecuta la propia orden.
    • Se ejecuta si existe, el disparador de tipo AFTER (disparador posterior) con nivel de fila.
  • Se ejecuta, si existe, el disparador de tipo AFTER con nivel de orden. 


Restricciones de los triggers
    El cuerpo de un trigger es un bloque PL/SQL. Cualquier orden que sea legal en un bloque PL/SQL, es legal en el cuerpo de un disparador, con las siguientes restricciones:

  • Un disparador no puede emitir ninguna orden de control de transacciones: COMMITROLLBACK o SAVEPOINT. El disparador se activa como parte de la ejecución de la orden que provocó el disparo, y forma parte de la misma transacción que dicha orden. Cuando la orden que provoca el disparo es confirmada o cancelada, se confirma o cancela también el trabajo realizado por el disparador.
  • Por razones idénticas, ningún procedimiento o función llamado por el disparador puede emitir órdenes de control de transacciones.
  • El cuerpo del disparador no puede contener ninguna declaración de variables LONG o LONG RAW





http://www.devjoker.com/



sábado, 14 de junio de 2014

TAREA6.

Con su grupo de trabajo crear (inventar)  ejemplos, desarrollar  y publicar en su blog, el código correspondiente del o los procedimientos almacenados que utilicen las siguientes instrucciones: ( publique el código y las referencias en donde se inspiró),
  • Varray, 
  • Record, 
  • Table, 
  • instruccion case 
  • %type
  • %Rowtype

VARRAYS

Definición de VARRAYS.

    Un varray se manipula de forma muy similar a las tablas de PL, pero se implementa de forma diferente. Los elementos en el varray se almacenan comenzando en el índice 1 hasta la longitud máxima declarada en el tipo varray.
    La sintaxis general es la siguiente:

TYPE <nombre_tipo> IS VARRAY (<tamaño_maximo>) OF <tipo_elementos>;
    Una consideración a tener en cuenta es que en la declaración de un varray el tipo de datos no puede  ser de los siguientes tipos de datos:
  • BOOLEAN
  • NCHAR
  • NCLOB
  • NVARCHAR(n)
  • REF CURSOR
  • TABLE
  • VARRAY
    Sin embargo se puede especificar el tipo utilizando los atributos %TYPE y %ROWTYPE
    Los VARRAY deben estar inicializados antes de poder utilizarse. Para inicializar un VARRAY se utiliza un constructor (podemos inicializar el VARRAY en la sección DECLARE o bien dentro del cuerpo del bloque):
DECLARE
    /* Declaramos el tipo VARRAY de cinco elementos VARCHAR2*/
    TYPE t_cadena IS VARRAY(5) OF VARCHAR2(50);
    /* Asignamos los valores con un constructor */
    v_lista t_cadena:= t_cadena('Aitor', 'Alicia', 'Pedro','','');
BEGIN
    v_lista(4) := 'Tita';
    v_lista(5) := 'Ainhoa';
END;
     El tamaño de un VARRAY se establece mediante el número de parámetros utilizados en el constructor, si declaramos un VARRAY de cinco elementos pero al inicializarlo pasamos sólo tres parámetros al constructor, el tamaño del VARRAY será tres. Si se hacen asignaciones a elementos que queden fuera del rango se producirá un error.
    El tamaño de un VARRAY podrá aumentarse utilizando la función EXTEND, pero nunca con mayor dimensión que la definida en la declaración del tipo. Por ejemplo, la variable v_lista que sólo tiene 3 valores definidos por lo que se podría ampliar hasta cinco elementos pero no más allá.
    Un VARRAY comparte con las tablas de PL todas las funciones válidas para ellas, pero añade las siguientes:

  • LIMIT . Devuelve el número maximo de elementos que admite el VARRAY.
  • EXTEND .Añade un elemento al VARRAY.
  • EXTEND(n) .Añade (n) elementos al VARRAY.



RECORDS


Declaración de un registro(Record).
    Un registro es una estructura de datos en PL/SQL, almacenados en campos, cada uno de los cuales tiene su propio nombre y tipo y que se tratan como una sola unidad lógica.
    Los campos de un registro pueden ser inicializados y pueden ser definidos como NOT NULL. Aquellos campos que no sean inicializados explícitamente, se inicializarán a NULL.
    La sintaxis general es la siguiente:

TYPE <nombre> IS RECORD 
(
campo <tipo_datos> [NULL | NOT NULL] 
[,<tipo_datos>...]
); 

    El siguiente ejemplo crea un tipo PAIS, que tiene como campos el código, el nombre y el continente.

TYPE PAIS IS RECORD 
(
CO_PAIS     NUMBER  ,
DESCRIPCION VARCHAR2(50),
CONTINENTE  VARCHAR2(20)

);  
    Los registros son un tipo de datos, por lo que podremos declarar variables de dicho tipo de datos.


DECLARE
 
  TYPE PAIS IS RECORD 
  (
    CO_PAIS     NUMBER  ,
    DESCRIPCION VARCHAR2(50),
    CONTINENTE  VARCHAR2(20)
  );  
/* Declara una variable identificada por miPAIS de tipo PAIS 
   Esto significa que la variable miPAIS tendrá los campos 
   ID, DESCRIPCION y CONTINENTE.

 */
  miPAIS PAIS;
BEGIN
/* Asignamos valores a los campos de la variable.

 */
  miPAIS.CO_PAIS := 27;
  miPAIS.DESCRIPCION := 'ITALIA';
  miPAIS.CONTINENTE  := 'EUROPA';
END;

    Los registros pueden estar anidados. Es decir, un campo de un registro puede ser de un tipo de dato de otro registro.

DECLARE 
 TYPE PAIS IS RECORD 
 (CO_PAIS     NUMBER  ,
  DESCRIPCION VARCHAR2(50),
  CONTINENTE  VARCHAR2(20)
 );  
 TYPE MONEDA IS RECORD
 ( DESCRIPCION VARCHAR2(50),
   PAIS_MONEDA PAIS ); 
 
 miPAIS   PAIS; 
 miMONEDA MONEDA;
BEGIN
     /* Sentencias
      */
END;

    Pueden asignarse todos los campos de un registro utilizando una sentencia SELECT. En este caso hay que tener cuidado en especificar las columnas en el orden conveniente según la declaración de los campos del registro. Para este tipo de asignación es muy frecuente el uso del atributo %ROWTYPE que veremos más adelante.

SELECT  CO_PAIS, DESCRIPCION, CONTINENTE
INTO miPAIS
FROM PAISES
WHERE CO_PAIS = 27;
     Puede asignarse un registro a otro cuando sean del mismo tipo:



DECLARE
 
  TYPE PAIS IS RECORD ...
  miPAIS PAIS;
  otroPAIS PAIS;
BEGIN

  miPAIS.CO_PAIS := 27;
  miPAIS.DESCRIPCION := 'ITALIA';
  miPAIS.CONTINENTE  := 'EUROPA';
  otroPAIS := miPAIS;  
END;



TABLAS

Declaración de tablas de PL/SQL
    Las tablas de PL/SQL son tipos de datos que nos permiten almacenar varios valores del mismo tipo de datos.
    Una tabla PL/SQL :
  • Es similar a un array
  • Tiene dos componenetes: Un índice de tipo BINARY_INTEGER que permite acceder a los elementos en la tabla PL/SQL y una columna de escalares o registros que contiene los valores de la tabla PL/SQL
  • Puede incrementar su tamaño dinámicamente.
    La sintaxis general para declarar una tabla de PL es la siguiente:
TYPE <nombre_tipo_tabla> IS TABLE OF
<tipo_datos> [NOT NULL]
INDEX BY BINARY_INTEGER ;
    Una vez que hemos definido el tipo, podemos declarar variables y asignarle valores.

DECLARE
   /* Definimos el tipo PAISES como tabla PL/SQL */
   TYPE PAISES IS TABLE OF NUMBER INDEX BY BINARY_INTEGER ; 
   /* Declaramos una variable del tipo PAISES */
   tPAISES PAISES;
BEGIN   tPAISES(1) := 1;
   tPAISES(2) := 2;
   tPAISES(3) := 3;
END;

     No es posible inicializar las tablas en la inicialización.
     El rango de binary integer es –2147483647.. 2147483647, por lo tanto el índice puede ser negativo, lo cual indica que el índice del primer valor no tiene que ser necesariamente el cero.

Tablas PL/SQL de registros
    Es posible declarar elementos de una tabla PL/SQL como de tipo registro.

DECLARE
 
  TYPE PAIS IS RECORD 
  (
    CO_PAIS     NUMBER NOT NULL ,
    DESCRIPCION VARCHAR2(50),
    CONTINENTE  VARCHAR2(20)
  );  
  TYPE PAISES IS TABLE OF PAIS INDEX BY BINARY_INTEGER ;
  tPAISES PAISES;
BEGIN

  tPAISES(1).CO_PAIS := 27;
  tPAISES(1).DESCRIPCION := 'ITALIA';
  tPAISES(1).CONTINENTE  := 'EUROPA';
END;

Funciones para el manejo de tablas PL/SQL
    Cuando trabajamos con tablas de PL podemos utilizar las siguientes funciones:
  • FIRST. Devuelve el menor índice de la tabla. NULL si está vacía.
  • LAST. Devuelve el mayor índice de la tabla. NULL si está vacía.
    El siguiente ejemplo muestra el uso de FIRST y LAST : 
DECLARE 
 TYPE ARR_CIUDADES IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
 misCiudades ARR_CIUDADES;
BEGIN
     misCiudades(1) := 'MADRID';
     misCiudades(2) := 'BILBAO';
     misCiudades(3) := 'MALAGA';
     
     FOR i IN misCiudades.FIRST..misCiudades.LAST
     LOOP
         dbms_output.put_line(misCiudades(i));
     END LOOP;
END;
  • EXISTS(i). Utilizada para saber si en un cierto índice hay almacenado un valor. Devolverá TRUE si en el índice i hay un valor.
DECLARE 
 TYPE ARR_CIUDADES IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
 misCiudades ARR_CIUDADES;
BEGIN     misCiudades(1) := 'MADRID';     
     misCiudades(3) := 'MALAGA';
     
     FOR i IN misCiudades.FIRST..misCiudades.LAST
     LOOP         IF misCiudades.EXISTS(i) THEN
           dbms_output.put_line(misCiudades(i));
         ELSE
           dbms_output.put_line('El elemento no existe:'||TO_CHAR(i));
         END IF; 
     END LOOP;
END;
  • COUNT. Devuelve el número de elementos de la tabla PL/SQL.
DECLARE 
 TYPE ARR_CIUDADES IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
 misCiudades ARR_CIUDADES;
BEGIN
     misCiudades(1) := 'MADRID';     
     misCiudades(3) := 'MALAGA';
     /* Devuelve 2, ya que solo hay dos elementos con valor */
     dbms_output.put_line(
     'El número de elementos es:'||misCiudades.COUNT);    
END;
  • PRIOR (n). Devuelve el número del índice anterior a n en la tabla.
DECLARE
  TYPE ARR_CIUDADES IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
  misCiudades ARR_CIUDADES;
BEGIN  misCiudades(1) := 'MADRID';
  misCiudades(3) := 'MALAGA'; 
  /* Devuelve 1, ya que el elemento 2 no existe */
  dbms_output.put_line(
  'El elemento previo a 3 es:' || misCiudades.PRIOR(3));
END;
  • NEXT (n). Devuelve el número del índice posterior a n en la tabla.
DECLARE
  TYPE ARR_CIUDADES IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
  misCiudades ARR_CIUDADES;
BEGIN  misCiudades(1) := 'MADRID';
  misCiudades(3) := 'MALAGA'; 
  /* Devuelve 3, ya que el elemento 2 no existe */  dbms_output.put_line(
  'El elemento siguiente es:' || misCiudades.NEXT(1));
END;
  • TRIM. Borra un elemento del final de la tabla PL/SQL.
  • TRIM(n) borra n elementos del final de la tabla PL/SQL.
  • DELETE. Borra todos los elementos de la tabla PL/SQL.
  • DELETE(n) borra el correspondiente al índice n.
  • DELETE(m,n) borra los elementos entre m y n.



CASE

Estructura condicional CASE
    La estructura condicional CASE permite evaluar una expresion y devolver un valor u otro.
    La sintaxis general de case es:
    CASE <expresion>
        WHEN <valor_expresion> THEN <valor_devuelto>
        WHEN <valor_expresion> THEN <valor_devuelto>
        ELSE <valor_devuelto>  -- Valor por defecto
    END
    Ejemplo de CASE.
    DECLARE @Web varchar(100),
            @diminutivo varchar(3)
    SET @diminutivo = 'DJK'    SET @Web = (CASE @diminutivo
                    WHEN 'DJK' THEN 'www.devjoker.com'
                    WHEN 'ALM' THEN 'www.aleamedia.com'
                    ELSE 'www.devjoker.com'
                END)
    PRINT @Web 
    Otra sintaxis de CASE nos permite evaluar diferentes expresiones:
    CASE 
        WHEN <expresion> = <valor_expresion> THEN <valor_devuelto>
        WHEN <expresion> = <valor_expresion> THEN <valor_devuelto>
        ELSE <valor_devuelto> -- Valor por defecto
    END
    El mismo ejemplo aplicando esta sintaxis:
    DECLARE @Web varchar(100),
            @diminutivo varchar(3)
    SET @diminutivo = 'DJK'
     SET @Web = (CASE 
                    WHEN @diminutivo = 'DJK' THEN 'www.devjoker.com'
                    WHEN @diminutivo = 'ALM' THEN 'www.aleamedia.com'
                    ELSE 'www.devjoker.com'
                END)
    PRINT @Web 

    Otro aspecto muy interesante de CASE es que permite el uso de subconsultas.
    DECLARE @Web varchar(100),
            @diminutivo varchar(3)
    SET @diminutivo = 'DJK'
     SET @Web = (CASE 
                    WHEN @diminutivo = 'DJK' THEN (SELECT  web
                                                   FROM WEBS 
                                                   WHERE id=1)
                    WHEN @diminutivo = 'ALM' THEN (SELECT  web
                                                   FROM WEBS 
                                                   WHERE id=2)
                    ELSE 'www.devjoker.com'
                END)
    PRINT @Web 


%TYPE

El atributo %TYPE permite conocer el tipo de una variable, constante o campo de la base de datos.

La sintaxis %TYPE:

  tipo_campo|variable%TYPE
  customers.name%TYPE

Por ejemplo:
DECLARE
  v_EmpName emp.ename%TYPE;
  BEGIN
  SELECT ename INTO v_EmpName FROM emp WHERE ROWNUM = 1;
  DBMS_OUTPUT.PUT_LINE('Name = '|| v_EmpName);
  END;
    

%ROWTYPE


El atributo%ROWTYPE permite obtener los tipos de todos los campos de una tabla de la base de datos, de una vista o de un cursor.

     Por ejemplo, si tengo una tabla PAISES declarada como:
CREATE TABLE PAISES(
CO_PAIS          NUMBER,
DESCRIPCION      VARCHAR2(50),
CONTINENTE       VARCHAR2(20) );
    Puedo declarar una variable de tipo registro como PAISES%ROWTYPE;

DECLARE  miPAIS PAISES%ROWTYPE;
BEGIN
  /* Sentencias ... */
END;
     Lo cual significa que el registro miPAIS tendrá la siguiente estructura: CO_PAIS NUMBER, DESCRIPCION VARCHAR2(50), CONTINENTE VARCHAR2(20).
    De esta forma se crea el registro de forma dinamic y se podrán asignar valores a los campos de un registro a través de un select sobre la tabla, vista o cursor a partir de la cual se creo el registro.




http://www.devjoker.com/gru/tutorial-PL-SQL/PLSQ/Tutorial-PL-SQL.aspx

TAREA 7 - USO DE CURSOR.

CURSORES EXPLICITOS EN PL/SQL.

 Los cursores explicitos se emplean para realizar consultas SELECT que pueden devolver cero filas o más de una fila.

* Para trabajar con un cursor explicito necesitamos realizar las siguientes tareas:
   - Declarar el Cursor.
   - Abrir el Cursor con la instrucción OPEN.
   - Leer los datos del Cursor con la instrucción FETCH.
   - Cerrar el Cursor y leberar los recursos con la instrucción CLOSE.

* Para declarar un cursor debemos emplear la siguiente sintaxis:
     CURSOR nombre_cursor IS
     instrucción_SELECT

* También debemos declarar los posibles parámetros que requiera el Cursor:
     CURSOR nombre_cursor(param1 tipo1, ..., paramN tipoN) IS
     instrucción_SELECT

   Para abrir el Cursor:  
     OPEN nombre_cursor;
   o bien (en el caso de un Cursor con parámetros)
     OPEN nombre_cursor(valor1, valor2, ..., valorN);

   Para recuperar los datos en variables PL/SQL:
     FETCH nombre_cursor INTO lista_variables;
  o bien ...
     FETCH nombre_cursor INTO registro_PL/SQL;

   Para cerrar el Cursor:
     CLOSE nombre_cursor;


** El siguiente ejemplo ilustra el trabajo con un Cursor explicito.
     Hay que tener en cuenta que al leer los datos del Cursor debemos hacerlo sobre variables del mismo tipo de datos de la tabla (o tablas) que trata el Cursor.

   DECLARE
   CURSOR cpaises
   IS
   SELECT co_pais, descripcion, continente
   FROM paises;

   co_pais VARCHAR2(3);
   descripcion VARCHAR2(50);
   continente VARCHAR2(25);
   BEGIN
   OPEN cpaises;
   FETCH cpaises INTO co_pais, descripcion, continente;
   CLOSE cpaises;
   END;


 Podemos simplificar el ejemplo utilizando el atributo de tipo %ROWTYPE sobre el Cursor.

   DECLARE
   CURSOR cpaises
   IS
   SELECT co_pais, descripcion, continente
   FROM paises;

   registro cpaises %ROWTYPE;
   BEGIN
   OPEN cpaises;
   FETCH cpaises INTO registro;
   CLOSE cpaises;
   END;


 El mismo ejemplo, pero utilizando parámetros:

   DECLARE
   CURSOR cpaises (p_continente VARCHAR2)
   IS
   SELECT co_pais, descripcion, continente
   FROM paises
   WHERE continente=p_continente;

   registro cpaises %ROWTYPE;
   BEGIN
   OPEN cpaises('EUROPA');
   FETCH cpaises INTO registro;
   CLOSE cpaises;
   END;


**Cuando trabajamos con Cursores debemos considerar:
  - Cuando un Cursor está cerrado, no se puede leer.
  - Cuando leemos un Cursor debemos comprobar el resultado de la lectura utilizando los atributos de los Cursores.
  - Cuando se cierra el Cursor, es ilegal tratar de usarlo.
  - Es ilegal tratar de cerrar un Cursor que ya está cerrado o no ha sido abierto.

**Atributos de los Cursores.
    Toman los valores TRUE, FALSE o NULL dependiendo de la situación:
      - Antes de abrir;
             %NOTFOUND ORA-1001 NULL FALSE TRUE ORA-1001
      - Al abrir durante la recuperación;
             %FOUND ORA-1001 NULL TRUE FALSE ORA-1001
      - Al finalizar la recuperación;
             %ISOPEN FALSE TRUE TRUE TRUE FALSE
      - Después de cerrar;
             %ROWCOUNT ORA-1001  0 *  ** ORA-1001

          *     Número de registros que ha recuperado hasta el momento.
          **   Número de total de registros.


*** Manejo del Cursor
   Por medio del Ciclo LOOP podemos iterar a través del Cursor. Debe tenerse cuidado de agregar una condición para salir del bucle:
 Veremos varias formas de iterar a tráves de un Cursor;

1. Utilizando Bucle LOOP, con una sentencia EXIT condicionada.

    OPEN nombre_cursor;
    LOOP
    FETCH nombre_cursor INTO lista_variables;
    EXIT WHEN nombre_cursor%NOTFOUND;
    */Procedimiento de los registros recuperados*/
    END LOOP;
    CLOSE nomnre_cursor;

Aplicado a nuestro ejemplo;

    DECLARE
    CURSOR cpaises
    IS
    SELECT co_pais, descripcion, continente
    FROM paises;

    co_pais VARCHAR2(3);
    descripcion VARCHAR2(50);
    continente VARCHAR2(25);
    BEGIN
    OPEN cpaises;
    LOOP
    FETCH cpaises INTO co_pais, descripcion, continente;  
    EXIT WHEN cpaises%NOTFOUND;
    dbms_output.put_line(descripcion);
    END LOOP;
    CLOSE cpaises;
    END;


2. Utilizando Bucle WHILE LOOP, con la instrucción FETCH aparece dos veces.

    OPEN nombre_cursor;
    FETCH nombre_cursor INTO lista_variables;
    WHILE nombre_cursor%FOUND
    LOOP
    */Procedimiento de los registros recuperados*/
    FETCH nombre_cursor INTO lista_variables;
    END LOOP;
    CLOSE nombre_cursor;

Aplicado a nuestro ejemplo;

    DECLARE
    CURSOR cpaises
    IS
    SELECT co_pais, descripcion, continente
    FROM paises;

    co_pais VARCHAR2(3);
    descripcion VARCHAR2(50);
    continente VARCHAR2(25);
    BEGIN
    OPEN cpaises;
    FETCH cpaises INTO co_pais, descripcion, continente;
    WHILE cpaises%FOUND;
    LOOP;
    dbms_output.put_line(descripcion);
    FETCH cpaises INTO co_pais, descripcion, continente;
    END LOOP;
    CLOSE cpaises;
    END;


3. Utilizando Bucle FOR LOOP. Esta es la forma más corta ya que el Cursor es implicitamente se ejecutan las instrucciones OPEN, FETCH y CLOSE.

    FOR variable IN nombre_cursor LOOP
    */Procedimiento de los registros recuperados*/
    END LOOP;

Aplicado a nuestro ejemplo;

    BEGIN
    FOR reg IN (SELECT*FROM paises)
    LOOP
    dbms_output.put_line(descripcion);
    END LOOP;
    END;


sábado, 19 de abril de 2014

TAREA4-SECUENCIA-INDICES-SYNONYM

SECUENCIA

Crea un objeto capaz de darnos números consecutivos únicos.
CREATE SEQUENCE secuencia
      INCREMENT BY n
      START WITH n
      {MAX VALUE n | NOMAXVALUE}
      {MIN VALUE N | NOMINVALUE}
      {CYCLE | NOCYCLE}
      {CACHE N | NOCACHE}
      {ORDER | NOORDER};
En realidad es un generador de identificadores únicos que no bloquea transacciones.

Es muy útil para generar primary keys.

EJEMPLO: crea una secuencia de nombre ID, que se utilizara para la clave primaria de tabla ALUMNO

CREATE SEQUENCE  ID
                INCREMENT BY 1    // se incrementara en 1
                START WITH 1        // se iniciara en 1
                NOMAXVALUE       // sin valor máximo o tope
    NOCYCLE                 // no cycle, no es un ciclo
                NOCACHE ;             // no cache, para no perder números


Si no nos gusta perder números usamos NOCACHE.
CREATE SEQUENCE ID MINVALUE 1 START WITH 1
    INCREMENT BY 1 NOCACHE;

Si nos interesa la velocidad:
CREATE SEQUENCE ID MINVALUE 1 START WITH 1
    INCREMENT BY 1 CACHE 20;

Así obtenemos el siguiente valor:
SELECT ID.NEXTVAL FROM DUAL;

NEXTVAL -------------> Siguiente numero en la secuencia
CURRVAL -------------> Ultimo numero generado

También podemos obtener el valor actual:
SELECT ID.CURRVAL FROM DUAL;


MODIFICAR SECUENCIA:

      Se modifica secuencia creada cambiando el incremento de 1 a 20 y valor máximo a 999999

alter sequence ID
increment by 20
maxvalue 999999
nocache
nocycle;

DONDE SE PUEDE USAR UNA SECUENCIA:

- Clausula VALUES de la instrucción INSERT
- Clausula SET de la instrucción UPDATE
- Clausula SELECT de la instrucción SELECT

DONDE NO SE PUEDE USAR:

- Clausulas DISTINCT, GROUP BY, ORDER BY, WHERE de la instrucción SELECT
- Valor por defecto de una columna
PARA ELIMINAR UNA SECUENCIA UTILIZAMOS EL COMANDO DROP:

- DROP SEQUENCE ID;


INDICES

Los índices se usan para mejorar el rendimiento de las operaciones sobre una tabla.
En general mejoran el rendimiento las SELECT y empeoran (mínimamente) el rendimiento de los INSERT y los DELETE.
Una vez creados no es necesario nada más, Oracle la usa cuando es posible

En Oracle existen tres tipos de índices:

1)Table Index:
CREATE [UNIQUE|BITMAP] INDEX [esquema.]index_name
      ON [esquema.]table_name [tbl_alias]
         (col [ASC | DESC]) index_clause index_attribs

2)Bitmap Join Index:
CREATE [UNIQUE|BITMAP] INDEX [esquema.]index_name
      ON [esquema.]table_name [tbl_alias]
         (col_expression [ASC | DESC])
            FROM [esquema.]table_name [tbl_alias]
               WHERE condition [index_clause] index_attribs

3)Cluster Index:
CREATE [UNIQUE|BITMAP] INDEX [esquema.]index_name
      ON CLUSTER [esquema.]cluster_name index_attribs             

las index_clauses posibles son:
LOCAL STORE IN (tablespace)

LOCAL STORE IN (tablespace)
  (PARTITION [partition
       [LOGGING|NOLOGGING]
       [TABLESPACE {tablespace|DEFAULT}]
       [PCTFREE int]
       [PCTUSED int]
       [INITRANS int]
       [MAXTRANS int]
       [STORAGE storage_clause]
       [STORE IN {tablespace_name|DEFAULT]
       [SUBPARTITION [subpartition [TABLESPACE tablespace]]]])


LOCAL (PARTITION [partition
       [LOGGING|NOLOGGING]
       [TABLESPACE {tablespace|DEFAULT}]
       [PCTFREE int]
       [PCTUSED int]
       [INITRANS int]
       [MAXTRANS int]
       [STORAGE storage_clause]
       [STORE IN {tablespace_name|DEFAULT]
       [SUBPARTITION [subpartition [TABLESPACE tablespace]]]])

GLOBAL PARTITION BY RANGE (col_list)
   ( PARTITION partition VALUES LESS THAN (value_list)
       [LOGGING|NOLOGGING]
       [TABLESPACE {tablespace|DEFAULT}]
       [PCTFREE int]
       [PCTUSED int]
       [INITRANS int]
       [MAXTRANS int]
       [STORAGE storage_clause] )

INDEXTYPE IS indextype [PARALLEL int|NOPARALLEL] [PARAMETERS ('ODCI_Params')]

 {Esto es solo para table index, no para bitmap join Index}

Y además index_attribs puede ser cualquier combinación de los siguientes:
NOSORT|SORT
REVERSE
COMPRESS int
NOCOMPRESS
COMPUTE STATISTICS
[NO]LOGGING
ONLINE
TABLESPACE {tablespace|DEFAULT}
PCTFREE int
PCTUSED int
INITRANS int
MAXTRANS int
STORAGE storage_clause
PARALLEL parallel_clause

Si usamos la opcion PARALLEL esta debe estar al final.

create index es una de las pocas sentencias que pueden usar nologging option.

create index requiere un segmento temporal si no hay espacio en memoria suficiente.


Crear indices basados en funciones require que query_rewrite_enabled este a true y query_rewrite_integrity este a trusted.

Un ejemplo de indices basados en funciones para busquedas en mayusculas:
CREATE INDEX idx_case_ins ON my_table(UPPER(empname));

SELECT * FROM my_table WHERE UPPER(empname) = 'KARL';





SINONIMOS
Crea un sinónimo para algún objeto de la base de datos.
   CREATE [OR REPLACE] [PUBLIC] SYNONYM [esquema.]sinonimo
      FOR [esquema.]objeto [@dblink]

Con la opción 'PUBLIC' se crea un sinónimo público accesible a todos los usuarios, siempre que tengan los privilegios adecuados para el mismo.

Sirve para no tener que usar la notación 'esquema.objeto' para referirse a un objeto que no es propiedad de usuario.

Crea un nombre abreviado a la vista PROGRAMADOR.T_PEDIDOS:
CREATE PUBLIC SYNONYM T_PEDIDOS
FOR PROGRAMADOR.T_PEDIDOS;

No es necesario recompilarlos cuando se redefinen las tablas, de hecho puedes existir sin que exista el objeto al que referencian.

El acceso es un poco más eficiente cuando se accede por sinónimos públicos.
Cuando en una sentencia no citamos el nombre del esquema, Oracle resuelve los nombres en el siguiente orden:
·       usuario actual
·       private synonym
·       public synonym

También podemos usarlo para cambiar el objeto que usamos sin tener que cambiar la programación.

Así cambiamos la tabla:
CREATE PUBLIC SYNONYM T_PEDIDOS FOR PROGRAMADOR.T_PEDIDOS_PRUEBA;
Borrar un sinónimo:
DROP SYNONYM T_PEDIDOS;