PostgreSQL: Funciones, Procedimientos y Vistas

8 11 2009

El diagrama siguiente es la consecuencia de la creación de la base de datos con el script descrito en PostgreSQL: Sentencias DDL (1), Es un modelo pequeño, pero servirá para las futuras demostraciones con postgres.

Descripción: Una universidad realiza el registro de contactos, que son las personas que podrían ser potenciales postulantes a diferentes carreras. Los postulantes deberán pertenecer a un periodo académico y deberán elegir una modalidad asì como la carrera a la que quieren postular. Por lo general en un año solo existen dos periodos académicos, por ejemplo los periodos académicos del año 2008 fueron: 2008-1 y 2008-2. El contacto debe tener los datos personales del sujeto asì como la fecha de creación. El postulante debe tener registrado si asistió a su exámen de admisión, y si ingresó o no, debe tener también establecido el puntaje que alcanzó en el exámen.

Con esos datos podemos comenzar a elaborar nuestras primeras consultas usando instrucciones DML.

Modelo Relacional Base de datos

Antes de ir al grano, aclaro que acostumbro crear funciones cuando se trata de retornar datos, como por ejemplo una consulta que utilice la cláusula SELECT, y procedimientos almacenados únicamente cuando se trata de realizar una operación que no retorne ningún dato, por ejemplo, INSERT, UPDATE o DELETE.

En SQLServer se suele utilizar un Procedimiento Almacenado para cualquiera de los 2 casos descritos, aunque en PostGres también se puede retornar datos con procedimientos almacenados, sería ideal respetar la funcionalidad de cada uno. Las funciones desarrolladas en éste post se realizará haciedno uso del lenguaje procedural ‘plpgsql’, que generalmente trae  PostGreSQL.

Si aún no tienes preparado la base de datos, aqui les dejo un script. Es la unión de las DDL y DML creadas en posts anteriores. Ésta creará el entorno en el que se realizarán las demostraciones.

Descargar Script: DBAdmision.sql

FUNCIONES:

1) Cree una función que devuelva los siguientes datos: <ver>

Periodo 101 309 310 Total
2005-1 1 7 7 15
2005-2 0 13 12 25
2006-1 0 17 18 35
2006-2 0 23 22 45
2007-1 0 27 28 55

2) Cree una función que devuelva los siguientes datos: <ver>

Periodo 101 309 310 Total
2005-1 1 7 7 15
2005-2 0 13 12 25
2006-1 0 17 18 35
2006-2 0 23 22 45
2007-1 0 27 28 55
TOTAL 1 87 87 175

3) Cree una función que liste todos los postulantes de un determinado periodo académico. La lista debe reiniciar la numeración por orden alfabético. <ver>

Apellidos y Nombres
1 Alanya Padilla Alina Susan
2 Alarcon Castro Gustavo Claudio Andres
1 Baldeón Balvín Olger
2 Baldeón Sanabria Natalia Ivonne
1 Cachuán Cámac Miguel Fernando
2 Cajachagua Chui Jose Arturo

4) Cree una función que liste todos los postulantes de un determinado periodo académico, la lista debe estar enumerada y ordenada por apellido paterno, materno y nombres. <ver>

Apellidos y Nombres
1 Alanya Padilla Alina Susan
2 Alarcon Castro Gustavo Claudio Andres
3 Alarco Lama Ricardo Rafael

5) Cree una función que reciba como parámetro el id de un contacto y que muestra la siguiente información. Se debe de mostrar todos los periodos académicos y una X en todos aquellos en la cual el contacto postuló. <ver>

Periodo Postuló
2005-1 X
2005-2
2006-1
2006-2
2007-1 X

6) Cree una función que muestre un resumen como el siguiente: <ver>

Apellidos y Nombres 2005-1 2005-2 2006-1 2006-2 2007-1 2007-2 TOTAL
Alanya Padilla Alina Susan X 1
Alarcon Castro Gustavo Claudio Andres X 1
Alarco Lama Ricardo Rafael X 1
Altez Yanez Jasmin Gabriela X 1
Amable Salva Katerin Lisbet X 1

7) Cree una función que muestre un resumen como el siguiente: <ver>

