CREACIÓN DE UNA NA DE U BASE DE DATOS
CREACION DE UNA BASE DE DATOS Prácticamente, la creación de la base de datos consiste en la creación de las tablas que la componen. Así que para la creación de una nueva base de datos se debe dar clic en una de las bases de datos que están creadas y abrir un nuevo texto de consultas. GRAFICO La sintaxis empleada por PostgreSQL, pero también por las DBMS más difundidas, es la siguiente: CREATE DATABASE nombre_base_de_datos DATABASE nombre_base_de_datos
Ejemplo: CREATE DATABASE PEDIDOS DATABASE PEDIDOS
Creación de Tablas Las tablas forman parte de una base de datos, como se dijo anteriormente entonces para crear una tabla debemos resolver qué campos (columnas) tendrá y qué tipo de datos almacenarán cada uno de ellos, es decir, su estructura. Sintaxis: create table NOMBRETABLA table NOMBRETABLA( ( NOMBRECAMPO 1 TIPODEDATO , ... NOMBRECAMPON TIPODEDATO NOMBRECAMPON TIPODEDATO );
Ejemplo CREATE TABLE EMPLEADOS( EMPLEADOID int NOT NULL, NOMBRE char (30) (30) NULL, APELLIDO char (30) (30) NULL, FECHA_NAC date NULL, REPORTA_A int NULL, EXTENSION int NULL, CONSTRAINT PK_EMPLEADOS PRIMARY KEY (EMPLEADOID));
DROP TABLE El comando DROP TABLE permite eliminar una tabla, incluyendo todas las tuplas almacenadas en ella: Sintaxis: DROP TABLE table_name;
Ejemplo:
DROP TABLE CATEGORIAS;
INSERT INTO Para llenar una tabla previamente creada se hace el uso del comando INSERT INTO, que permite llenar todos los campos que la tabla tiene. Sintaxis: INSERT INTO table_name (name_of_attr_1 [, name_of_attr_2 [,...]]) VALUES (val_attr_1 [, val_attr_2 [ ...]]);
Ejemplo: insert into categorias (categoriaid, nombrecat) values (100, ‘CARNICOS ‘CARNICOS’); ’); insert into categorias (categoriaid, nombrecat) values (200, ‘LACTEOS ‘LACTEOS’); ’); insert into categorias (categoriaid, nombrecat) values (300, ‘LIMPIEZA ‘LIMPIEZA’); ’);
FUNCION UPDATE Cambia los valores de columnas especificadas en todas las flas que satisfagan cierta condición. En la clausula SET se deben mencionar solamente las columnas a ser modificadas; el resto de columnas no mencionadas retendrán sus valores anteriores. Por defecto, UPDATE puede actualizar una tabla específica y todas sus subtablas. Si se desea actualizar únicamente cierta tabla, se debe utilizar la clausula ONLY. Existen dos maneras de modificar una tabla utilizando la información contenida en otras tablas en la base de datos: utilizando utilizando subconsultas o especificando las tablas adicionales en la clausula FROM. La técnica más apropiada depende de las circunstancias específicas.
Sintaxis: UPDATE [ ONLY ] table SET column = { expression | DEFAULT } [, ...] [ FROM fromlist ]
Donde:
table: Nombre de la tabla a actualizar. column: Nombre de la columna de la tabla. El nombre de la columna puede calificarse como nombre de un subcampo o subíndice del arreglo, si es necesario. expression: Expresión para asignar a la columna. La expresión podría utilizar los antiguos valores de esa y otras columnas en la tabla. DEFAULT: Asigna el valor predefinido a la columna (qué será NULL si ninguna expresión predefinida específica se ha asignado a él). fromlist: Una lista de expresiones de la tabla, permitiendo la aparición de columnas de otras tablas en la condición WHERE y las expresiones de actualización. Esto es similar a la lista de tablas en que pueden especificarse en la función FROM de una sentencia SELECT. La tabla designada no debe aparecer en el fromlist, a menos que se inserte un self-join (en tal caso debe aparecer con un alias). condition: Una expresión que devuelve un valor del tipo booleano. Solamente pueden actualizadas las flas para las cuales devuelve el valor true. UPDATE count: count es el número de flas actualizadas. Si el valor de count es igual a cero, ninguna fila cumple con la condición (no quiere decir que ha ocurrido un error).
Nota: Cuando una clausula FROM está presente, lo que ocurre esencialmente es que la tabla designada se une a las tablas mencionadas en el fromlist, y cada fila resultante en la unión representa una operación de actualización para las tablas designadas. Cuando se utiliza FROM se debe asegurar que la unión produce a lo mucho una fila resultante para cada fila a ser modificada. En otras palabras, una fila designada no debe unir a más de una fila en la otra tabla(s). Si lo hace, entonces solamente se utilizará una fila para actualizarla cuya selección es aleatoria. Debido a esta indeterminación, es más seguro hacer referencia a otras tablas dentro de subconsultas de SELECT, aunque a menudo es más difícil leer y más retardado que utilizando una unión.
Ejemplo: Actualizar el nombre de la categoría HIGINE PERSONAL a HIGIENE PERSONAL, en la columna nombrecat: UPDATE CATEGORIAS SET nombrecat = ‘HIGIENE PERSONAL’ WHERE nombrecat = ‘HIGINE PERSONAL’;
ALTER TABLE: Cambia la definición de una tabla existente. Existen varias de sus formas:
ADD COLUMN: Añade una nueva columna a la tabla utilizando la misma sintaxis que CREATE TABLE.
DROP COLUMN: Elimina una columna de la tabla. Los índices y constraints que involucra la column deberán ser automáticamente borrados también. Si algún elemento externo depende de la columna, será necesario utilizar la clausula CASCADE, por ejemplo, referencias a clave foráneas o vistas.
SET/DROP DEFAULT : Coloca o remueve el valor predefinido de una columna. El valor predefinido sólo se aplica las órdenes INSERT subsecuentes. También pueden crearse valores predeterminados para vistas, en el caso en que son insertadas en las declaraciones INSERT antes de que la regla de la vista ON INSERT sea aplicada.
SET/DROP NOT NULL: Cambian si una columna es marcada para permitir valores o rechazar los valores nulos.
SET STATISTICS: Coloca un valor de estadísticas recogidas por columna para una operación ANALIZE subsecuente. El valor puede estar en el rango de 0 a 1000; alternativamente, se usa -1 para revertir el uso del sistema de valores de estadísticas predeterminado.
SET STORAGE: Define el modo de almacenamiento de una columna. Este controla si dicha columna depende de otra tabla suplementaria, y si los datos deben comprimirse o no. PLAIN debe utilizarse para valores de longitud fija como el entero interno no comprimible. MAIN es para datos ligados comprimibles. EXTERNAL es para datos externos no comprimibles, y EXTENDED es para datos externos comprimibles. EXTENDED es el valor predeterminado para todo tipo de datos que lo soportan.
SET WITHOUT OIDS: Quita el identificador de columna de la tabla. La remoción de OIDs de una tabla no ocurre inmediatamente. El espacio que ocupa el OID se guardará cuando la fila sea actualizada. Si no se actualiza la fila, el espacio y el valor del OID son guardados indefinidamente. Esta semántica es similar a la del proceso DROP COLUMN.
RENAME: Cambia el nombre de una tabla (o un índice, secuencia, o vista) o el nombre de una columna individual en la tabla. No hay efecto en el almacenamiento de datos.
ADD table_constraint: Añade un nuevo constraint a la tabla usando la misma sintaxis que CREATE TABLE.
DROP CONSTRAINT: Elimina los constraints de una tabla. Actualmente, los constraints de las tablas no requieren tener nombres únicos, entonces puede haber más de un constraint identificados los cuales serán eliminados.
OWNER: Cambia el propietario de una tabla, índice, secuencia, o vista de un usuario especificado. CLUSTER: Marca una tabla para futuras operaciones CLUSTER. La clausula ALTER TABLE solo puede ser ejecutada por el propietario de la tabla, mientras la clausula ALTER TABLE OWNER, sólo puede ser ejecutada por un superusuario.
Sintaxis: ALTER TABLE [ ONLY ] name [ * ] ADD [ COLUMN ] column type [ column_constraint [ ... ] ] ALTER TABLE [ ONLY ] name [ * ] DROP [ COLUM COLUMN N ] column [ RESTRICT | CASCADE ] ALTER TABLE [ ONLY ] name [ * ] ALTER [ COLUMN ] column { SET DEFAULT expression | DROP DEFAULT } ALTER TABLE [ ONLY ] name [ * ] ALTER [ COLUMN ] column { SET | DROP } NOT NULL ALTER TABLE [ ONLY ] name [ * ] ALTER [ COLUMN ] column SET STATISTICS integer ALTER TABLE [ ONLY ] name [ * ] ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ALTER TABLE [ ONLY ] name [ * ] SET WITHOUT OIDS ALTER TABLE [ ONLY ] name [ * ] RENAME [ COLUMN ] column TO new_column ALTER TABLE name RENAME TO new_name ALTER TABLE [ ONLY ] name [ * ] ADD table_constraint ALTER TABLE [ ONLY ] name [ * ] DROP CONSTRAINT constraint_name [ RESTRICT | CASCADE ] ALTER TABLE name OWNER TO new_owner ALTER TABLE name CLUSTER ON index_name
Donde:
name: Nombre de una tabla existente para alterarla. Si se desea alterar una sola tabla, se debe utilizar la clausula ONLY. Caso contrario, se alterarán la tabla y todas las tablas que desciendan de ésta. column: Nombre de una columna ya existente o nueva. type: Tipo de dato para la nueva columna. new_column : Nombre nuevo para una columna existente. new_name: Nombre nuevo para la tabla. table_constraint: Nuevo constraint para la tabla. constraint_name: Nombre de un constraint existente para eliminarlo. new_owner: Nombre del usuario o del nuevo propietario de la tabla. index_name: Nombre del índice que indica la tabla marcada para CLUSTER. CASCADE: Elimina automáticamente objetos que dependen de una columna o constraint eliminado. RESTRICT: Negación a eliminar la columna o constraint si hay objetos dependientes. Esta es una conducta predeterminada.
Notas: La palabra clave columna puede ser omitida. En la implementación actual de las clausulas ADD COLUMN, default y NOT NULL para la nueva columna no son soportadas. La nueva columna siempre entra teniendo todos los valores nulos. Se puede utilizar la forma SET DEFAULT de ALTER TABLE para poner el valor predeterminado después. Para marcar la columna como no nula, se utiliza la forma SET NOT NULL, después de haber ingresado los valores no nulos el las flas de la columna. La forma DROP COLUMN no elimina la columna físicamente, simplemente la hace invisible para las operaciones de SQL. Subsecuentemente las operaciones INSERT y UPDATE podrían almacenar valores nulos en esta columna. Así, eliminar una columna es fácil pero no reduce inmediatamente el tamaño en disco de la tabla, ya que el espacio ocupado por la tabla eliminada no puede reutilizarse a menos que se realice una operación UPDATE sobre las flas. Si una tabla tiene tablas descendientes, no es permitido añadir o renombrar una columna en la tabla padre sin hacer lo mismo en las descendientes. Es decir, ALTER TABLE ONLY será rechazado. Esto asegura que las tablas descendientes siempre estén emparejadas a la tabla padre.
Una operación recursiva DROP COLUMN sólo quitará la columna de una tabla descendiente, si ésta no hereda esa columna de cualquier padre. Una operación no recursiva DROP COLUMN (ALTER TABLE ONLY… DROP COLUMN) nunca remueve columnas descendientes, en cambio las marca como herencia.
Ejemplos:
Añadir una nueva columna del tipo varchar a la tabla EMPLEADOS:
ALTER TABLE EMPLEADOS ADD EMPLEADOS ADD COLUMN Direccion varchar (30); (30);
Eliminar una columna de una tabla:
ALTER TABLE EMPLEADOS DROP COLUMN Direccion RESTRICT RESTRICT;;
Renombrar una columna existente de la tabla DETALLE_ORDENES
ALTER TABLE DETALLE_ORDENES RENAME COLUMN CANTIDAD TO QUANTITY;
CONSULTAS SQL
CONSULTAS SQL WHERE: En este ejemplo sólo se devuelven las flas de la tabla Productos que suministra el proveedor de código 10 y el producto que entrega es ‘SALCHICHAS’ SELECT descripcion, preciounit AS preciounit AS “Precio unitario” FROM productos WHERE proveedorid = 10 AND descripcion LIKE ‘SALCHICHAS %’ Operadores de comparación (como =, < >, < y >). -- Muestre los productos que tengan un precio mayor a 2.60 SELECT descripcion, preciounit AS preciounit AS “Precio unitario” FROM productos WHERE preciounit >2.60
Intervalos (BETWEEN y NOT BETWEEN).
-- Muestre los productos con precios entre 9 y 15 SELECT descripcion, preciounit AS preciounit AS “Precio unitario” FROM productos WHERE preciounit BETWEEN 9 AND 15 ORDER BY preciounit -- Muestre los productos con precios fuera de 9 y 15 SELECT descripcion, preciounit AS preciounit AS “Precio unitario” FROM productos WHERE preciounit NOT BETWEEN 9 AND 15 ORDER BY preciounit
Listas (IN, NOT IN).
-- Muestre las categorías que sean CARNICOS, LACTEOS o MEDICINAS SELECT * FROM categorias WHERE nombrecat IN (‘CARNICOS’,’LACTEOS’,’MEDICINAS’)
Coincidencia de modelos (LIKE y NOT LIKE).
-- Muestre los empleados cuyo nombre empiece con J SELECT * FROM empleados WHERE nombre LIKE ‘J%’ -- Muestre los empleados cuyo nombre no empiece con J SELECT * FROM empleados WHERE nombre NOT LIKE ‘J%’
Valores NULL (ISNULL y NOTNULL).
--Muestra las órdenes donde no existe descuento SELECT * FROM ordenes WHERE descuento ISNULL --Muestra las órdenes donde existe descuento SELECT * FROM ordenes WHERE descuento NOTNULL
FUNCIONES
FUNCIONES EL LENGUAJE DE FUNCIONES PL/pgSQL
Una de las características de PostgreSQL es que permite al usuario o administrador de la base de datos escribir sus propias funciones dentro de la base de datos, estas funciones se almacenan y ejecutan desde el proceso de base de datos y no desde la aplicación del cliente. PostgreSQL permite en este sentido crear sus funciones de usuario o comúnmente llamadas “PROCEDIMIENTOS ALMACENADOS” no solo en lenguaje SQL que es un lenguaje que carece de estructuras de control como IF, WHILE, FOR y otros, sino que permite definir un lenguaje propio y extenderlo a la base de datos, es así como están disponibles para Postgre los siguientes lenguajes: C, Perl, Phyton, PHP entre otros. Estos lenguajes deben ser instalados en la base de datos previamente antes de ser utilizados. Sin embargo, también existe un lenguaje propio de PostgreSQL, denominado “PL/pgsql”, que posee estructuras de control y permite aprovechar toda la potencia de SQL para crear nuestras propias funciones, es este lenguaje de funciones en el que concentraremos este manual.
VENTAJAS DEL USO DE FUNCIONES
Desde el momento momento en que podemos crear nuestras propias funciones en la base de datos, obtenemos una serie de ventajas en nuestras aplicaciones, es así como podemos mencionar las siguientes ventajas del uso de funciones definidas por el usuario.
Se pueden crear funciones para ser ejecutadas en algún evento de la base de datos. Al borrar, modificar o insertar datos por ejemplo.
Se pueden añadir estructuras de control al lenguaje SQL, podemos ahora definir ciclos de ejecución como FOR y WHILE que nos permitan recorrer variables de tipo array, tablas u otras estructuras.
Las funciones nos permiten realizar cálculos complejos, así ampliamos las funciones predefinidas por el motor de base de datos y construir funciones a medida de nuestras necesidades o las del cliente/empresa.
Se pueden heredar todos los tipos definidos por el usuario, las funciones y los operadores, esta característica nos permite tomar variables de tipo registro o fila (RECORD o ROW) y permitirnos procesar sus datos.
Nos aporta una ejecución fable para el servidor, es decir, podemos estar seguros de de el conjunto de instrucciones de la función definida se ejecutará, sin importar si ocurren problemas en el cliente, en una conexión o enlace, una vez solicitada la función esta se ejecuta en modo seguro y protegido en el servidor.
NOTA: Es un lenguaje fácil de usar, pues extiende de una manera simplista pero a la vez potente el lenguaje SQL.
DESCRIPCION DEL LENGUAJE ESTRUCTURA DE PL/pgSQL
El lenguaje PL/pgSQL no es sensible al reconocimiento de mayúsculas. Todas las palabras clave e identificadores pueden usarse en cualquier mescla de mayúsculas y minúsculas, sin embargo, de preferencia, el nombre de tablas y de registros utilice según definió en la base de datos. PL/pgSQL es un lenguaje orientado a bloques. la estructura básica del lenguaje se define de la siguiente manera : CREATE [OR REPLACE] FUNCTION ([lista de parámetros]) RETURNS AS AS $$ DECLARE BEGIN END; $$ $$LANGUAGE LANGUAGE ‘plpgsql plpgsql’;’;
DEFINIENDO LOS PARAMETROS DE LAS FUNCIONES Una de las características de PL/pgSQL es que no es necesario definir los nombres de variables en la función, sólo es necesario definir si tipo, de de esta manera tenemos que una función puede ser definida en términos de parámetros de entrada y salida de la siguiente forma : FUNCTION suma ( real , real ) RETURNS real AS real AS ‘ /*...resto de la funcion... */ En este ejemplo definimos la función “suma” con dos parámetros de entrada de tipo real y también la salida o RETURNS de tipo real. Cabe notar que podemos utilizar como parámetros todos los tipos usados por PostgreSQL, es decir: INTEGER, DATE, TIME, VARCHAR, CHAR, TIMESTAMP, REAL,
TEXT y muchos otros, e inclusive tipos definidos por el usuario por medio de la instrucción CREATE TYPE.
DEFINICION DE VARIABLES LOCALES O DE FUNCION Como explicamos anteriormente, las variables locales son definidas dentro de la sección DECLARE de la función, de forma muy similar a otros lenguajes podemos definir variables, por ejemplo: DECLARE contador integer contador integer == 0; cadena varchar ; fecha date date;; continuar bool continuar bool;; suma real real;; En este caso definimos una serie de variables con su tipo de dato, también, podemos definir una variable y asignarle un valor en la misma línea de código de la definición de la variable (note la variable “contador” inicializada en cero). FUNCTION suma (real FUNCTION (real,, real ) RETURNS real AS real AS ‘ DECLARE numero_1 alias for $1; for $1; numero_2 alias for $2; for $2; valor_total real real;; /*...resto de la funcion... */ Continuando nuestra función suma, podemos apreciar que en la definición de variables usamos una nomenclatura especial para asignar nombres de variable a los parámetros de entrada, de hecho, si no hace esta redefinición, puede los parámetros asignando “$” y el número indicador en la lista de parámetros a cada variable de parámetro, por ejemplo: valor_total = $1 + $2;
ASIGNACION DE LAS SENTENCIAS DE PL/pgSQL Una vez definidos los parámetros de entrada/salida, y también nuestras variables locales, podemos comenzar a trabajar en nuestra función en la sección BEGIN .... END; Las asignaciones de valores se realizan de la misma forma que en PASCAL, es decir, utilizando = como operador de asignación y punto y coma al final de la línea, ejemplo:
FUNCTION suma (real (real,, real ) RETURNS real AS real AS ‘ DECLARE numero_1 alias for $1; for $1; numero_2 alias for $2; for $2; valor_total real; BEGIN valor_total = numero_1 + numero_2; numero_1 = numero_1 * numero_2; /*...resto de la funcion... */ Como vemos en este ejemplo la asignación de valores es prácticamente igual a PASCAL.
RETORNANDO EL UN VALOR COMO FUNCION Finalmente una vez procesados nuestros valores debemos retornar algún valor (pues ese es la esencia de la función), este retorno de valores también se realiza dentro de la sección BEGIN de la función, pero utilizando la siguiente forma básica : /*...resto de la funcion... */ RETURN ; /*...resto de la funcion... */ Ejemplo completo de la función SUMA: FUNCTION suma ( real , real ) RETURNS real AS real AS ‘ DECLARE numero_1 alias for $1; for $1; numero_2 alias for $2; for $2; valor_total real; BEGIN valor_total = numero_1 + numero_2; RETURN valor_total; END;; END $$ $$LANGUAGE LANGUAGE ‘plpgsql plpgsql’;’; Poco a poco hemos ido creando esta función, ahora está terminada y lista para ser utilizada.
ASIGNANDO COMENTARIOS Si así lo necesitas, puedes documentar tus funciones usando los operadores /* ... */ para crear un comentario de bloque multilinea o bien -- para un comentario de línea sencilla, Ejemplo : /*...resto de la función... */ /* Este es un comentario que utiliza multiples líneas de comentario */ -- Este es un comentario en una sola línea /*...resto de la función... */
UTILIZANDO SENTENCIAS DE CONTROL Podemos utilizar sentencias de control para escribir nuestros programas y permitir que sigan un algoritmo no lineal, para ello, contamos básicamente con las siguientes estructuras: LOOP EXIT IF, ELSE FOR WHILE
SENTENCIA DE CICLO LOOP Esta sentencia nos permite efectuar un ciclo, su estructura básica es: /*...resto de la funcion... */ LOOP ...sentencias a ejecutar en el ciclo... END LOOP /*...resto de la funcion... */
SENTENCIA DE SALIDA EXIT: Cuando usamos un ciclo LOOP, es necesario darle una salida para que este mismo termine, la sentencia EXIT nos permite finalizar el LOOP y continuar en la sentencia siguiente a la salida de éste, generalmente, EXIT está acompañado con la sentencia IF, por ejemplo
LOOP /*...resto de la funcion... */ contador = contador + 1; IF contador >= 10 THEN EXIT;; -- salida del loop cuando sea mayor o igual que 10 EXIT END IF; IF; END LOOP /*...resto de la funcion... */
SENTENCIAS IF, ELSE: Podemos efectuar operaciones de comparación con las sentencias IF, ELSE, los operadores de comparación son los siguientes: < menor que... > mayor que... <> distinto a... <= menor o igual que... >= mayor o igual que... = igual que... OR o... AND y...
Ejemplo: /*...resto de la funcion... */ IF >= 10 or THEN or THEN RETURN true; ELSE RETURN false; END IF; IF; /*...resto de la funcion... */
SENTENCIA DE CICLO FOR Existen dos tipos de ciclos FOR, el primero tiene que ver claramente con los ciclos numéricos comunes, es decir, lo que comúnmente se usa para efectuar repeticiones, y por otra parte, tenemos
un ciclo FOR que nos permite recorrer tablas y procesar sus datos, esta segunda está ligada a sentencias SQL, veamos entonces como se utiliza la sentencia FOR. CASO 1: SENTENCIA FOR DE PROCESO CICLICO NUMERICO
FOR IN .. LOOP ... SENTENCIAS A EJECUTAR DENTRO DEL CICLO FOR... END LOOP; LOOP; o bien puede usar el FOR de forma inversa FOR REVERSE .. LOOP ... SENTENCIAS A EJECUTAR DENTRO DEL CICLO FOR... END LOOP; LOOP; Ejemplo: /*...resto de la funcion... */ FOR inc IN 1..10 LOOP factorial = factorial * inc; END LOOP; LOOP; RETURN factorial; /*...resto de la funcion... */ CASO 2: SENTENCIA FOR APLICADA A PROCESOS DE REGISTROS SQL
FOR IN LOOP ... SENTENCIAS A EJECUTAR DENTRO DEL CICLO FOR... END LOOP; Ejemplo: /*...resto de la funcion... */ DECLARE registro RECORD RECORD;; BEGIN FOR registro IN SELECT * FROM productos LOOP stock = registro.sock_actual + 100; /*... otras sentencias... */ END LOOP; /*...resto de la funcion... */
Note que para utilizar esta sentencia FOR debemos declarar una variable de tipo RECORD o registro. RECORD es una palabra reservada para estos casos, y no posee una estructura definida pues no ha sido asignada a ninguna tabla, este tipo de dato nos permite recorrer la tabla de productos y obtener sus valores por medio de esta variable.
SENTENCIA DE CICLO CONDICIONAL WHILE La sentencia WHILE se ejecuta de forma muy similar a otros lenguajes de programación, su estructura es la siguiente: WHILE LOOP ... SENTENCIAS A EJECUTAR DENTRO DEL CICLO WHILE... END LOOP; Ejemplo: /*...resto de la funcion... */ WHILE inc <= 10 LOOP factorial = factorial * inc; END LOOP; LOOP; RETURN factorial; /*...resto de la funcion...*/ Este código funciona igual al descrito en el ejemplo del ciclo FOR.
EJEMPLOS COMBINANDO PL/pgSQL con SQL Una de las características que hacen de este lenguaje una herramienta poderosa, es la capacidad de interactuar con SQL, obtener datos y procesarlos, la forma de utilizar SQL es tan familiar que solo basta realizar los comandos SQL para ejecutar o procesar los datos necesarios. Ejemplo 1: Buscar un cliente y retornar si existe o no CREATE OR REPLACE FUNCTION buscar_cliente (varchar (varchar ) RETURNS bool AS ‘ DECLARE ruc_buscar alias for $1; registro clientes%ROWTYPE clientes%ROWTYPE;; /* Aqui se defne la variable registro del tipo FILA de clientes indicando la tabla, el simbolo % y luego la palabra reservada ROWTYPE */
BEGIN SELECT INTO registro * FROM clientes WHERE ruc_cliente = ruc_buscar; IF FOUND THEN RETURN true; END IF; IF; RETURN false; END;; END $$ $$LANGUAGE LANGUAGE ‘plpgsql plpgsql’;’; Como podemos apreciar, este código busca un cliente en la tabla de clientes, si existe o se encuentra el cliente, la función devolverá un valor verdadero (true), de lo contrario, ésta devolverá falso (false). Ejemplo 2: Buscar un producto y actualiza su precio según porcentaje CREATE OR REPLACE FUNCTION actualizar_producto (varchar (varchar , varchar, real real)) RETURNS bool AS bool AS ‘ DECLARE producto ALIAS producto ALIAS FOR $1; porcentaje ALIAS porcentaje ALIAS FOR $2; categoria ALIAS categoria ALIAS FOR $3; registro productos%ROWTYPE productos%ROWTYPE;; BEGIN SELECT INTO registro * FROM productos WHERE productoid = producto; IF FOUND THEN UPDATE productos SET PRECIOUNIT = PRECIOUNIT + (PRECIOUNIT * porcentaje) WHERE categoriaid = categoria; RETURN true; END IF; IF; RETURN false; END;; END $$ $$LANGUAGE LANGUAGE ‘plpgsql’ plpgsql’;;
Este código busca el producto, obtiene los datos necesarios y actualiza el registro.
Ejemplo 3: Incrementar valores según el porcentaje de IVA CREATE OR REPLACE FUNCTION inc_iva (integer, real) RETURNS integer AS AS ‘
DECLARE valor ALIAS ALIAS FOR $1; iva ALIAS iva ALIAS FOR $2; total real; BEGIN total = valor + (valor * iva); RETURN total; RETURN;; RETURN END;; END $$ $$LANGUAGE LANGUAGE ‘plpgsql plpgsql’;’; Esta función no actualiza realmente los datos de la tabla, solamente los procesa parámetros, de tal manera que si los datos ingresados fueran los de una tabla devolvería el valor mas IVA.
LLAMANDO A LAS FUNCIONES Hasta ahora hemos descrito a grandes rasgos como construir fácilmente funciones de usuario o procedimientos almacenados, pero todavía no los hemos invocado, a continuación ejemplos de llamadas a los procedimientos almacenados o funciones en PL/pgSQL: Este ejemplo retornará true si el cliente SELECT buscar_ existe o fase si no se encuentra en la tabla cliente(‘1710185883’); de clientes. El producto “PRO-0540” actualizará su SELECT actualizar_producto(‘PROprecio en un 3% más. 0540’,0.03) Sumará 2 números y retornara su valor SELECT suma(5.45, 10.452) Retornará si el RUT está validado o no pero SELECT valida_ruc (ruc_cliente), analizará todos los registros de la tabla. nombres, apellidos FROM clientes Esta sentencia utiliza la funcion que SELECT incrementa los precios con IVA y renombra codigo,nombre, descripcion, la salida de la funcion inc_iva a “precio_ inc_iva(precio_venta,0.18) AS inc_iva(precio_venta,0.18) AS precio_ iva”. iva FROM productos
Funciones SQL “Funciones SQL” son construcciones definidas por el estándar SQL92, que tiene sintaxis igual que funciones pero que no pueden ser implementadas como simples funciones.
Funciones
Retorna
COALESCE(list)
no-NULO
NU-LLIF(input,value)
input or NULO
CASE WHEN expr THEN expr [...] ELSE expr END
expr
Descripción Descripción retorna el primer valor no-NULO en la lista retorna NULO si input = value retorna la expresión para la primera claúsula verdadera
Ejemplo COALESCE(r”le>, c2 + 5, 0) NULLIF(c1, ’N/A’) CASE WHEN c1 = 1 THEN ’match’ ELSE ’no match’ END
FUNCIONES MATEMÁTICAS Funciones dexp(foat8)
Retorna fooat8 float8
float(int)
float8
float4(int)
foat4
integer(float)
int
Descripción Descripción redimensiona al exponente especificado redimensiona un numero al exponente especificado convierte un entero a punto convierte un entero a punto convierte un punto flotante a punto
Ejemplo dexp(2.0) dpow(2.0, 16.0)
float(2) foat4(2) integer(2.0)
FUNCIONES STRING SQL92 define funciones de texto con sintaxis específica. Algunas son implementadas usando otras funciones Postgres Los tipos de Texto soportados para SQL92 son char, varchar, y text.
Funciones char_ characlower(string) octet_ position(string in substring(string upper(text)
Retorna int4 ter_ int4 string int4 int4 string string oth] text
Descripción Descripción longitud del texto longitud del texto convierte el texto almacena el octet_ localiza la position extrae un substring borra caracteres convierte un texto
Ejemplo char_ char_ lower(’TOM’) octet_ (’o’) in (’Tom’) trim(both ’x’ )from upper(’tom’)
La mayoría de funciones de texto están disponibles para tipos text, varchar() y char().Algunas son usadas internamente para implementar las funciones de texto SQL92 descritas arriba.
Funciones
Retorna
char(text)
Char
char(varchar)
char
initcap(text)
text
pad(text,int,text)
text
ltrim(text,text) textpos(text,text) rpad(text,int,text)
text text text
rtrim(text,text)
text text
text(char)
text
text(varchar)
text
translate(text,from,to)
text
varchar(char)
varchar
Descripción Descripción convierte un texto a tipo char convierte un varchar a tipo char primera letra de cada palabra a initcap relleno de caracteres por lpad recorte de caracteres localiza un subtexto relleno de caracteres por rpad recorte de caracteres extrae el subtexto especificado convierte char a tipo text convierte varchar a tipo text convierte character a string translate convierte char a tipo varchar
Ejemplo char(’text string’) (varchar ’varchar string’) (’thomas’) (’hi’,4,’??’)
position(’high’,’ig’) (’hi’,4,’x’)
substr(’hi there’,3,5) text(’char string’) (varchar ’varchar string’) (’12345’) varchar (’char string’)
varchar(text)
varchar
convierte text a tipo varchar (’text varchar string’)
La mayoría de funciones explícitamente defI8nidas para texto trabajarán para argumentos char () y varchar().
FUNCIONES DE FECHA/HORA Las funciones de Fecha/Hora provee un poderoso conjunto de herramientas para manipular varios tipos Date/Time.
Funciones
Retorno abstime timespan )
datetime(date)
datetime
da- te_
float8
da- te_
float8
da- te_
datetime
isfnite(abstime) isfnite(datetime) isfnite(timespan) reltime(timespan)
bool bool bool reltime
timespan(reltime)
timespan timespan
Descripción Descripción
Ejemplo
convierte a abstime preserva meses y age (’now’,’1957años 0613’::datetime) convierte date datetime(’1998a datetime 0224’::datetime, porción de fecha da- te_ part (’dow’,’now’:: datetime porción de hora date_ part(’hour’,’4 hrs 3 mins’::timespan) fecha truncada da- te_ trunc(’month’,’now un tiempo finito? isfniuna hora finita? isfniuna hora finita? isfnite(’4 convierte a reltime(’4 reltime convierte a timespan(’4 timespan
Para las funciones date_part and date_trunc, los argumentos pueden ser ‘year’, ‘month’, ‘day’, ‘hour’, ‘minute’, y ‘second’, así como las mas especializadas cantidades ‘decade’, ‘century’, ‘millenium’, ‘millisecond’, y ‘microsecond’. date_part permite ‘dow’ para retornar el día de la semana ‘epoch’ para retornar los segundos desde 1970 (para datetime) o ’epoch’ para retornar el total de segundos transcurridos (para timespan).
FUNCIONES DE FORMATO Las funciones de formato proveen un poderoso conjunto de herramientas para convertir varios datetypes (date/time, int, float, numeric) a texto formateado y convertir de texto formateado a su datetypes original.
Funciones
Retorno
to_char(datetime, text) to_char(timestamp,
text
to_char(int, text)
text
to_char(float, text) to_ char(numeric,
text
to_datetime(text, text)
datetime
to_date(text, text) to_ timestamp(text, text) to_number(text, text)
date
text
text
date numeric
Descripción Descripción convierte datetime a string convierte timestamp a to_char convierte int4/int8 a string convierte foat4/ float8 a string convierte numeric a string convierte string a datetime convierte string a date convierte string a timestamp
Ejemplo to_ to_char( now(), ’HH12:MI:SS’) to_char(125, ’999’) to_char(125.8, ’999D9’) to_char(-125.8, ’999D99S’) to_datetime(’05 Dec 2000 13’, DD Mon) to_date(’05 Dec 2000’, ’DD Mon) to_timestamp(’05 Dec 2000’, ’DD Mon)
convierte string a numeric
Para todas las funciones de formato, el segundo argumento es format-picture.
Format-picture HH HH12 MI SS SSSS Y,YYY YYYY YYY YY Y
Descripción hora del día(01-12) hora del día(01-12) minuto (00-59) segundos (00-59) segundos pasados la medianoche(086399) año(4 o mas dígitos) con coma año(4 o mas dígitos) últimos 3 dígitos del año últimos 2 dígitos del año último dígito del año
MONTH Month month MON Mon mon MM DAY Day day DY Dy dy DDD DD D W WW CC J día juliano Q RM
nombre completo del mes(9-letras) todos los caracteres en mayúsculas nombre completo del mes(9letras) - el primer carácter en mayúsculas nombre completo del mes(9-letras) todos los caracteres en minúsculas nombre abreviado del mes(3-letras) -todos los caracteres en mayúsculas nombre abreviado del mes(3-letras) - el primer carácter en mayúsculas nombre abreviado del mes(3-letras) - todos los caracteres en minúsculas mes (01-12) nombre completo del día(9-letters) todos los caracteres en mayúsculas nombre completo del día(9-letters) el primer carácter en mayúsculas nombre completo del día(9-letters) todos los caracteres en minúsculas nombre abreviado del día(3-letters) - todos los caracteres en mayúsculas nombre abreviado del día(3-letters) - el primer carácter en mayúsculas nombre abreviado del día(3-letters) - todos los caracteres en minúsculas día del año(001-366) día del mes(01-31) día de la semana(1-7; SUN=1) semana del mes número de la semana en el año centuria (2-digits) (días desde Enero 1, 4712 BC) Quarter mes en numeral romano(I-XII; I=ENE)
JOINS
JOINS (CRUCES) El siguiente ejemplo muestra como las joins (cruces) se realizan en SQL. Para cruzar tres tablas PRODUCTOS, PROVEEDORES y DETALLE ORDENES a través de sus atributos comunes, formularemos la siguiente instrucción: SELECT pr.nombreprov, p.descripcion, d.cantidad FROM proveedores pr, productos p, detalle_ordenes d WHERE p.productoid = d.productoid AND d.productoid AND pr.proveedorid=p.proveedorid:; En la clausula FROM hemos introducido un alias al nombre para cada relación porque hay atributos con nombre común en las relaciones. Ahora podemos distinguir entre los atributos con nombre común simplificando la adicción de un prefijo al nombre del atributo con el nombre del alias seguido de un punto. La join se calcula de la misma forma, tal como se muestra en Una Inner Join (Una Join Interna). Primero el producto cartesiano PRODUCTOS x PROVEEDORES x DETALLE ORDENES. Ahora seleccionamos únicamente aquellas tuplas que satisfagan las condiciones dadas en la clausula WHERE (es decir, los atributos con nombre común deben ser iguales).
OPERADORES AGREGADOS SQL proporciona operadores agregados (como son AVG, COUNT, SUM, MIN, MAX) MAX) que toman el nombre de un atributo como argumento. El valor del operador agregado se calcula sobre todos los valores de la columna especificada en la tabla completa. Si se especifican grupos en la consulta, el cálculo se hace sólo sobre los valores de cada grupo (vean la siguiente sección). Ejemplo: Si queremos conocer el coste promedio de todos los artículos de la tabla PART, utilizaremos la siguiente consulta: SELECT AVG(preciounit) AVG(preciounit) AS AS “Precio promedio” FROM productos; Si queremos conocer cuántos artículos se recogen en la tabla PART, utilizaremos la instrucción: SELECT COUNT(productoid) COUNT(productoid) FROM productos;
AGREGACIÓN POR GRUPOS SQL nos permite particionar las tuplas de una tabla en grupos. En estas condiciones, los operadores agregados descritos antes pueden aplicarse a los grupos (es decir, el valor del operador agregado no se calculan sobre todos los valores de la columna especificada, sino sobre todos los valores de un grupo. El operador agregado se calcula individualmente para cada grupo). Ejemplo: Si queremos conocer cuántos artículos han sido vendidos por cada proveedor formularemos la consulta: SELECT pr.proveedorid, pr.nombreprov, COUNT (p.productoid) FROM proveedores pr, productos p WHERE pr.proveedorid= p.proveedorid GROUP BY pr.proveedorid, pr.nombreprov;
HAVING La clausula HAVING trabaja de forma muy parecida a la clausula WHERE, y se utiliza para considerar sólo aquellos grupos que satisfagan la cualificación dada en la misma. Las expresiones permitidas en la clausula HAVING deben involucrar funcionen agregadas. Cada expresión que utilice sólo atributos planos deberá recogerse en la clausula WHERE. Por otro lado, toda expresión que involucre funciones agregadas debe aparecer en la clausula HAVING. Ejemplo Si queremos solamente los proveedores que venden más de un artículo, utilizaremos la consulta: SELECT pr.proveedorid, pr.nombreprov, COUNT COUNT(p.productoid) (p.productoid) FROM proveedores pr, productos p WHERE pr.proveedorid= p.proveedorid GROUP BY pr.proveedorid, pr.nombreprov HAVING COUNT(p.productoid) COUNT(p.productoid) >1;
SUBCONSULTAS
SUBCONSULTAS En las clausulas WHERE y HAVING se permite el uso de subconsultas (subselects) en cualquier lugar donde se espere un valor. En este caso, el valor debe derivar de la evaluación previa de la subconsulta.
El uso de subconsultas amplía el poder expresivo de SQL.
Ejemplo: Si queremos conocer los artículos que tienen mayor precio que el producto llamado ’Tornillos’, utilizaremos la consulta: SELECT * FROM productos WHERE preciounit > (SELECT (SELECT preciounit FROM productos WHERE descripcion =’BOTON PARA ASADO’); Cuando revisamos la consulta anterior, podemos ver la palabra clave SELECT dos veces. La primera al principio de la consulta - a la que nos referiremos como la SELECT externa - y la segunda en la clausula WHERE, donde empieza una consulta anidada - nos referiremos a ella como la SELECT interna. Para cada tupla de la SELECT externa, la SELECT interna deberá ser evaluada. Tras cada evaluación, conoceremos el precio de la tupla llamada ‘BOTON PARA ASADO’, y podremos chequear si el precio de la tupla actual es mayor. Si queremos conocer todos los proveedores que no venden ningún producto (por ejemplo, para poderlos eliminar de la base de datos), utilizaremos: SELECT * FROM proveedores p WHERE NOT EXISTS (SELECT * FROM productos pr WHERE pr WHERE pr.proveedorid = p.proveedorid);
UNIÓN, INTERSECC I NTERSECCIÓN, IÓN, EXCEPCIÓN Estas operaciones calculan la unión, la intersección y la diferencia de la teoría de conjuntos de las tuplas derivadas de dos subconsultas. Ejemplo: Union, Intersect, Except
La siguiente consulta es un ejemplo de UNION:
SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘TONY’ UNION SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘JURIS’
Aquí se tiene un ejemplo para INTERSECT:
SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘TONY’ INTERSECT SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘JURIS’
Finalmente, un ejemplo de EXCEPT:
SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘TONY’ EXCEPT SELECT p.nombreprov, p.contacto FROM proveedores p WHERE p.nombreprov= ‘JURIS’
TRANSACCIONES
TRANSACCIONES Las transacciones son un concepto fundamental en todos los sistemas de base de datos, el punto esencial de una transacción es que engloba múltiples operaciones en un solo paso. En PostgreSQL las transacciones se configuran simplemente encerrando en un bloque las operaciones que se desean incluir en la misma, el bloque debe comenzar y terminar con los comandos BEGIN y COMMIT. BEGIN: Comienza una transacción en modo encadenado BEGIN [ WORK | TRANSACTION ] Para comenzar una transacción de usuario: BEGIN WORK; WORK; Entrada: WORK WORK,, TRANSACTION Palabras clave opcionales. No tienen efecto. Salida: BEGIN Esto significa que una nueva transacción ha sido comenzada. NOTICE:: BEGIN NOTICE BEGIN:: already a transaction in progress Esto indica que una transacción ya está en progreso. La transacción en curso no se ve afectada.
Descripción Por defecto, PostgreSQL ejecuta las transacciones en modo no encadenado (también conocido como “autocommit” en otros sistemas de base de datos). En otras palabras, cada estado de usuario es ejecutado en su propia transacción y un commit se ejecuta implícitamente al final del estatuto (si la ejecución fue exitosa, de otro modo se ejecuta un rollback). BEGIN inicia una transacción de usuario en modo encadenado, todos los estados de usuarios después de un comando BEGIN se ejecutaran en una transacción única hasta un explicito COMMIT, ROLLBACK, o aborte la ejecución. Los estados en modo encadenado se ejecutan mucho más rápido, porque la transacción start/commit requiere una actividad significativa de CPU y de disco. La ejecución de múltiples estados dentro de una transacción también es requerida para la consistencia cuando se cambian muchas tablas relacionadas. El nivel de aislamiento por defecto de las transacciones en PostgreSQL es READ COMMITTED, donde las consultas dentro de la transacción solo tienen en cuenta los cambios consolidados antes
de la ejecución de la consulta. Así pues, debes utilizar SET TRANSACTION ISOLATION LEVEL SERIALIZABLE justo después de BEGIN si necesitas aislamiento de transacciones más riguroso. Las consultas del tipo SERIALIZABLE solo tendrán en cuenta los cambios consolidados antes de que la transacción entera comience (realmente, antes de la ejecución del primer estado DML en una transacción serializable). Si la transacción está consolidada, PostgreSQL asegurara que todas las actualizaciones sean hechas o si no que ninguna de ellas lo sea. Las transacciones tienen la propiedad estándar ACID (atómica, consistente, aislada y durable).
COMMIT Realiza la transacción actual COMMIT [ WORK | TRANSACTION ] Para hacer todos los cambios permanentes: COMMIT WORK; WORK; Entrada: WORK WORK,, TRANSACTION Palabra clave opcional. No tiene efecto. Salida: COMMIT Mensaje devuelto si la transacción se realiza con éxito. NOTICE: COMMIT COMMIT:: no transaction in progress Si no hay transacciones en progreso.
Descripción COMMIT realiza la transacción actual. Todos los cambios realizados por la transacción son visibles a las otras transacciones, y se garantiza que se conservan si se produce una caída de la máquina.
ROLLBACK Interrumpe la transacción en curso ROLLBACK [ WORK | TRANSACTION ] Para cancelar todos los cambios: ROLLBACK WORK; WORK; Entrada: Ninguna. Salida: Salida: ABORT
Mensaje devuelto si la operación es exitosa. NOTICE: ROLLBACK ROLLBACK:: no transaction in progress Si no hay transacciones en progreso actualmente.
Descripción ROLLBACK deshace la transacción actual y provoca que todas las modificaciones originadas por la misma sean descartadas. ABORT es un sinónimo de ROLLBACK ROLLBACK.. Estructura de una transacción: BEGIN; BEGIN; UPDATE cuentas SET balance = balance – 100 WHERE nombre = ‘Alice’; … COMMIT;; COMMIT Al momento que se le pasa a PostgreSQL la clausula COMMIT es cuando se escribe en base de datos las actualizaciones u operación que se desea hacer en la misma, si en algún momento no queremos hacer COMMIT de alguna operación (quizás se nota que la cuenta de Alice da un balance negativo) entonces se puede utilizar la clausula ROLLBACK y todas las actualizaciones dentro de la transacción se cancelaran. Si no se desea hacer un rollback completo de la transacción, entonces se pueden definir marcadores (savepoints) hasta los cuales se desea que se regrese en la transacción, Ejemplo: BEGIN; BEGIN; UPDATE cuentas SET balance = balance – 100 WHERE nombre = ‘Alice’; SAVEPOINT marcador1; UPDATE cuentas SET balance = balance + 100 WHERE nombre = ‘Bob’; — se desea descartar la actualizacion para Bob y en vez hacerla para Wally — ROLLBACK TO marcador1; UPDATE cuentas SET balance = balance + 100 WHERE nombre = ‘Wally’; COMMIT;; COMMIT En el ejemplo anterior se vio el uso de Marcadores y Rollbacks, en este caso lo que paso es que se realizo una actualización sobre la cuenta de Bob, pero a ultima instancia se decide que el dinero no se le va a abonar a Bob sino a Wally, entonces se realiza un rollback hasta el marcador llamado marcador1 y se pasa a hacer la actualización en la cuenta de Wally
VISTAS Y REGLAS
VISTAS Y REGLAS VISTAS Se puede ver una vista como una tabla virtual, es decir, una tabla que no existe físicamente en la base de datos, pero aparece al usuario como si existiese. Por contra, cuando hablamos de una tabla base, hay realmente un equivalente almacenado para cada fila en la tabla en algún sitio del almacenamiento físico. Las vistas no tienen datos almacenados propios, distinguibles y físicamente almacenados. En su lugar, el sistema almacena la definición de la vista (es decir, las reglas para acceder a las tablas base físicamente almacenadas para materializar la vista) en algún lugar de los catálogos del sistema (vea System Catalogs). En SQL se utiliza el comando CREATE VIEW para definir una vista. La Sintaxis es: CREATE VIEW view_name AS select_stmt
Donde select_stmt es una instrucción select válida, como se definió en Select. Nótese que select_stmt no se ejecuta cuando se crea la vista. Simplemente se almacena en los catálogos del sistema y se ejecuta cada vez que se realiza una consulta contra la vista. SELECT * FROM categorias WHERE nombrecat = ‘CARNICOS’
REGLAS CREATE RULE - definen una nueva regla de reescritura Sintaxis: CREATE [ OR REPLACE ] RULE nombre AS ON evento TO tabla [ WHERE condicion ] DO [ ALSO | INSTEAD ] { NOTHING | commando | ( commando ; commando ...) }
Descripción CREATE RULE define una nueva norma se aplica a una tabla o vista especificada. CREATE OR REPLACE pronunciarse creará una nueva regla, o cambiará una regla existente del mismo nombre para la misma tabla. El sistema de reglas PostgreSQL permite definir una acción alternativa para llevar a cabo en las inserciones, actualizaciones o supresiones en las tablas de bases de datos. En términos generales, una regla causas comandos adicionales que se ejecutan cuando una orden dada en una tabla dada es ejecutada. Las reglas se utilizan también para implementar las vistas de tabla. Es importante darse cuenta de que una norma es en realidad un mecanismo de transformación de comandos, o macro de comandos. La transformación ocurre antes que la ejecución de los comandos se inicie.
Parámetros
name: El nombre de una norma para crear. Esta debe ser distinta del nombre de cualquier otra norma de la misma tabla. Múltiples reglas sobre la misma mesa y mismo tipo de evento se aplican en el orden del nombre alfabético. event: El evento es uno de SELECT, INSERT, UPDATE o DELETE. table: El nombre (opcional esquema cualificada) de la tabla o vista se aplica la regla. condition: Cualquier expresión condicional SQL (volviendo boolean. La expresión de condición no puede referirse a las tablas, salvo NEW y OLD, y no puede contener funciones de agregado. INSTEAD : indica que los comandos deben ser ejecutados en lugar del comando original. ALSO: indica que los comandos deben ser ejecutados, además de la orden original. command: El comando o comandos que componen la acción de la regla. Comandos válidos son SELECT, INSERT, UPDATE, DELETE o NOTIFY.
Dentro de condición y de comandos, los nombres de tabla especial NEW y OLD pueden ser usados para referirse a los valores en la tabla referenciada. NUEVO es válido en ON INSERT y UPDATE ON normas que se refieren a la nueva fila a insertar o actualizar. OLD es válido en ON y ON UPDATE DELETE normas para hacer referencia a la fila existente se actualiza o eliminado. Es muy importante tener cuidado para evitar reglas circulares.
Ejemplos: CREATE OR REPLACE RULE regla2 AS regla2 AS ON INSERT TO empleados WHERE empleadoid>3 DO NOTHING; NOTHING; CREATE OR REPLACE RULE regla3 AS regla3 AS ON INSERT TO empleados WHERE apellido like ‘NOBOA’ DO NOTHING
PROCEDIMIENTOS ALMACENADOS
PROCEDIMIENTOS PROCEDIMIENTOS ALMACENADOS Un procedimiento almacenado se puede definir como un programa, procedimiento ó función, el cual está almacenado en la base de datos y listo para ser usado. Existen dos ventajas evidentes al utilizar procedimientos almacenados en nuestro sistema:
La ejecución del procedimiento ocurre en el servidor de bases de datos. Esto probablemente aumentará el rendimiento de nuestra aplicación al no tenerse que mandar datos entre el cliente y el servidor, y no tener que procesar resultados intermedios en el cliente para obtener el resultado final.
Al tener la lógica de la aplicación implementada en la base de datos no tendremos que implementarla en los clientes, con el consiguiente ahorro de líneas de código redundante y complejidad.
Podemos definir e instalar un procedimiento en PL/pgSQL de la siguiente manera: CREATE [ OR REPLACE ] FUNCTION nombre_funcion([ [ argmodo ] [ argnombre ] argtipo [, ...] ]) RETURNS tipo AS tipo AS $$ [ DECLARE ] [ declaraciones de variables ] BEGIN codigo END;; END $$ LANGUAGE plpgsql | IMMUTABLE | STABLE | VOLATILE | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | COST execution_cost | ROWS result_rows | SET confguration_parameter { TO value | = value | FROM CURRENT } A continuación vamos a ver algunas de las opciones y valores más importantes.
argmodo : El modo de un argumento puede ser IN, OUT, or INOUT. Por defecto se usa IN si
no se define. argtipo: Los tipos que podemos utilizar son todos los disponibles en PostgreSQL y todos los definidos por el usuario
declaraciones de variables: Las declaraciones de variables se pueden realizar de la siguiente manera ($n = orden de declaración del argumento.): nombre_variable ALIAS nombre_variable ALIAS FOR $n; nombre_variable [ CONSTANT ] tipo [ NOT NULL ] [ { DEFAULT | := } expresion ];
IMMUTABLE | STABLE | VOLATILE:
IMMUTABLE: Indica que la función no puede alterar a la base de datos y que siempre devolverá el mismo resultado, dados los mismos valores como argumentos. Este tipo de funciones no pueden realizar consultas en la base de datos.
STABLE: Indica que la función no puede alterar a la base de datos y que siempre devolverá el mismo resultado en una consulta individual de una tabla, dados los mismos valores como argumentos. El resultado podría cambiar entre sentencias SQL.
VOLATILE: Indica que la función puede devolver diferentes valores, incluso dentro de una consulta individual de una tabla (valor por defecto)
CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT:
CALLED ON NULL INPUT: Indica que la función se ejecutará aunque algunos de los argumentos sean NULL. El usuario tiene la responsabilidad de comprobar si algún argumento es NULL cuando sea necesario tener esto en cuenta. (Valor por defecto) RETURNS NULL ON NULL INPUT / STRICT: Indican que la función no se ejecutará y devolverá el valor NULL si alguno de los argumentos es NULL.
SECURITY INVOKER | SECURITY DEFINER:
SECURITY INVOKER: Indica que la función se ejecutará con los privilegios del usuario que la ejecuta (valor por defecto). SECURITY DEFINER: Indica que la función se ejecutará con los privilegios del usuario que la creo. Ejemplos: Si queremos que cualquier usuario con acceso a la base de datos pueda usarlo sin tener que ser el administrador Postgres, tendremos que utilizar TRUSTED con el comando anterior. CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql;
A continuación creamos nuestro primer procedimiento. (Podemos copiar y pegar en el cliente psql, escribirlo a mano ó usar el editor interno en psql (\e)): CREATE OR REPLACE FUNCTION ejemplo() RETURNS integer AS AS $$ BEGIN RETURN 104; END;; END $$ LANGUAGE plpgsql;
Ahora definimos la función con un argumento:
CREATE OR REPLACE FUNCTION ejemplo(integer) RETURNS integer AS AS $$ BEGIN RETURN $1; END;; END $$ LANGUAGE plpgsql;
Este procedimiento se podría haber escrito también de las siguientes maneras:
CREATE OR REPLACE FUNCTION ejemplo(numero integer) RETURNS integer AS AS $$ BEGIN RETURN numero; END;; END $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION ejemplo(integer) RETURNS integer AS AS $$ DECLARE numero ALIAS numero ALIAS FOR $1; BEGIN RETURN numero; END;; END $$ LANGUAGE plpgsql;
Vamos a empezar a complicar un poco las cosas usando dos argumentos y defniendo algunas variables:
CREATE OR REPLACE FUNCTION ejemplo(integer , integer) RETURNS integer AS AS $$ DECLARE numero1 ALIAS numero1 ALIAS FOR $1; numero2 ALIAS numero2 ALIAS FOR $2; constante CONSTANT integer := 100; resultado integer;
BEGIN resultado := (numero1 * numero2) + constante; RETURN resultado; END;; END $$ LANGUAGE plpgsql;
A continuación vamos a usar una sentencia IF ... THEN en nuestra función:
CREATE OR REPLACE FUNCTION ejemplo_txt(integer , integer) RETURNS text AS text AS $$ DECLARE numero1 ALIAS numero1 ALIAS FOR $1; numero2 ALIAS numero2 ALIAS FOR $2; constante CONSTANT integer := 100; resultado INTEGER INTEGER;; resultado_txt TEXT DEFAULT ‘El resultado es 104’; BEGIN resultado := (numero1 * numero2) + constante; IF resultado <> 104 THEN resultado_txt := ‘El resultado NO es 104’; END IF; IF; RETURN resultado_txt; END;; END $$ LANGUAGE plpgsql;
TRIGGERS
TRIGGER Las diversas funciones proporcionan grandes ventajas al simplificar acciones en la base de datos. Pero estas acciones requieren la intervención de una persona encargada de ejecutar dichas funciones cuando se requiera de su actuación. Los Triggers al contrario son funciones que se ejecutan de forma automática en respuesta a ciertos eventos que ocurren en la base de datos. Un trigger es un tipo especial de procedimiento almacenado que es disparado cuando se intenta modificar los datos que protegen. Un procedimiento almacenado es invocado por el usuario mientras que un trigger lo es por el SQL. CREATE TRIGGER crea un nuevo trigger. El trigger se asociará con la tabla especificada y ejecutará la función especificada function_name cuando ocurra cierto evento. Los triggers pueden ser definidos a ejecutarse antes o después de cualquier operación INSERT, UPDATE O DELETE, una vez por fila modificada o por una declaración del SQL. La función trigger debe ser definida antes de que el propio trigger se cree. Si el trigger se ejecuta antes del evento, el trigger puede saltar la operación de la fila actual, o cambiar la fila a ser insertada (solamente para operaciones INSERT y UPDATE). Si el trigger se ejecuta después del evento, todo cambia, incluyendo los efectos de otros triggers, son visibles al trigger. Un trigger que es marcado FOR EACH ROW (row-level) es llamado una vez por cada fila que modifica la operación. Por ejemplo, una operación DELETE que afecta a 10 filas causaría cualquier ON DELETE triggers en la relación designada a ser llamada 10 veces independientemente, una vez por cada fila borrada. En contraste, un trigger que es marcado marcado FOR EACH STATEMENT (statement-level) (statement-level) sólo se ejecuta una vez para cada operación dada sin tener en cuenta cuantas flas modifica (en particular, una operación que modifica cero filas todavía producirá la ejecución de cualquier FOR EACH STATEMENT trigger). Adicionalmente: Los triggers pueden ser definidos para disparar a un TRUNCATE, aunque solo FOR EACH STATEMENT. También, una definición de trigger puede especificar una condición booleana WHEN, la cual se probará para ver si el trigger se disparará o no. En los triggers de niveles de flas la condición WHEN puede examinar los valores antiguos y/o nuevos de la columna de la fila.
Los triggers de nivel de sentencias pueden también tener condiciones WHEN, aunque el rasgo no es tan útil para ellos ya que la condición no puede referirse a cualquier valor en la tabla. Si se definen múltiples triggers del mismo tipo para el mismo evento, pueden ser disparados alfabéticamente de acuerdo al nombre. SELECT no modifica flas por lo tanto no se pueden crear triggers SELECT. Las reglas y vistas son más apropiadas en estos casos. Para crear un trigger en una tabla, el usuario debe tener el privilegio de crear triggers para esa tabla.
Para eliminar un trigger se debe utilizar la clausula DROP TRIGGER.
Sintáxis:
CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] } ON table [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments )
Donde:
name: Nombre del Nuevo trigger. Este debe ser distinto de cualquier nombre de otro trigger en la misma tabla.
BEFORE, AFTER: Determina si la función es llamada antes o después de un evento. event: Una de INSERT, UPDATE, DELETE o TRUNCATE; este especifica el evento que ocurrirá cuando el trigger dispare. Se pueden utilizar varios eventos utilizando OR.
Para los triggers UPDATE, es posible especificar una lista de columnas utilizando eta sintaxis: UPDATE OF column_name1 [, column_name2 ... ] El trigger disparará solamente si al menos una de las columnas listadas es mencionada como designada a actualizar.
table: Nombre de la tabla para la cual es el trigger.
FOR EACH ROW, FOR EACH STATEMENT: Especifica si el procedimiento del trigger será disparado una vez para todas las flas afectadas por el evento, o solo una vez por cada declaración SQL. Si no se especifica, el valor predeterminado es FOR EACH STATEMENT. condition: Una expresión booleana que determina si la función del trigger se ejecutará realmente. Si WHEN es especificado, la función solo será llamada si la condición retorna verdadero. function_name: Función de usuario declarada para no tomar ningún valor y retornar el tipo de trigger, la cual es ejecutada cuando el trigger dispara. arguments: Una lista opcional de argumentos separados por coma para ser proporcionada a la función cuando el trigger es ejecutado. Los argumentos son cadenas de caracteres constantes. Simples nombres o constantes numéricas pueden ser utilizados también pero pueden ser convertidos en cadenas de caracteres.
Ejemplos: Ejecutar la función check_account_update siempre que una fila de la tabla accounts sea actualizada: CREATE TRIGGER trigger_actualizacion BEFORE UPDATE ON PROVEEDORES FOR EACH ROW EXECUTE PROCEDURE check_proveedores_update();