Está en la página 1de 333

Creación de una base de

datos en postgreSQL
Primero vamos a abrir una
terminar con control+alt+t
Luego cambiar del usuario
actual al usuario postgres

sudo su postgres
Despues ya como usuario
postgres

Createdb taller
Una vez creada la base de
datos, vamos a acceder a ella:

psql taller
Creación de tablas
create table NOMBRETABLA(
NOMBRECAMPO1
TIPODEDATO,
...
NOMBRECAMPON
TIPODEDATO
);
Para ver la información de la
tablas se utiliza el siguiente
comando:
Taller# \d tabla
Para eliminar una tabla
Taller=# DROP TABLE tabla;
Crear la tabla jobs
CREATE TABLE jobs (
job_id serial NOT NULL,
job_title varchar(255) NOT NULL,
min_salary integer NOT NULL,
max_salary integer NOT NULL,
PRIMARY KEY (job_id));
Inserte datos el la tabla jobs
INSERT INTO jobs (job_title,
min_salary, max_salary)
VALUES
('Gerente', 10000, 11000);
create table editoriales(
codigo serial,
nombre varchar(30),
primary key (codigo) );
create table libros (
codigo serial,
titulo varchar(40),
autor varchar(30),
codigoeditorial smallint,
primary key(codigo) );
insert into editoriales(nombre) values('Planeta');
insert into editoriales(nombre) values('Emece');
insert into editoriales(nombre) values('Paidos');
insert into editoriales(nombre) values('Siglo XXI');
insert into libros(titulo,autor,editorial)
values('Uno','Richard Bach',1);
insert into libros(titulo,autor,editorial)
values('Ilusiones','Richard Bach',1);
insert into libros(titulo,autor,editorial)
values('Puente al infinito','Richard Bach',2);
Realizar una consulta que
obtenga el nombre de las
editoriales que han publicado
libros del autor "Richard
Bach":
select nombre
from editoriales
where codigo in
(select codigoeditorial
from libros
where autor='Richard
Bach');
SUBCONSULTAS
Una subconsulta (subquery) es
una sentencia "select" anidada en
otra sentencia "select", "insert",
"update" o "delete" (o en otra
subconsulta).
Las subconsultas se emplean
cuando una consulta es muy
compleja, entonces se la divide en
varios pasos lógicos y se obtiene
el resultado con una única
instrucción y cuando la consulta
depende de los resultados de otra
consulta.
Las subconsultas se DEBEN
incluir entre paréntesis.

Puede haber subconsultas


dentro de subconsultas.
Se pueden emplear
subconsultas:

- En lugar de una expresión,


siempre que devuelvan un
solo valor o una lista de
valores.
- Que retornen un conjunto de
registros de varios campos en
lugar de una tabla o para
obtener el mismo resultado
que una combinación (join).
Hay tres tipos básicos de
subconsultas:

1. las que retornan un solo


valor escalar que se utiliza con
un operador de comparación o
en lugar de una expresión.
2. las que retornan una lista
de valores, se combinan con
"in", o los operadores "any",
"some" y "all".
3. los que prueban la
existencia con "exists".
Ejercicio:
Agregar a la tabla libros el
campo precio de tipo numeric
(5,2) y actualizar el precio de
cada libro.
ALTER TABLE libros ADD
precio numeric (5,2);
update libros set
precio=120.23
where codigo=2;
Elaborar una consulta que me
obtenga el precio de un libro y
la diferencia de este precio
con el precio más alto.
select titulo,precio,
precio-(select max(precio)
from libros) as “Diferencia”
from libros
where titulo='Uno';
Realizar una consulta que
obtenga el título, autor y
precio del libro más costoso:
select titulo,autor, precio
from libros
where precio=
(select max(precio) from
libros);
Subconsultas de tipo in
Se vio que una subconsulta
puede reemplazar una
expresión. Dicha subconsulta
debe devolver un valor escalar
o una lista de valores de un
campo.
las subconsultas que retornan
una lista de valores
reemplazan a una expresión
en una cláusula "where" que
contiene la palabra clave "in".
El resultado de una
subconsulta con "in" o ("not
in") es una lista. Luego que la
subconsulta retorna
resultados, la consulta exterior
los usa.
La sintaxis básica es la
siguiente:

...where EXPRESION in
(SUBCONSULTA);
Podemos buscar las
editoriales que no han
publicado libros de "Richard
Bach":
select nombre
from editoriales
where codigo not in
(select codigoeditorial
from libros
where autor='Richard
Bach');
Ejercicio:
Una empresa tiene registrados
sus clientes en una tabla
llamada "clientes", también
tiene una tabla "ciudades"
donde registra los nombres de
las ciudades.
1- Cree la tabla "clientes"
create table clientes (
codigo_cliente serial,
nombre_cliente varchar(30),
domicilio varchar(30),
codigo_ciudad smallint not
null, primary
key(codigo_cliente)
);
2.-Cree la tabla ciudades:
create table ciudades(
codigo_ciudad serial,
nombre_ciudad varchar(20),
primary key (codigo_ciudad)
);
insert into ciudades (nombre_ciudad)
values('Cordoba'),('Cruz del Eje'),('Carlos Paz'),
('La Falda'),('Villa Maria');
insert into
clientes(nombre,domicilio,codigociudad)
values ('Lopez Marcos','Colon 111',1),
('Lopez Hector','San Martin 222',1),
('Perez Ana','San Martin 333',2),
('Garcia Juan','Rivadavia 444',3);
insert into
clientes(nombre,domicilio,codigociudad)
values ('Perez Luis','Sarmiento 555',3),
('Gomez Ines','San Martin 666',4),('Torres
Fabiola','Alem 777',5),('Garcia Luis','Sucre
888',5);
Necesitamos conocer los
nombres de las ciudades de
aquellos clientes cuyo
domicilio es en calle
"San Martin", empleando
subconsulta.
select nombre
from ciudades
where codigo in
(select codigociudad
from clientes
where domicilio like 'San
Martin %');
Obtenga los nombre de las
ciudades de los clientes cuyo
apellido no comienza con una
letra específica, empleando
subconsulta.
COMBINACIONES (JOINS)
Por medio del operador
combinación (JOIN) podemos
combinar dos relaciones o
tablas segun una condición
para obtener tuplas
compuestas por atributos de
las dos relaciones
combinadas.
En el lenguaje SQL existen
diferentes maneras de
combinar dos relaciones o
tablas.
Combinaciones internas
(R INNER JOIN S): Un INNER
JOIN entre dos relaciones R y S,
es el resultado que se obtiene
después de aplicar al producto
cartesiano de las dos relaciones R
y S, una condición para acotar
dicho producto.
Un join es una operación que
relaciona dos o más tablas
para obtener un resultado que
incluya datos (campos y
registros) de ambas; las tablas
participantes se combinan
según los campos comunes a
ambas tablas.
La sintaxis básica es la
siguiente:

select CAMPOS
from TABLA1
inner join TABLA2
on CONDICIONdeCOMBINACION;
Ejemplos:
select * from libros inner join
editoriales on
codigo_editorial=editoriales.co
digo_editorial;
select l.*, e.nombre_editorial
from libros as l inner join
editoriales as e on
l.codigo_editorial=e.codigo_ed
itorial where
e.codigo_editorial=2;
Analicemos la consulta
anterior.

- especificamos los campos


que aparecerán en el
resultado en la lista de
selección;
- indicamos el nombre de la tabla
luego del "from" ("libros");

- combinamos esa tabla con "inner


join" y el nombre de la otra tabla
("editoriales"); se especifica qué
tablas se van a combinar y cómo;
-cuando se combina
información de varias tablas,
es necesario especificar qué
registro de una tabla se
combinará con qué registro de
la otra tabla, con "on".
Se debe especificar la
condición para enlazarlas, es
decir, el campo por el cual se
combinarán, que tienen en
común.
"on" hace coincidir registros de
ambas tablas basándose en el
valor de tal campo, en el ejemplo,
el campo "codigo_editorial" de
"libros" y el campo
"codigo_editorial" de "editoriales"
son los que enlazarán ambas
tablas.
Se emplean campos
comunes, que deben tener
tipos de datos iguales o
similares.
La condición de combinación,
es decir, el o los campos por
los que se van a combinar
(parte "on"), se especifica
según las claves primarias y
externas.
Si una de las tablas tiene clave
primaria compuesta, al combinarla
con la otra, en la cláusula "on" se
debe hacer referencia a la clave
completa, es decir, la condición
referenciará a todos los campos
clave que identifican al registro.
Se emplea este tipo de
combinación para encontrar
registros de la primera tabla
que se correspondan con los
registros de la otra, es decir,
que cumplan la condición del
"on".
Si un valor de la primera tabla
no se encuentra en la
segunda tabla, el registro no
aparece.
select
l.codigo,titulo,autor,nombre
from libros as l
Inner join editoriales as e
on
l.codigo_editorial=e.codigo_ed
itorial;
Combinación externa
Vimos que una combinación
interna (inner join) encuentra
registros de la primera tabla
que se correspondan con los
registros de la segunda,
es decir, que cumplan la
condición del "on" y si un valor
de la primera tabla no se
encuentra en la segunda
tabla, el registro no aparece.
Si queremos saber qué
registros de una tabla NO
encuentran correspondencia
en la otra, es decir, no existe
valor coincidente en la
segunda, necesitamos otro
tipo de combinación, "outer
join" (combinación externa).
Las combinaciones externas
combinan registros de dos
tablas que cumplen la
condición, más los registros
de la segunda tabla que no la
cumplen;
es decir, muestran todos los
registros de las tablas
relacionadas, aún cuando no
haya valores coincidentes
entre ellas.
Hay tres tipos de
combinaciones externas: "left
outer join", "right outer join" y
"full outer join"; se pueden
abreviar con "left join", "right
join" y "full join"
respectivamente.
Se emplea una combinación
externa izquierda para mostrar
todos los registros de la tabla de
la izquierda. Si no encuentra
coincidencia con la tabla de la
derecha, el registro muestra los
campos de la segunda tabla
puestos a "null".
select CAMPOS
from TABLAIZQUIERDA
left join TABLADERECHA
on CONDICION;
select l.titulo,e.nombre
from editoriales as e
left join libros as l
on l.codigo_editorial =
e.codigo_editorial;
El resultado mostrará el título y
nombre de la editorial; las
editoriales de las cuales no hay
libros, es decir, cuyo código de
editorial no está presente en
"libros" aparece en el resultado,
pero con el valor "null" en el
campo "titulo".
Es importante la posición en
que se colocan las tablas en
un "left join", la tabla de la
izquierda es la que se usa
para localizar registros en la
tabla de la derecha.
También podemos mostrar las
editoriales que NO están
presentes en "libros", es decir,
que NO encuentran
coincidencia en la tabla de la
derecha:
select l.titulo,e.nombre
from editoriales as e
left join libros as l
on
e.codigo_editorial=l.codigo_ed
itorial
where l.codigo_editorial is
null;
ROLES
PostgreSQL maneja los
permisos de acceso a bases
de datos usando el concepto
de ROLES. Un ROL puede
ser pensado como si fuera un
usuario o un grupo de base de
datos, dependiendo de como
se establezca el ROL.
Los Roles pueden poseer
objetos de base de datos (por
ejemplo tablas) y puede
asignar privilegios sobre esos
objetos hacia otros roles para
controlar quien tiene acceso a
dichos objetos.
Los ROLES de base de datos
son en concepto
completamente separados de
los usuarios del sistema
operativo.
En la practica podría se
conveniente mantener una
correspondencia, Aunque esto
no es obligatorio.
Los roles de base de datos
son globales en todo el cluster
de base de datos (y no
individuales para cada base
de datos).
Para crear un rol se usa el
siguiente comando SQL

CREATE ROLE nombre;


Para eliminar un rol se usa el
siguiente comando SQL:

DROP ROLE nombre;


Atributos de un ROL
Un rol de base de datos puede
tener un número de atributos
que define sus privilegios e
interactua con el sistema de
autenticación de usuarios.
Privilegio de LOGIN

Solo roles que tienen el


atributo LOGIN pueden ser
usados como el rol inicial para
una conexión a la base de
datos.
Un rol con el atributo LOGIN
puede ser considerado como
si fuera un usuario de base de
datos. Para crear un role con
el privilegio de login usar:
CREATE ROLE nombre LOGIN;
Estatus SUPERUSER
Un super usuario de base de
datos sobrepasa todo el
chequeo de permisos, excepto
el derecho de loguearse o el
derecho de iniciar replicación.
Este es un privilegio peligroso
y no debe usarse sin cuidado;
es mejor hacer la mayoria del
trabajo con un rol que no sea
de super usuario.
Para crear un un nuevo
superusuario de base de
datos:
CREATE ROLE nombre
SUPERUSER.
Este rol debe de hacerse
siendo ya un superusuario.
Rol de creación de base de
datos.
A un rol se le deben de dar
permisos explicitos para crear
bases de datos(excepto para
los superusers, por que ellos
tienen todos los permisos).
Para crear un rol con permisos
para crear bases de datos
use:
CREATE ROLE nombre
CREATEDB
A un rol se le deben dar
permisos explicitos para crear
más roles (excepto para
superusers).
Para crear tal rol usar :
CREATE ROLE nombre
CREATEROLE;
Un rol con el privilegio
CREATEROLE puede
cambiar o borrar otros roles
así como otorgar o quitar
permisos sobre dichos roles
Asignando contraseña a un rol

Una contraseña se utilizará solo si


el método de autenticación de él
cliente requiere que el usuario
ingrese una contraseña para
conectarse a la base de datos.
CREATE ROLE nombre
PASSWORD ’contraseña’;
Membresia de ROLES
Es conveniente el agrupar
usuarios para administrar de
forma fácil los privilegios, de esa
forma los privilegios pueden ser
otorgados o revocados a todo el
grupo como un todo.
En PostgreSQL esto se hace
creando un rol que represente al
grupo y otorgue la membresia en
el rol del grupo y entonces
otorgarles permiso en el rol del
grupo a usuarios individuales.
Para crear un grupo como un rol
primero se crea el rol:
CREATE ROLE nombre;

Tipicamente un rol que va a ser


usado como un grupo no tendría
el atributo LOGIN.
Una vez que el role exista, se
pueden agregar miembros o quitar
miembros usando los comandos
GRANT y REVOKE

GRANT rol_grupo TO rol1, ... ;


REVOKE rol_grupo FROM rol1,.. ;
VISTAS
Una vista es una alternativa
para mostrar datos de varias
tablas. Una vista es como una
tabla virtual que almacena una
consulta.
Los datos accesibles a través
de la vista no están
almacenados en la base de
datos como un objeto.
Entonces, una vista almacena
una consulta como un objeto
para utilizarse posteriormente.
Las tablas consultadas en una
vista se llaman tablas base.
En general, se puede dar un
nombre a cualquier consulta y
almacenarla como una vista.
Una vista, en sí, es una “tabla
virtual” derivada, con nombre. El
término virtual significa que la
tabla no existe como tal, pero
para el usuario si parece existir.
Las vistas tienen la misma
estructura que una tabla : filas
y columnas. los datos se
recuperan mediante una
consulta SELECT y se
presentarán igual que los de
una tabla.
La sintaxis de definición de
una vista en SQL es:
CREATE [OR REPLACE]
VIEW nombre_de_vista
AS
sentencia_SELECT
Ejemplo sencillo :

CREATE VIEW
cliente_apellido AS
SELECT * FROM clientes
WHERE ap_paterno LIKE
‘A%’
ELIMINAR VISTAS.

Si en algún caso, se necesita


modificar una vista, deberá
eliminarla primero y luego
volverla a crear.
De forma similar si también se
necesita eliminar una vista de
la base de datos, la sentencia
es la siguiente :
DROP VIEW
<nombre_de_la_vista>
REGLAS
El sistema de reglas de
PostgreSQL permite definir
una acción alternativa cuando
se ejecutan inserciones,
actualizaciones o borrados en
las tablas de la base de datos
Es decir, una regla va a
proveer comandos adicionales
que serán ejecutados cuando
se ejecute una acción en una
tabla determinada.
Como alternativa una regla
tipo INSTEAD reemplazará el
comando dado por otro o hará
que el comando dado no se
ejecute del todo
Las reglas se suelen
implementar en las vistas
también.
Hay que tomar en cuenta que
la regla es un mecanismo de
transformación o un comando
macro.
La tranformación pasa antes
de la ejecución del comando
dado
Se puede crear la ilusión de
una “Vista Actualizable”
definiendo reglas para
inserción, borrado y
actualización
Por ejemplo reemplazando la
acción UPDATE en la vista,
por un UPDATE en la tabla o
tablas que involucra la vista.
Siempre hay que tomar en
cuenta que cuando se
actualiza una vista, debemos
utilizar una regla tipo
INSTEAD incondicional
Parametros:
Nombre: Es el nombre de la
regla a crear debe de ser
distinto a cualquier nombre de
otra regla o de la tabla.
Evento: El evento será un
SELECT, UPDATE, INSERT o
DELETE.
Tabla: El nombre de la tabla o
vista a la cual se va a aplicar
la regla.
Condición: Cualquier
expresión SQL. La condición
no puede hacer referencia a
ningún otra tabla, solo NEW y
OLD y no puede tener
funciones agregadas.
INSTEAD: El INSTEAD indica
los comandos que serán
ejecutados en lugar del
comando original
ALSO: Indica que los
comandos serán ejecutados
ademas del comando original
Comando: El comando o
comandos que se haran con la
regla, los comandos validos
son SELECT, UPDATE,
INSERT Y DELETE.
Se debe ser el propietario de
la tabla para poder crear o
cambiar una regla asociada a
dicha tabla.
CREATE [ OR REPLACE ]
RULE nombre AS ON evento
TO tabla [ WHERE
condición ]
DO [ ALSO | INSTEAD ]
{ NOTHING | comando |
( comando ; comando ... ) }
Ejercicio:
Crear la tabla clientes, con un
cliente_id de tipo serial y un
nombre de tipo varchar de 60,
teniendo como llave primaria
cliente_id
Insertar 3 clientes en la tabla
clientes: Armando Guerra,
Elmer Homero, Aquiles Brinco.
Crear la tabla lineas teniendo
como llave primaria linea_id
de tipo serial, cliente _id de
tipo entero (llave foranea con
clientes) y un numero que
será varchar de 40.
Insertar en la la tabla lineas:
2 números para el cliente 1, 1
para el cliente 2 y 1 para el
cliente 3.
Crear una vista que retorne
toda la información de las
líneas de los clientes.
CREATE VIEW
clientes_lineas AS SELECT
c.cliente_id,l.linea_id,
c.nombre, l.numero FROM
clientes c INNER JOIN lineas l
ON c.cliente_id=l.cliente_id
;
Se necesita crear una REGLA
que proteja los datos de la
tabla clientes en caso de
actualización o borrado
CREATE RULE
proteccion_clientes_update
AS ON UPDATE TO clientes
WHERE old.cliente_id < 3 DO
INSTEAD nothing;
UPDATE clientes SET
nombre='PETER' WHERE
cliente_id=1;
CREATE RULE
proteccion_clientes_delete AS
ON DELETE TO clientes
where old.cliente_id < 4 DO
INSTEAD nothing;
DELETE FROM clientes
WHERE cliente_id=3
Las Reglas de Inserción:
sobre la vista cuando se trata
de insertar un cliente Nuevo
CREATE RULE ins_clientes_lineas_nuevo
AS
ON INSERT TO clientes_lineas
WHERE NEW.cliente_id IS NULL
DO INSTEAD
(
INSERT INTO clientes (nombre)
VALUES (NEW.nombre);
INSERT INTO lineas (cliente_id, numero)
VALUES (currval('clientes_cliente_id_seq'),
NEW.numero));
Las Reglas de Inserción:
Cliente Existente
CREATE RULE
ins_cliente_linea_existente AS
ON INSERT TO clientes_lineas
WHERE NEW.cliente_id IS NOT NULL
DO INSTEAD
INSERT INTO lineas (cliente_id, numero)
VALUES (NEW.cliente_id, NEW.numero);
Las Reglas de Inserción:
Incondicional
CREATE RULE
ins_cliente_linea_nothing AS
ON INSERT TO
clientes_lineas
DO INSTEAD NOTHING;
INSERT INTO clientes_lineas
(nombre, numero)
VALUES ('Daniela Donoso'
'234-4567');
INSERT INTO clientes_lineas
(cliente_id, numero)
VALUES (3, ’987-1233’);
Las Reglas de Actualización
CREATE RULE
upd_clientes_lineas_cliente AS
ON UPDATE TO clientes_lineas
WHERE NEW.cliente_id IS NOT NULL
DO INSTEAD
UPDATE clientes
SET nombre = NEW.nombre
WHERE cliente_id = NEW.cliente_id;
CREATE RULE
upd_clientes_lineas_linea AS
ON UPDATE TO clientes_lineas
WHERE NEW.linea_id IS NOT NULL
DO INSTEAD
UPDATE lineas
SET numero = NEW.numero
WHERE linea_id = NEW.linea_id;
CREATE RULE
upd_clientes_lineas_nothing
AS
ON UPDATE TO
clientes_lineas
DO INSTEAD NOTHING;
UPDATE clientes_lineas
SET nombre = 'Carmen
Campora'
WHERE cliente_id = 3;
UPDATE clientes_lineas
SET numero = '1-800-8888'
WHERE linea_id = 4;
Reglas de Borrado.
Borrar una linea o varias de un
cliente
CREATE RULE del_clientes_lineas
AS ON DELETE TO clientes_lineas
where old.cliente_id IS NOT NULL
and old.linea_id IS NOT NULL DO
INSTEAD
DELETE FROM lineas WHERE
linea_id=old.linea_id AND
cliente_id=old.cliente_id;
Funciones SQL
PostgreSQL nos brinda un
conjunto de funciones para
el manejo de fechas, string,
números etc. pero además
nos permite crear funciones
propias.
La creación de una función
es muy útil cuando
queremos reutilizar un
algoritmo. Podemos crear
una función y luego llamarla
en diferentes situaciones.
create or replace function
[nombre de la función]
([parámetros]) returns [tipo de
dato que retorna]
as
[definición de la función]
language [lenguaje utilizado]
Antes de crear nuestras funciones hay que crear
el lenguaje en el que las vamos a programar:

CREATE LANGUAGE plpgsql;


Como primer problema
implementaremos una
función que reciba dos
enteros y retorne la suma de
los mismos:
create or replace function
sumar(integer,integer) returns
integer
AS
'select $1+$2;'
language sql;
Cada parámetro se lo
accede luego mediante la
posición que ocupa y se le
antecede el caracter $.
El o los comandos SQL deben
ir entre comillas simples al
final del comando pondremos ;

Luego indicamos al final que


se trata de una función SQL.
Para llamar luego a esta
función lo hacemos por
ejemplo en un select:

select sumar(3,4);
create or replace function
retornarclave(varchar) returns
integer
as
'select cliente_id from
clientes where nombre=$1;'
language sql;
Cree la tabla con la siguiente
estructura:
create table medicamentos(
codigo serial,
nombre varchar(20),
laboratorio varchar(20),
precio decimal(5,2),
cantidad smallint,
primary key(codigo)
);
('Sertal','Roche',5.2,100);
('Buscapina','Roche',4.10,200);
('Amoxidal','Bayer',15.60,100);
('Paracetamol','Bago',1.90,200);
('Aspirina','Bayer',2.10,150);
('Amoxidal jarabe','Bayer',5.10,250);
Implementar una función que
retorne el precio promedio de la
tabla medicamentos.
Imprimir el precio promedio de los
medicamentos.
Imprimir los medicamentos que
tienen un precio mayor al
promedio.
create or replace function
preciopromedio() returns
decimal
as
'select avg(precio) from
medicamentos;'
language sql;
select preciopromedio();
select * from medicamentos
where
precio>preciopromedio();
Funciones que no retornan
valor
Cuando queremos crear una
función que no retorne dato lo
debemos indicar luego de la
palabra clave returns
disponiendo el valor void:
create or replace function cargarusuarios()
returns void
as
$$
insert into clientes (nombre) values ('Marcelo');
insert into clientes (nombre) values ('JuanPerez');
insert into clientes (nombre) values ('Susana');
insert into clientes (nombre) values ('Luis');
$$
language sql;
Implementar una función que
reciba el código de un
medicamento y proceda a
borrarlo.
La función no retorna dato.
create or replace function
borrarmedicamento(integer)
returns void
as
'delete from medicamentos
where codigo=$1;'
language sql;
select borrarmedicamento(1);

select * from medicamentos;


Hemos visto que una función
puede no retornar dato,
retornar un dato simple
(integer, varchar etc.) Ahora
veremos como retornar toda
una fila de una tabla.
create or replace function
retornarlibro(int) returns libros
as
'select * from libros where
codigo=$1 ;'
language sql;
select retornarlibro(4);

(3,"Alicia en el pais de las


maravillas","Lewis
Carroll",Emece,19.95)
Implementar una función que
retorne el registro completo
del medicamento más caro.
create or replace function
medicamentomascaro() returns
medicamentos
as
'select * from medicamentos
where precio=(select max(precio)
from medicamentos);'
language sql;
EL LENGUAJE DE
FUNCIONES PL/pgSQL
Una de las características de
PostgreSQL en que aventaja a la
base de datos mySQL 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 PostgreSQL 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, tambien 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.
Estructura de PL/pgSQL
El lenguaje PL/pgSQL es
estructura en bloques.
Todas las palabras clave y
los identificadores pueden
escribirse mezclando letras
mayúsculas y minúsculas.
Un bloque se define de la
siguiente manera:
[ <<label>> ]
[ DECLARE
Declarations ]
BEGIN
statements
END [ label ];
Pueden existir varios
bloques o sub-bloques en la
secció́ n de sentencias de un
bloque.
Los sub-bloques pueden ser
usados para ocultar las
variables a los bloques más
externos.
Normalmente una de las
sentencias es el valor de
retorno, usando la palabra
clave RETURN.
Las variables declaradas en
la sección que antecede a
un bloque se inicializan a su
valor por omisión cada vez
que se entra al bloque
No solamente al ser llamada
la función.
Por ejemplo:
CREATE FUNCTION estafunc()
RETURNS INTEGER AS $$
DECLARE
cantidad INTEGER := 30;
BEGIN
RAISE NOTICE 'Cantidad
contiene aquí %',cantidad;
-- Cantidad contiene aquí 30
cantidad := 50;
-- Creamos un sub-bloque
DECLARE
cantidad INTEGER := 80;
BEGIN
RAISE NOTICE 'Cantidad
contiene aquí %',cantidad;
-- Cantidad contiene aquí 80
END;
RAISE NOTICE 'Cantidad contiene
aquí %',cantidad;
-- Cantidad contiene aquí 50
RETURN cantidad;
END;
$$ LANGUAGE 'plpgsql';
Comentarios, constantes y
variables
Existen dos tipo de
comentarios en PL/pgSQL. Un
doble guión -- da inicio a un
comentario, el cual se
extiende hasta el final de la
línea.
Un /* inicia un bloque que se
extiende hasta la primera
ocurrencia de */.
Variables y constantes
Todas las variables, filas y
registros usados en un
bloque o en sus sub-
bloques deben declararse
en la sección de
declaraciones del bloque.
Las variables en PL/pgSQL
pueden ser de cualquier tipo
de datos de SQL, como
INTEGER, VARCHAR y
CHAR.
A continuación se muestran
algunos ejemplos de
declaración de variables:
user_id integer;
quantity numeric(5);
url varchar;
Myrow tablename%ROWTYPE;
arow RECORD;
La declaraciones tienen las
siguiente sintaxis:

nombre [ CONSTANT ] tipo


[ NOT NULL ] [ { DEFAULT
| := } valor ];
El valor de una variable
declarado como CONSTANT no
puede ser modificado.
cantidad DEFAULT 32;
url varchar := 'http://mysite.com';
user_id CONSTANT integer := 10;
Variables pasadas a las
funciones (parametros)
Las variables (parametros)
que se pasan a las funciones
son denominadas con los
identificadores $1, $2, etc. (el
máximo es 16).
Opcionalmente se pueden
establecer alias para las
variables que recibe la
función haciendolas más
leibles.
nombre ALIAS FOR $n;

Los alias se pueden


establecer para cualquier
variable dentro de la
función.
CREATE FUNCTION
iva_venta(REAL)
RETURNS REAL AS $$
DECLARE
subtotal ALIAS FOR $1;
BEGIN
return subtotal * 1.15;
END;
$$ LANGUAGE 'plpgsql';
Es posible agregar parametros
de salida a una función
Cuando una función es
declarada con parametros
de salida puede ser
proporcionado con un alias
igual que los parametros de
entrada.
Un parametro de salida es
una variable que inicia su
valor con NULL y durante la
ejecución de la función se le
asigna su valor
correspondiente.
CREATE FUNCTION
iva_venta2(subtotal real, OUT total
real) AS $Bloque1$
BEGIN
total:=subtotal * 1.15;
END;
$Bloque1$ LANGUAGE 'plpgsql';
CREATE FUNCTION
sum_y_mul(x int, y int, OUT
sum int, OUT mul int) AS $$
BEGIN
sum := x + y;
mul := x * y;
END;
$$ LANGUAGE plpgsql;
Atributos
Usando los atributos %TYPE
and %ROWTYPE, es posible
declarar variables con el mismo
tipo de dato o estructura de otro
item de la base de datos (por
ejemplo, un campo de una
tabla).
%TYPE Proporciona el tipo
de dato de una variable o
una columna. Se puede
utilizar para declarar
variables que almacenen
valores de bases de datos.
Por ejemplo, supongamos
que tenemos una columna
llamada cliente_id en la
tabla clientes.
Para declarar una variable
con el mismo tipo de dato
que el usado en nuestra
tabla de clientes,
escribiriamos:

cliente_id clientes.cliente_id%TYPE;
Al usar %TYPE puede
despreocuparse de los
cambios futuros en la
definición de la tabla.
Nombre tabla%ROWTYPE
Declara un renglón con la
estructura de la tabla
especificada. tabla puede
ser una tabla o una vista
que exista en la base de
datos.
Los campos del renglón se
accesan con la notación
punto. Los parámetros de
una función pueden ser de
tipo compuesto (renglones
completos de una tabla).
Es este caso, el identificador
correspondiente $n será del
tipo rowtype, pero debe
usarse un seudónimo o alias
usando el comando ALIAS
DECLARE
renglon clientes%ROWTYPE;
Sentencias
Asignación
Una asignación de un valor
a una variable o campo de
fila o de registro se escribe:

identifier := expression;
Si el tipo de dato resultante
de la expresión no coincide
con el tipo de dato de las
variables, o la variable
tienen un tamaño o
precisión conocido (como
char(29))
El resultado será amoldado
implicitamente por el
interprete de PL/pgSQL,
usando los tipos de las
variables para las funciones
de entrada y los tipos
resultantes en las funciones
de salida.
impuesto := subtotal * 0.15;
mi_registro.user_id := 20;
Una asignación de una
selección completa en un
registro o fila puede hacerse
del siguiente modo:

SELECT expressions INTO


target FROM ...;
target puede ser un registro,
una variable de fila o una
lista separada por comas de
variables y campo de
registros o filas.
Si una fila o una lista de
variables se usa como
objetivo, los valores
seleccionados han de
coincidir exactamente con la
estructura de los objetivos o
se producirá un error de
ejecución.
Existe una variable especial
llamada FOUND de tipo
booleano, que puede usarse
inmediatamente después de
SELECT INTO para
comprobar si una
asignación ha tenido éxito.
SELECT * INTO myrec
FROM clientes WHERE
nombre = minombre;
IF NOT FOUND THEN
RAISE EXCEPTION
'cliente % no encontrado',
minombre;
END IF;
Abortando la ejecución y
mensajes
Use la sentencia RAISE para
enviar mensajes al
mecanismo de bitacora de
PostgreSQL.

RAISE level ’format’ [,


identifier [...]];
RAISE NOTICE 'Cantidad
contiene aquí %',cantidad;
RAISE EXCEPTION 'cliente %
no encontrado', minombre;
END IF;
Estructuras de control
Condiciones
IF expresion THEN
sentencias
[ELSE
sentencias]
END IF;
IF expresión boolean THEN
sentencias
[ ELSEIF expresión boolean THEN
sentencias
[ ELSEIF expresión boolean THEN
sentencias
...]]
[ ELSE
statements ]
END IF;
Realizar una función con el
lenguaje pl/pgsql que reciba
como parametro un número
y con el uso de estructuras
de control dé como
resultado si el número es
cero, positivo o negativo
CREATE OR REPLACE
FUNCTION
ejemploIF(numero integer)
RETURNS varchar AS
$$
DECLARE tipo varchar;
BEGIN IF numero = 0 THEN
tipo:='cero';
ELSEIF numero>0 THEN
tipo:='positivo';
ELSEIF numero < 0 THEN
tipo:='Negativo';
ELSE tipo:='NULL'; END IF;
RETURN tipo;
END; $$
LANGUAGE plpgsql;
Case simple
CASE expresión
WHEN expresión [, expresión [ ... ]]
THEN
sentencias
[ WHEN expresión [, expresión [ ... ]]
THEN
sentencias
... ]
[ ELSE
sentencias ]
END CASE;
La expresión es evaluada una
vez y sucesivamente comparada
con cada expresión en la
clausula WHEN, si hay
concordancia, entonces las
sentencias correspondientes son
ejecutadas.
Entonces el control pasa a
la siguiente sentencia
despues del END CASE;
(todos los THEN siguientes
no son evaluados)
Si no se encuentran
correspondencias las
sentencias asignadas al
ELSE son ejecutadas.
CASE x
WHEN 1, 2 THEN
msg := 'Uno o Dos'
ELSE
msg := 'Otro valor
diferente a uno o dos';
END CASE;
CREATE OR REPLACE FUNCTION
obtiene_rango(medicamento_id integer)
RETURNS VARCHAR(50) AS $$
DECLARE
rango NUMERIC;
segmento_precio VARCHAR(50);
BEGIN
-- obtenemos el rango basados en el precio
SELECT INTO rango precio
FROM medicamentos
WHERE codigo = medicamento_id;
CASE rango
WHEN 1.9 THEN
segmento_precio = 'Precio Barato';
WHEN 4.10 THEN
segmento_precio = 'Precio Intermedio';
WHEN 15.60 THEN
segmento_precio = 'Precio Alto';
ELSE
segmento_precio = 'No especificado';
END CASE;

RETURN segmento_precio;
END; $$
LANGUAGE plpgsql;
Ciclos
LOOP
[<<Etiqueta>>]
LOOP
sentencias
END LOOP;
Se trata de un bucle no
condicional que ha de ser
terminado de forma
explicita, mediante una
sentencia EXIT.
La etiqueta opcional puede
ser usada por las sentencias
EXIT de otros ciclos
anidados, para especificar el
nivel del ciclo que ha de
terminarse.
EXIT [ Etiqueta ] [ WHEN
Expresión boolean ];
LOOP
-- Algunos Calculos
IF contador > 0 THEN
EXIT; -- sale del loop
END IF;
END LOOP;
CICLO LOOP
-- Algunos Calculos
EXIT WHEN contador > 0;

-- mismo resultado anterior


END LOOP;
<<bloquex>>
BEGIN
-- Algunos calculos
IF stocks > 100000 THEN
EXIT bloquex; -- Sale Begin
END IF;
-- Más Calculos que seran
brincados
Cuando stocks > 100000
END;
CICLO WHILE
[<<Etiqueta>>]
WHILE expresión LOOP
Sentencias
END LOOP;
El Ciclo WHILE repite una
secuencia de sentencias
hasta que la expresión sea
evaluada y sea verdadera. La
expresión se checa cada vez
que se entra al cuerpo del
ciclo.
CICLO FOR
[<<Etiqueta>>]
FOR variable IN [ REVERSE ]
expresión .. expresión LOOP
sentencias
END LOOP;
Se trata de un bucle que se
itera sobre un rango de
valores enteros. La variable
se crea automáticamente con
el tipo entero, y existe solo
dentro del ciclo.
Las dos expresiones dan el
limite inferior y superior del
rango y son evaluados sólo
cuando se entra en el ciclo.
El paso de la iteración es
siempre 1.
FOR i IN 1..10 LOOP
-- Tomará los valores de 1
a 10 en el ciclo
END LOOP;
FOR i IN REVERSE 10..1 LOOP
-- Tomará los valores de 10 a 1
en el ciclo
END LOOP;
Hacer una función en
pl/pgsql que reciba 4
parametros, 3 números y
una operación. y te de el
resultado de la Operación
especificada(Suma,
Multiplicación, Promedio)
Manejando Registros
RECORD es un tipo de dato
que almacena un registro
completo de una tabla de
base de datos a través de un
select
RECORD es similar a
rowtype la unica diferencia
es que no hay una
estructura definida para
RECORD
RECORD se puede usar en
sentencias y ciclos FOR
Para declarar un record se
sigue la siguiente sintaxis

nombre RECORD;
Una asignación se puede
dar de la siguiente forma:

SELECT INTO target


expresiones FROM ...;
Los posibles valores para
TARGET son:

Un registro

Una variable renglón

Una lista de valores
separados por comas
CREATE FUNCTION
nombre_cliente(cliente integer)
RETURNS text AS $$
DECLARE
reg_cliente RECORD;
nombre_completo TEXT;
--se declaran una variable de tipo
registro y una variable de tipo
texto
BEGIN

SELECT INTO reg_cliente *


FROM clientes WHERE
cliente_id = cliente;
– Se busca al cliente 2 y se
asigna el resultado a la variable
tipo RECORD(reg_cliente)
nombre_completo := reg_cliente.nombre
||' '|| reg_cliente.apellidos;
--Se asigna el valor del nombre
concatenado con los apellidos del
cliente
return nombre_completo;
END;
$$
LANGUAGE plpgsql;
Hay otra forma de checar
los resultados de un select
into, utilizando la condición
NULL.
Con un IF podemos saber si
un campo es NULL o NOT
NULL, si hay más de un
registro NULL, solo se
mostrará el primero los
demas se eliminan.
Iteraciones a través de
registros
Existe una sintaxis especial
del ciclo for para iterar entre
resultados de una sentencia
select y darnos la facilidad
de manipular los datos
La sintaxis es:
FOR RECORD | row IN
sentencia select LOOP
sentencias;
END LOOP;
Cuando se ejecuta el ciclo
for las sentencias en el
cuerpo del ciclo son
ejecutadas para cada
registro o renglon en
resultado de la sentencia
select
Realizar una función que, de
la tabla de medicamentos
sume todas las existencias
y regrese la suma total
utilizando un ciclo for
Realizar una función que
actualize el precio de un
medicamento determinado de
la tabla de medicamentos
incrementandolo o
decrementandolo según un
porcentaje determinado
PL/pgSQL y Triggers
Las funciones pueden ser
definidas para que de forma
automática se ejecuten
cuando una acción tal como
UPDATE, DELETE, INSERT
ocurre.
Esto se lleva a cabo con un
Trigger ó disparador
El Trigger invoca a una
función cuando la operación
UPDATE, DELETE, INSERT
ocurre en la tabla
especificada.
Los Triggers pueden ser
definidos con el comando
CREATE FUNCTION
Deben ser declarados sin
argumentos y con retorno
OPAQUE.
OPAQUE es un tipo de dato
que es usado solo por
funciones internas que
llaman a otras funciones.
Las funciones definidas con
el tipo de retorno OPAQUE
no pueden ser usadas en
consultas SQL por que el
tipo OPAQUE no existe en
SQL
La sintaxis para crear un
Trigger es:
CREATE TRIGGER
Nombre_trigger

{BEFORE|AFTER}
tipo_evento
ON
nombre_tabla
FOR EACH {ROW|
STATEMENT}
EXECUTE PROCEDURE
nombre_funcion
(parametros)
El orden importa:
Si primero se crea un
Trigger y despues se crea la
función que el Trigger llama,
el Trigger no se ejecutará de
forma correcta.
Se debe crear primero la
función y despues el Trigger
que usará esa función
Variables especiales en
PL/pgSQL
Cuando una función escrita en
PL/pgSQL es llamada por un
Trigger tenemos ciertas
variables especiales
disponibles en dicha función.
Estas variables son las
siguientes:
NEW
Tipo de dato RECORD; Variable
que contiene la nueva fila de la
tabla para las operaciones
INSERT/UPDATE en Triggers del
tipo row-level. Esta variable es
NULL en Triggers del tipo
statement-level.
OLD
Tipo de dato RECORD; Variable
que contiene la antigua fila de la
tabla para las operaciones
UPDATE/DELETE en Triggers
del tipo row-level. Esta variable
es NULL en Triggers del tipo
statement-level.
TG_NAME
Tipo de dato name; variable
que contiene el nombre del
Trigger que está usando la
función actualmente.
TG_WHEN
Tipo de dato text; una cadena
de texto con el valor BEFORE o
AFTER dependiendo de como el
Trigger que está usando la
función actualmente ha sido
definido.
TG_OP
Tipo de dato text; una cadena
de texto con el valor INSERT,
UPDATE o DELETE
dependiendo de la operación
que ha activado el Trigger que
está usando la función
actualmente.
Crear la tabla:
create table
autores(id_autor integer,
nombre varchar);
Otro ejemplo de un Trigger
es guardar una bitacora de
cambios sobre una tabla
Realizar un trigger que
proteja la tabla
medicamentos de ser
borrada.
En resumen:

Un Trigger se puede definir


de las siguientes maneras:
# Para que ocurra ANTES de
cualquier INSERT,UPDATE ó
DELETE

# Para que ocurra DESPUES


de cualquier INSERT,
UPDATE ó DELETE
# Para que se ejecute una
sola vez por comando SQL
(statement-level trigger)

# Para que se ejecute por


cada linea afectada por un
comando SQL (row-level
trigger)
Creación de un Trigger de
tipo statement-Level:
Ejercicio:
Crear la tabla
ventas_medicamentos
Con:
id_usuario integer
codigo integer
cantidad integer
Crear un trigger que, cuando
se inserte en la tabla
ventas_medicamentos,
decremente las existencias
de dicho medicamento en la
tabla medicamentos.
Si el medicamento no tiene
existencias suficientes que
la operación no se realice, si
la operación es válida que
mande a pantalla la
existencia del medicamento
después de la venta.

También podría gustarte