Puntaje 2005-1 2005-2 2006-1 2006-2 2007-1 2007-2 TOTAL
0 1 3 1 2 2 9
12 1 1
13 1 1
14 1 1
21 1 1 2
23 1 3 4

8.) Cree una función que liste todos aquellos postulantes (Apellidos, Nombres, Puntaje) cuyo puntaje es mayor o igual al puntaje promedio obtenido en todos los exámenes. <ver>

VISTAS:

9) Cree una vista que liste a todos aquellos postulantes que no asistieron al examen. Muestre los nombres, Apellidos, edad y género en formato (Varón/Mujer). <ver>

10) Cree una vista que liste a todos aquellos postulantes que ingresaron cuyo cumpleaños sea mañana (Entiéndase mañama como el dia después de la fecha actual). Muestre nombres y apellidos. <ver>

11) Cree una vista que muestre un resumen como el siguiente: <ver>

Nombre 2005-1 2005-2 2006-1 2006-2 2007-1 TOTAL
Administración 5 8 12 14 23 62
Contabilidad 6 7 13 17 22 65
Ingeniería Informática 0 0 0 0 0 0
TOTAL 11 15 25 31 45 127

PROCEDIMIENTOS ALMACENADOS:

12) Cree un procedimiento almacenado que permita eliminar los postulantes registrados correspondientes a una modalidad. <ver>

13)Cree un procedimiento almacenado que permita registrar a un nuevo contacto. <ver>

14)Cree un procedimiento almacenado que permita actualizar los datos de un postulante. <ver>

TOPIC:

FUNCTION, PROCEDURE, VIEW
*Post no concluido




PostgreSQL: Sentencias DML

5 11 2009

El lenguaje de Manipulación de Datos (Data Manipulation Language – DML) sirve para llevar a cabo las transacciones en las base de datos, entiéndase por transacciones los procesos de insersión, actualización, eliminación, selección.

Podemos clasificar a estas sentencias como: INSERT, UPDATE, DELETE, SELECT.

Usaremos la base de datos DBAdmision estructurado en el post de Sentencias DDL para realizar las operaciones antes mencionadas.

En este ejemplo insertaremos, actualizaremos y eliminaremos datos de Admision.Modalidad , de la base de datos generada en el post de Sentencias DDL.

--1) LISTAR DATOS DE Admision.Modalidad
SELECT IDModalidad, Modalidad FROM Admision.Modalidad;
--2) INSERTAR DATOS EN Admision.Modalidad
INSERT INTO Admision.Modalidad(Modalidad)
VALUES('Exámen Ordinario'); --El campo IDModalidad es secuencial
SELECT * FROM Admision.Modalidad; --Comprobar Inserción
--3) ACTUALIZAR DATOS EN Admision.Modalidad
UPDATE Admision.Modalidad SET Modalidad='Ordinario'
WHERE IDModalidad='1';
SELECT * FROM Admision.Modalidad; --Comprobar Actualización
--4) ELIMINAR DATOS EN Admision.Modalidad
DELETE FROM Admision.Modalidad
WHERE IDModalidad='1';
SELECT * FROM Admision.Modalidad; --Comprobar Eliminación
Descargar Script: PostgreSQL Sentencias DML.sql

Aquí les dejo el Script DML completo que insertará los datos correspondientes en cada tabla.

TOPIC: INSERT,UPDATE,DELETE,SELECT

RELACIONADOS:





PostgreSQL: Sentencias DDL (2)

5 11 2009

En esta parte veremos como realizar la eliminación de los objetos de la base de datos creada anteriormente, pero con fines prácticos lo haremos paso a paso, ya que la eliminación podría ser tan sensilla como eliminar la base de datos directamente, o los componentes que lo componen en cascada si fuese necesario.

--1) ELIMINACIÓN DE CLAVES FORÁNEAS (FOREIGN KEYS):
ALTER TABLE Persona.Postulante
DROP CONSTRAINT fk_IDCarrera;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT fk_IDPerAcad;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT fk_IDModalidad;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT fk_IDContacto;
;;
--2) ELIMINACIÓN DE CLAVES PRIMARIAS (PRIMARY KEYS):
ALTER TABLE Admision.PerAcad
DROP CONSTRAINT pk_IDPerAcad;
;;
ALTER TABLE Admision.Carrera
DROP CONSTRAINT pk_IDCarrera;
;;
ALTER TABLE Persona.Contacto
DROP CONSTRAINT pk_IDContacto;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT pk_IDPostulante;
;;
ALTER TABLE Admision.Modalidad
DROP CONSTRAINT pk_IDModalidad;
;;
--3) ELIMINACIÓN DE RESTRICCIONES (UNIQUE):
ALTER TABLE Admision.Carrera
DROP CONSTRAINT uq_nombrecarrera;
;;
ALTER TABLE Persona.Contacto
DROP CONSTRAINT uq_ContactoDNI;
;;
ALTER TABLE Admision.Modalidad
DROP CONSTRAINT uq_Modalidad;
;;
--4) ELIMINACIÓN DE RESTRICCIONES (CHECK):
ALTER TABLE Persona.Contacto
DROP CONSTRAINT ck_Genero;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT ck_asistioexamen;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT ck_ingreso;
;;
ALTER TABLE Persona.Postulante
DROP CONSTRAINT ck_puntaje;
;;
--5) ELIMINACIÓN DE COLUMNAS (COLUMNS):
ALTER TABLE Admision.Carrera
DROP COLUMN IDCarrera,
DROP COLUMN Nombre;
;;
--6) ELIMINACIÓN DE TABLAS (TABLES):
DROP TABLE Admision.Carrera;
DROP table Persona.Contacto;
DROP table Persona.Postulante;
DROP Table Admision.PerAcad;
DROP TABLE Admision.Modalidad;
;;
--7) ELIMINACIÓN DE SECUENCIAS (SEQUENCE):
DROP SEQUENCE Persona.seq_idcontacto;
DROP SEQUENCE Admision.seq_idmodalidad;
;;
--8) ELIMINACIÓN DE ESQUEMAS (SCHEMAS) :
DROP SCHEMA Persona;
DROP SCHEMA Admision;
;;
--9) ELIMINACIÓN DE BASE DE DATOS (DATABASE):
DROP DATABASE DBAdmision;

Como explicaba en un inicio, podríamos utilizar métodos más directos si queremos eliminar un objeto, por ejemplo:

--1)Eliminar la base de datos con todos sus objetos:
DROP DATABASE DBAdmision; --en modo desconectados
--2)Eliminar una secuencia que está siendo utilizada por una tabla:
DROP SEQUENCE Persona.seq_idcontacto CASCADE;
DROP SEQUENCE Admision.seq_idmodalidad CASCADE;
--3)Eliminar una tabla con todos los constraints que posea:
DROP TABLE Admision.Carrera CASCADE;
DROP Table Admision.PerAcad CASCADE;
DROP TABLE Admision.Modalidad CASCADE;
DROP table Persona.Contacto CASCADE;
DROP table Persona.Postulante CASCADE;
--4)Eliminar un esquema con todos sus objetos
DROP SCHEMA Persona CASCADE;
DROP SCHEMA Admision CASCADE;

TOPIC: DROP, CASCADE, COLUMN

RELACIONADOS:





Diagramas de Base de Datos

4 11 2009

Ésta época me tocó obsesionarme con las base de datos, y por ahi encontré unos modelos  que no cae nada mal a la gente floja como yo,  aunque siempre habrá que adaptarlo a las necesidades, no todo cuaja para lo que quieras hacer, diría que son demasiados específicos, pero ya tienes una referencia, más que nada para practicar, podeis elegir entré más de 500 esquemas de base de datos en databaseanswers, desde los que sirven para gestionar morgues hasta algo para e-commerce.





PostgreSQL: Sentencias DDL (1)

3 11 2009

El Lenguaje de Definición de Datos  (Data Definition LanguageDDL) , sirve para modificar la estructura de los objetos en una base de datos.

Estas sentencias básicamente son: CREATE, ALTER, DROP y TRUNCATE.

A continuación iniciaremos con la creación de una base de datos.

“…La base de datos que diseñaremos se me entregó en la universidad en un curso con SQLServer, ahora me da gusto poder realizar lo mismo pero en PostGreSQL”.

--1) CREACIÓN DE BASE DE DATOS (DATABASE):
CREATE DATABASE DBAdmision TEMPLATE template0;
--2) CREACIÓN DE ESQUEMAS (SCHEMAS) :
CREATE SCHEMA Persona;
CREATE SCHEMA Admision;
--3) CREACIÓN DE SECUENCIAS (SEQUENCE):
CREATE SEQUENCE Persona.seq_idcontacto START 1; --empieza desde 1
CREATE SEQUENCE Admision.seq_idmodalidad START 1; --empieza desde 1
--4) CREACIÓN DE TABLAS (TABLES):
create table Persona.Contacto
(
IDContacto int default nextval('Persona.seq_idcontacto'),
Nombres varchar(30) not null,
Paterno varchar(30) not null,
Materno varchar(30) not null,
Genero char(1) default('0') not null,
DNI varchar(10) null,
FechaNac date null,
FechaCreacion date not null default now()
)
;;
create table Persona.Postulante
(
IDPostulante char(10) not null ,
IDContacto int not null,
IDCarrera char(3) not null,
IDPerAcad char(6) not null,
IDModalidad int not null,
Puntaje int not null default(0),
AsistioExamen char(1) not null default('0'),
Ingreso char(1) not null default('0')
)
;;
Create Table Admision.PerAcad
(
IDPerAcad char(6) not null ,
Periodo char(4),
Ano char(1)
)
;;
create table Admision.Carrera
(
IDCarrera char(3) not null,
Nombre varchar(150) not null
)
;;
create table Admision.Modalidad
(
IDModalidad int default nextval('Admision.seq_idmodalidad'),
Modalidad varchar(100) not null
)
;;
--5) CREACIÓN DE RESTRICCIONES (CHECK):
ALTER TABLE Persona.Contacto
ADD CONSTRAINT ck_Genero
CHECK (Genero in ('0','1'))
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT ck_asistioexamen
CHECK (asistioexamen in ('0','1'))
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT ck_ingreso
CHECK (ingreso in ('0','1'))
;;
ALTER TABLE Persona.Postulante
add CONSTRAINT ck_puntaje
CHECK (
(asistioexamen = '1' and puntaje >=0)
or
(asistioexamen = '0' and puntaje =0)
)
;;
--6) CREACIÓN DE RESTRICCIONES (UNIQUE):
ALTER TABLE Admision.Carrera
ADD CONSTRAINT uq_nombrecarrera
UNIQUE(Nombre)
;;
ALTER TABLE Persona.Contacto
ADD CONSTRAINT uq_ContactoDNI
UNIQUE(DNI)
;;
ALTER TABLE Admision.Modalidad
ADD CONSTRAINT uq_Modalidad
UNIQUE(Modalidad)
;;
--7) CREACIÓN DE CLAVES PRIMARIAS (PRIMARY KEYS):
ALTER TABLE Admision.PerAcad
ADD CONSTRAINT pk_IDPerAcad
PRIMARY KEY(IDPerAcad)
;;
ALTER TABLE Admision.Carrera
ADD CONSTRAINT pk_IDCarrera
PRIMARY KEY(IDCarrera)
;;
ALTER TABLE Persona.Contacto
ADD CONSTRAINT pk_IDContacto
PRIMARY KEY(IDContacto)
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT pk_IDPostulante
PRIMARY KEY(IDPostulante)
;;
ALTER TABLE Admision.Modalidad
ADD CONSTRAINT pk_IDModalidad
PRIMARY KEY(IDModalidad)
;;
--8) CREACIÓN DE CLAVES FORÁNEAS (FOREIGN KEYS):
ALTER TABLE Persona.Postulante
ADD CONSTRAINT fk_IDCarrera
FOREIGN KEY(idcarrera)
references Admision.Carrera(IDCarrera)
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT fk_IDPerAcad
FOREIGN KEY(IDPerAcad)
references Admision.PerAcad(IDPerAcad)
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT fk_IDModalidad
FOREIGN KEY(IDModalidad)
references Admision.Modalidad(IDModalidad)
;;
ALTER TABLE Persona.Postulante
ADD CONSTRAINT fk_IDContacto
FOREIGN KEY(IDContacto)
references Persona.Contacto(IDContacto)
;;
Descargar Script: PostgreSQL Sentencias DDL.sql

CONCLUSIONES:

–1) CREACIÓN DE BASE DE DATOS (DATABASE):

Con la línea CREATE DATABASE DBAdmision TEMPLATE template0; , se crea una tabla a partir de una plantilla que trae postgres llamada template0, el cual nos crea la base de datos totalmente vacía. También existe la plantilla de nombre template1 y también está limpia.

–2) CREACIÓN DE ESQUEMAS (SCHEMAS) :

Los esquemas son importantes para agrupar objetos  según especificaciones, y al mantener organizado la base de datos permite un mejor desempeño al momento de la administración.

Si no se le asigna un esquema al objeto, postgres lo asignará implicitamente  al esquema “public“. Para definir que un objeto pertenezca a un esquema se pone el nombre del esquema seguido por un ponto <.> y el nombre del objeto, que puede ser una tabla, una secuencia, etc…

–3) CREACIÓN DE SECUENCIAS (SEQUENCE):

Podemos obviar el paso 3, si definimos el tipo de datos de sequencia ‘SERIAL’, en los campos establecidos en la creación de tablas en el paso 4, deberíar las lineas en cuestión de la siguiente forma:

IDContacto int default nextval(‘Persona.seq_idcontacto’),

cambiar por:

IDContacto SERIAL,

también

IDModalidad int default nextval(‘Admision.seq_idmodalidad’),

cambiar por:

IDModalidad SERIAL,

Con estos cambios, no será necesario realizar el paso 3, pero en realidad postgres si realiza implicitamente la creación de sequencias.

–4) CREACIÓN DE TABLAS (TABLES):

Con “FechaCreacion date not null default now(),” asignaremos la fecha actual por defecto al campo FechaCreacion por medio de la función now().

–5) CREACIÓN DE RESTRICCIONES (CHECK):

Los valores dentro de CHECK , por ejemplo “CHECK (Genero in (‘0′,’1′))”, son los únicos que serán permitidos insertar en el campo establecido, en este caso se le asigna esa restricción al campo Genero.

–6) CREACIÓN DE RESTRICCIONES (UNIQUE):

Las restricciones UNIQUE, por ejemplo “UNIQUE(Modalidad)” , aseguran que en los datos en la misma columna, en este caso en el campo Modalidad, no sean repetidas, ya que no puede haber registradas 2 modalidades con el mismo nombre. Otro ejemplo se da en las tablas usuario, donde no permiten asignar el mismo login o nick a a más de una persona.

–7) CREACIÓN DE CLAVES PRIMARIAS (PRIMARY KEYS):

Las claves primarias, aparte de prevenir la duplicidad de datos, y servir como nexo para relacionarse con otras tablas, tiene otro fin también importante, que es agilizar el proceso de busqueda, no por el hecho de ser primary key, sino que al momento de la creación de una clave primaria se crea implícitamente un indice (index), del cual hablaré detalladamente en otro post.

–8) CREACIÓN DE CLAVES FORÁNEAS (FOREIGN KEYS):

Las claves foráneas son campos que servirán de nexo para la relación entre 2 tablas, la clave primaria de otra tabla se relacionará con la clave foránea de ésta.

TOPIC: CREATE, TABLE, SCHEMA, SEQUENCE, ALTER, CHECK, ADD CONSTRAINT, UNIQUE, PRIMARY KEY, FOREIGN KEY, TEMPLATE

RELACIONADOS:





PostgreSQL: Especificación de Ficheros

2 11 2009

El siguiente paso, después de instalar PostgreSQL es revisar lo que contiene los ficheros generados con la instalación de postgres. Es necesario ver los contenidos del directorio data, y entender como están organizados y que es lo que contiene cada uno de ellos.

  • PG_VERSION  – Archivo con la versión de PostgreSQL.
  • base – Directorio  con subdirectorios por cada base de datos.Guía PostgreSQL
  • global – Directorio  con subdirectorios para todo el cluster.
  • pg_clog – Directorio  con datos de transacciones.
  • pg_multixact – Directorio con datos de lockeos compartidos a nivel fila.
  • pg_subtrans – Directorio  con datos de subtransacciones.
  • pg_tblspc – Directorio con links a tablespaces.
  • pg_twophase – Directorio  con archivos de estado para transacciones preparadas.
  • pg_xlog – Directorio  con WAL logs .
  • postmaster.opts – Fichero  con opciones de arranque de postmaster utilizadas.
  • postmaster.pid -  Fichero de lock con el PID del postmaster y el ID de shared mem usado.

Cada tabla o índice esta almacenado en un archivo independiente, los nombres de archivos se pueden consultar en el catálogo.

RELACIONADOS:





PostgreSQL: Fuentes de Instalación

1 11 2009

Intento facilitar información práctica de postgres desde un nivel relativamente básico e ir subiendo de level a medida que pase el tiempo.

Usaremos la versión del motor más reciente hasta hoy. Particularmente suelo descargar de la web de EnterpriseDB o desde PostGreSQL.

Les dejo los links de descarga aquí:

Descargar: PostGreSQL o PostGreSQL

Descargar: PostGres Plus Standard Server

Descargar: PostGres Plus Advanced  Server

Sería bueno que lean las características y diferencias entre todos estos.

Para empezar deberán descargar e instalar PostGreSQL, y sería mejor si instalan PostGres Plus Advanced  Server.

En mi caso, tengo instalado PostGres Plus Advanced  Server8.3R2 en el puerto  5432 y  PostGres Plus Standard Server8.4 el el puerto 5433

También puede instalar la version que vienen en los repositorios de su distro linux:

Gentoo:

emerge -av postgresql

RedHat :

yum install postgresql

Debian/Ubuntu:

apt-get install postgresql postgresql-client
PRINCIPAL: PostgreSQL: Base de Datos

PostgreSQL





PostgreSQL: Base de Datos

31 07 2009

Un tiempo estuve involucrado con PotgreSQL , me gustó mucho, creo que se ha convertido en uno de mis motores de base de datos preferidos, de hecho hay muchas cosas aún que me faltan por conocer acerca de este, de todos modos os anímo a que lo experimenten si no lo han hecho aún.

postgresql

El logo lo dice todo, la robustéz que posee hace sentirse seguró, y hasta donde he experimentado ha tenido un rendimiento muy pero muy bueno.

Lo encontrarás en versiones para diferentes plataformas, como: FreeBSD · Linux · Mac OS X · Solaris · Windows,  y además está licenciado bajo BSD, el cual permite que las aplicaciones que desarrolles haciendo uso de Postgres podrias hacerlo con fines comerciales si ningún problema.

Hay diversos gestores para manipularlo, uno de ellos por ejemplo Postgres Plus de EnterpriseDB, inclusive su advanced server, manejan por separado las funciones y los procedimientos almacenados, y algo super interesante es que està diseñado para soportar multilenguajes procedurales, es decir, tus procedimientos almacenados los puedes realizar en PL/Java, PL/Ruby, PL/psm, PL/scheme, plPHP, PL/pgSQL, PL/Tcl, PL/Perl, PL/Python, alguno de estos ya los trae por defecto.

En esta entrada realizaré demostraciones con PostGreSQL, y este post será actualizado a medida que añada nuevos topics.

Demostraciones con PostGreSQL:





Funciones y Procedimientos en Postgres

31 07 2009

Este post fue actualizado en una nueva categoría.

Actualizado en: PostgreSQL: Funciones, Procedimientos y Vistas





Ahorrar más, Ganar más y Cobrar menos al cliente

10 07 2009

Trabajando, estudiando y escribiendo de ‘mes’ en cuando :) ……

Este cuadro lo hicimos para tener una propuesta alternativa  al  desarrollo con .NET.

Los precios fueron cotizados por un amigo ya hace algún tiempo, y creo que faltan algunas especificaciones en cuanto a la norvatividad de las licencias, pero solo es para dar una idea.

desarrollo software bajo net

Para desarrollar un proyecto optamos por el paquete 2 , solo que .NET Framework era parte de los requerimientos del docente de la facultad, creo que pronto estará portado totalmente para funcionar con mono.