4. Creacion y manipulacion de tablas

4. Creacion y manipulacion de tablas Dataprix 21 Octubre, 2009 - 11:00

4.1. Creacion de tablas

4.1. Creacion de tablas Dataprix 21 Octubre, 2009 - 11:35

Una vez conectados a una base de datos, la sentencia SQL create table permite crear las tablas que necesitemos:

demo=#   create table persona (
demo(#   nombre varchar(30),
demo(#   direccion varchar(30)
demo(# );
CREATE

El comando drop table permite eliminar tablas:

demo=# drop table persona;

La tabla recién creada aparece ahora en la lista de tablas de la base de datos en uso:

demo=# \dt
List of relations
Name     |Type   |Owner
---------+-------+--------
persona | table | quiron
(1 row)

Podemos consultar su descripción mediante el comando \d tabla:

demo=# \d persona
Table "persona"
Column     |Type                   | Modifiers
-----------+-----------------------+-----------
   nombre  | character varying(30) |
direccion | character varying(30) |

 

La tabla está lista para insertar en ella algunos registros.

demo=# insert into persona values ( `Alejandro Magno´ , `Babilonia´ );
INSERT 24756 1
demo=# insert into persona values ( `Federico García Lorca´ , `Granada 65´ );
INSERT 24757 1

 

Este aspecto se explicará en detalle más adelante.

El número con el que responde el comando insert se refiere al OID del registro insertado.

Las consultas se realizan con la sentencia SQL select. En este caso solicitamos que nos muestre todas las columnas de los registros en la tabla persona:

demo=# select * from persona;
nombre                 |direccion
-----------------------+------------
Alejandro Magno       | Babilonia
Federico García Lorca | Granada 65
(2 rows)
demo=#

Las tablas creadas en PostgreSQL incluyen, por defecto, varias columnas ocultas que almacenan información acerca del identificador de transacción en que pueden estar implicadas, la localización física del registro dentro de la tabla (para localizarla muy rápidamente) y, los más importantes, el OID y el TABLE OID. Estas últimas columnas están definidas con un tipo de datos especial llamado  identificador  de  objeto  (OID)  que  se  implementa  como  un  entero positivo de 32 bits. Cuando se inserta un nuevo registro en una tabla se le asigna un número consecutivo como OID, y el TABLEOID de la tabla que le corresponde.

En la programación orientada a objetos, el concepto de OID es de vital importancia, ya que se refiere a la identidad propia del objeto, lo que lo diferencia de los demás objetos.

Para observar las columnas ocultas, debemos hacer referencia a ellas específicamente en el comando select:

demo=# select oid, tableoid, * from persona;
oid    |tableoid  |nombre                  |direccion
-------+----------+------------------------+----------------------
17242 | 17240    | Alejandro Magno        | Babilonia
17243 | 17240    | Federico García Lorca  | Granada 65
(2 rows)
demo=#
Estas columnas se implementan para servir de identificadores en la realización de enlaces desde otras tablas.

Ejemplo de la utilización de OID para enlazar dos tablas

Retomamos la tabla persona y construimos una nueva tabla para almacenar los teléfonos.

demo=# create table telefono (
demo(# tipo char(10),
demo(# numero varchar(16),
demo(# propietario oid
demo(# );
CREATE

La tabla teléfono incluye la columna propietario de tipo OID, que almacenará la referencia a los registros de la tabla persona. Agreguemos dos teléfonos a ‘Alejandro Magno’, para ello utilizamos su OID que es 17242:

demo=# insert into telefono values( `móvil´ , `12345678´, 17242 );
demo=# insert into telefono values( `casa´ , `987654´, 17242 );

Las dos tablas están vinculadas por el OID de persona.

demo=# select * from telefono;
tipo        |numero       | propietario
------------+-------------+-------------
      móvil |    12345678 |   17242
       casa |      987654 |   17242
(2 rows)

La operación que nos permite unir las dos tablas es join, que en este caso une teléfono y persona, utilizando para ello la igualdad de las columnas telefono.propietario y persona.oid:

demo=# select * from telefono join persona on (telefono.propietario = persona.oid);
tipo        |numero       | propietario |nombre           | direccion
------------+-------------+-------------+-----------------+-----------
      móvil |    12345678 |       17242 | Alejandro Magno | Babilonia
       casa |      987654 |       17242 | Alejandro Magno | Babilonia
(2rows)

Los OID de PostgreSQL presentan algunas deficiencias:

•    Todos los OID de una base de datos se generan a partir de una única secuencia centralizada, lo que provoca que en bases de datos con mucha actividad de inserción y eliminación de registros, el contador de 4 bytes se desborde y pueda entregar OID ya entregados. Esto sucede, por supuesto, con bases de datos muy grandes.

•    Las tablas enlazadas mediante OID no tienen ninguna ventaja al utilizar operadores de composición en términos de eficiencia respecto a una clave primaria convencional.

•    Los OID no mejoran el rendimiento. Son, en realidad, una columna con un número entero como valor.

Los desarrolladores de PostgreSQL proponen la siguiente alternativa para usar OID de forma absolutamente segura:

•    Crear una restricción de tabla para que el OID sea único, al menos en cada tabla. El SGBD irá incrementando secuencialmente el OID hasta encontrar uno sin usar.

•    Usar la combinación OID - TABLEOID si se necesita un identificador único para un registro válido en toda la base de datos.

Por los motivos anteriores, no es recomendable el uso de OID hasta que nuevas versiones de PostgreSQL los corrijan. En caso de usarlos, conviene seguir las recomendaciones anteriores.

 

Es posible crear tablas que no incluyan la columna OID mediante la siguiente notación:

create table persona (
nombre varchar(30),
direccion varchar(30)
)without oids;

 

4.2. Herencia

4.2. Herencia Dataprix 21 Octubre, 2009 - 11:45

PostgreSQL ofrece como característica particular la herencia entre tablas, que permite definir una tabla que herede de otra previamente definida, según la definición de herencia que hemos visto en capítulos anteriores.

Retomemos la tabla persona definida como sigue:

create table persona (
nombre varchar (30),
direccion varchar (30)
);

A partir de  esta  definición, creamos la tabla estudiante  como derivada de persona:

create table estudiante (
demo(# carrera varchar(50),
demo(# grupo char,
demo(# grado int
demo(# ) inherits ( persona );
CREATE

 

En la tabla estudiante se definen las columnas carrera, grupo y grado, pero al so- licitar información de la estructura de la tabla observamos que también inclu- ye las columnas definidas en persona:

demo=# \d estudiante
Table "estudiante"
Column     |Type                   | Modifiers
-----------+-----------------------+-----------
    nombre | character varying(30) |
direccion | character varying(30) |
   carrera | character varying(50) |
     grupo |          character(1) |
     grado |               integer |

En este caso, a la tabla persona la llamamos padre y a la tabla estudiante, hija.

Cada registro de la tabla estudiante contiene 5 valores porque tiene 5 columnas:

demo=# insert into estudiante values (
demo(# `Juan´ ,
demo(# `Treboles 21´,
demo(# `Ingenieria en Computacion´,
demo(# `A´,
demo(# 3
demo(# );
INSERT 24781 1
La herencia no sólo permite que la tabla hija contenga las columnas de la tabla padre, sino que establece una relación conceptual es-un.

La consulta del contenido de la tabla estudiante mostrará, por supuesto, un solo registro. Es decir, no se heredan los datos, únicamente los campos (atributos) del objeto:

demo=# select * from estudiante;
nombre  |direccion    |carrera                    |grupo  | grado
--------+-------------+---------------------------+-------+-------
   Juan | Treboles 21 | Ingenieria en Computacion |     A | 3
(1 row)

Además, la consulta de la tabla persona mostrará un nuevo registro:

 

demo=# select * from persona;
nombre                 | direccion
-----------------------+-------------
  Federico Garca Lorca | Granada 65
       Alejandro Magno | Babilonia
                  Juan | Treboles 21
(3 rows)

El último registro mostrado es el que fue insertado en tabla estudiante, sin embargo la herencia define una relación conceptual en la que un estudiante es-una persona. Por lo tanto, al consultar cuántas personas están registradas en la base de datos, se incluye en el resultado a todos los estudiantes. Para consultar sólo a las personas que no son estudiantes, podemos utilizar el modificador ONLY:

demo=# select * from only persona;
nombre                 | direccion
-----------------------+------------
       Alejandro Magno | Babilonia
Federico García Lorca | Granada 65
(2 rows)
demo=#
No es posible borrar una tabla padre si no se borran primero las tablas hijo.
demo=# drop table persona;
NOTICE: table estudiante depende de table persona
ERROR: no se puede eliminar table persona porque otros objetos dependen de él
HINT: Use DROP ... CASCADE para eliminar además los objetos dependientes.

Como es lógico, al borrar la fila del nuevo estudiante que hemos insertado, se borra de las dos tablas. Tanto si lo borramos desde la tabla persona, como si lo borramos desde la tabla estudiante.

4.3. Herencia y OID

4.3. Herencia y OID Dataprix 21 Octubre, 2009 - 16:08

Los OID permiten que se diferencien los registros de todas las tablas, aunque sean heredadas: nuestro estudiante tendrá el mismo OID en las dos tablas, ya que se trata de única instancia de la clase estudiante:

 

demo=# select oid,* from persona ;
oid    |nombre                 | direccion
-------+-----------------------+-------------
17242 | Alejandro Magno       | Babilonia
17243 | Federico García Lorca | Granada 65
17247 | Juan                  | Treboles 21
(3 rows)
demo=# select oid,* from estudiante ;
oid    |nombre  |direccion    |carrera                    |grupo  | grado
-------+--------+-------------+---------------------------+-------+-------
17247  | Juan   | Treboles 21 | Ingenieria en Computación | A     |   3
(1 row)

Dado que no se recomienda el uso de OID en bases muy grandes, y debe incluirse explícitamente en las consultas para examinar su valor, es conveniente utilizar una secuencia compartida para padres y todos sus descendientes si se requiere un identificador.

En PostgreSQL, una alternativa para no utilizar los OID es crear una columna de tipo serial en la tabla padre, así será heredada en la hija. El tipo serial define una secuencia de valores que se irá incrementando de forma automática, y por lo tanto constituye una buena forma de crear claves primarias, al igual que el tipo AUTO_INCREMENT en MySQL.

demo=# create table persona (
demo(# id serial,
demo(# nombre varchar (30),
demo(# direccion varchar(30)
demo(# ) without oids;
NOTICE: CREATE TABLE will create implicit sequence `persona_id_seq´ for SERIAL column `persona.
NOTICE: CREATE TABLE / UNIQUE will create implicit index `persona_id_key´ for table `persona´ CREATE

La columna id se define como un entero y se incrementará  utilizando la función nextval() tal como nos indica la información de la columna:

demo=# \d persona
Table "persona"
Column   |Type                 |Modifiers
---------+---------------------+---------------------------------------------
       id|             integer |not null default nextval(`"persona_id_seq"`::text)
   nombre|character varying(30)|
direccion|character varying(30)|
Unique keys: persona_id_key

 

Al definir un tipo serial, hemos creado implícitamente una secuencia independiente de la tabla. Podemos consultar las secuencias de nuestra base de datos mediante el comando ‘\ds’:

demo=# \ds

                  List of relations

Schema |Name                 |Type      |Owner
--------+---------------------+----------+----------
public | productos_clave_seq | sequence | postgres
(1 row)

Creamos nuevamente la tabla estudiante heredando de persona:

create table estudiante (
demo(# carrera varchar(50),
demo(# grupo char,
demo(# grado int
demo(# ) inherits ( persona );
CREATE

El estudiante heredará la columna id y se incrementará utilizando la misma secuencia:

demo=# \d persona
Table "persona"
Column   |Type                 |Modifiers
---------+---------------------+---------------------------------------------
       id|             integer |not null default next-val(`"persona_id_seq"`::text)
   nombre|character varying(30)|
direccion|character varying(30)|
carrera |character varying(50)|
   grupo |         character(1)|
   grado |              integer|

Insertaremos en la tabla algunos registros de ejemplo, omitiendo el valor para la columna id:

demo=# insert into persona(nombre,direccion)
values ( `Federico García Lorca´ , `Granada 65´ );
demo=# insert into persona(nombre,direccion)
values ( `Alejandro Magno´ , `Babilonia´ );
demo=# insert into estudiante(nombre,direccion,carrera,grupo,grado)
values ( `Elizabeth´ , `Pino 35´, `Psicologia´ , `B´ , 5 );

 

La tabla estudiante contendrá un  solo registro, pero su identificador es el número 3.

demo=# select * from estudiante;
id |nombre     |direccion  |carrera     |grupo  |grado
---+-----------+-----------+------------+-------+-------
3  | Elizabeth | Pino 35   | Psicologia |   B   |  5
(1 row)

Todos los registros de persona siguen una misma secuencia sin importar si son padres o hijos:

demo=# select * from persona;
id |nombre                |direccion
----+----------------------+------------
  1 | Federico Garca Lorca | Granada 65
  2 |      Alejandro Magno | Babilonia
  3 |            Elizabeth | Pino 35
(3 rows)

La herencia es útil para definir tablas que conceptualmente mantienen elementos en común, pero también requieren  datos que los hacen diferentes. Uno de los elementos que conviene definir como comunes son los identificadores de registro.

4.4. Restricciones

4.4. Restricciones Dataprix 22 Octubre, 2009 - 11:55

Como ya sabemos, las restricciones permiten especificar condiciones que deberán cumplir tablas o columnas para mantener la integridad de sus datos. Algunas de las restricciones vendrán impuestas por el modelo concreto que se esté implementando, mientras que otras tendrán su origen en las reglas de negocio del cliente, los valores que pueden tomar algunos campos, etc.

 

Ejemplo                                                 
Una columna definida como integer no puede contener cadenas de         caracteres.                                            

Los valores que puede contener una columna están restringidos en primer lugar por el tipo de datos. Ésta no es la única restricción que se puede definir para los valores en una columna, PostgreSQL ofrece las restricciones siguientes:

•    null y not null. En múltiples ocasiones el valor de una columna es desconocido, no es aplicable o no existe. En estos casos, los valores cero, cadena vacía o falso son inadecuados, por lo que utilizamos null para especificar la ausencia de valor. Al definir una tabla podemos indicar qué columnas podrán contener valores nulos y cuáles no.

create table Persona (
nombre varchar(40) not null,
trabajo varchar(40) null,
correo varchar(20),
);

 

El nombre de una persona no puede ser nulo, y es posible que la persona no tenga trabajo. También es posible que no tenga correo, al no especificar una restricción not null, se asume que la columna puede contener valores nulos.

 

•    unique. Esta restricción se utiliza cuando no queremos que los valores contenidos en una columna puedan duplicarse.

create table Persona (
nombre varchar(40) not null,
conyuge varchar(40) unique,
);

 

cónyuge no puede contener valores duplicados, no permitiremos que dos personas tengan simultáneamente el mismo cónyuge.

 

•    primary key. Esta restricción especifica la columna o columnas que elegimos como clave primaria. Puede haber múltiples columnas unique, pero sólo debe haber una clave primaria. Los valores que son únicos pueden servir para identificar una fila de la tabla de forma unívoca, por lo que se les denomina claves candidatas.

 

create table Persona (
nss varchar(10) primary key, conyuge varchar(40) unique,
);

 

Al definir una columna como primary key, se define implícitamente con unique. El nss (número de la seguridad social) no sólo es único, sino que lo utilizamos para identificar a las personas.

 

•    references y foreign key. En el modelo relacional, establecemos las relaciones entre entidades mediante la inclusión de claves foráneas en otras relaciones. PostgreSQL y SQL ofrecen mecanismos para expresar y mantener esta  integridad  referencial.  En  el  siguiente  ejemplo,  las  Mascotas  tienen como dueño a una Persona:

create table Mascota(
nombre varchar(20),
dueño varchar(10) references Persona,
);

 

Una referencia por defecto es a una clave primaria, por lo que dueño se refiere implícitamente al nss de Persona. Cuando se capturen los datos de una nueva mascota, PostgreSQL verificará que el valor de dueño haga referencia a un nss que exista en Persona, en caso contrario emitirá un mensaje de error. En otras palabras, no se permite asignar a una mascota un dueño que no exista.

También es posible especificar a qué columna de la tabla hace referencia:

create table Mascota(
nombre varchar(20),
dueño varchar(10) references Persona(nss),
);

o su equivalente:

create table Mascota(
nombre varchar(20),
dueño varchar(10),
FOREIGN KEY dueño references Persona(nss),
);

Podría darse el caso de que la clave primaria de la tabla referenciada tuviera más de una columna, en ese caso, la clave foránea también tendría que estar formada por el mismo número de columnas:

create table t1 (
   a integer PRIMARY KEY,
   b integer,
   c integer,
   FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)
);

Si no se especifica otra acción, por omisión la persona que tenga una mascota no puede ser eliminada, porque la mascota se quedaría sin dueño. Para poder eliminar una persona, antes se deben eliminar las mascotas que tenga. Este comportamiento no parece ser el más adecuado para el caso.

Para modificar este comportamiento disponemos de las reglas de integridad referencial del lenguaje SQL, que PostgreSQL también soporta. En el siguiente ejemplo se permite que al eliminar una persona, las mascotas simplemente se queden sin dueño.

create table Mascota (
dueño varchar(10) references Persona on delete set null,
);

 

En cláusula on delete se pueden especificar las siguientes acciones:

–    set null. La referencia toma el valor NULL: si se elimina Persona su Mascota se quedará sin dueño.

–    set default. La referencia toma el valor por omisión.

–    cascade. La acción se efectúa en cascada: si se elimina Persona automáticamente se elimina su Mascota.

–    restrict. No permite el borrado del registro: no se puede eliminar una Persona que tenga Mascota. Ésta es la acción que se toma por omisión.

Si se modifica la clave primaria de la tabla referenciada, se dispone de las mismas acciones que en el caso anterior, que especificaremos con la cláusula ON UPDATE.

•    check. Esta restricción realiza la evaluación previa de una expresión lógica cuando  se  intenta  realizar  una  asignación.  Si  el  resultado  es  verdadero, acepta el valor para la columna, en caso contrario, emitirá un mensaje de error y rechazará el valor.

create table Persona (
edad int check( edad > 10 and edad < 80 ),
correo varchar(20) check( correo ~ `.+@.+\..+´ ),
ciudad varchar(30) check( ciudad <>" )
);
Comparación                                        
de expresiones regulares                    
El operador ~ realiza compara- ciones de cadenas con expre- siones regulares.
Las expresiones regulares son patrones de búsqueda muy flexibles desarrollados
en el mundo Unix.

 

Se han restringido los valores que se aceptarán en la columna de la manera siguiente.

•  Edad debe estar entre 11 y 79 años.
•  Ciudad no debe una cadena vacía.
•  Correo debe tener una arroba.

 

Cualquiera de esas restricciones puede tener nombre, de manera que se facilita la  referencia  a  las  restricciones  específicas  para  borrarlas,  modificarlas,  etc. pues puede hacerse por nombres. Para dar nombre a una restricción, utilizamos la sintaxis siguiente:

constraint nombre_de_restricción

4.4.1. Restricciones de tabla

4.4.1. Restricciones de tabla Dataprix 23 Octubre, 2009 - 11:16

Cuando las restricciones se indican después de las definiciones de las columnas, y pueden afectar a varias de ellas simultáneamente, se dice que son restricciones de tabla:

 

create table Persona (
nss int,
nombre varchar(30),
pareja varchar(30),
jefe int,
correo varchar(20),
primary key (nss),
unique (pareja),
foreign key (jefe) references Persona,
check (correo ~ `@´ )
);

Esta notación permite que la restricción pueda abarcar varias columnas.

create table Curso (
materia varchar(30),
grupo char(4),
dia int,
hora time,
aula int,
primary key (materia, grupo),
unique (dia, hora, aula)
);

 

Un curso se identifica por el grupo y la materia, y dos cursos no pueden estar en la misma aula el mismo día y a la misma hora.

Al igual que la restricción de columna, a las restricciones de tabla puede asignárseles un nombre:

create table Persona (
nss int,
nombre varchar(30),
pareja varchar(30),
jefe int,
correo varchar(20),
constraint identificador primary key (nss),
constraint monogamia unique (pareja),
constraint un_jefe foreign key (jefe) references Persona,
check (correo ~ `@´ )
);

La sentencia alter table permite añadir (add) o quitar (drop) restricciones ya definidas:

alter table Persona drop constraint monogamia
alter table add constraint monogamia unique (pareja);

4.5. Indexacion

4.5. Indexacion Dataprix 23 Octubre, 2009 - 11:18

PostgreSQL crea índices para las llaves primarias de todas las tablas. Cuando se necesite crear índices adicionales, utilizaremos la expresión del ejemplo siguiente:

create index persona_nombre_indice on Persona ( nombre );

 

4.6. Consulta de informacion de bases de datos y tablas

4.6. Consulta de informacion de bases de datos y tablas Dataprix 23 Octubre, 2009 - 11:49

Como ya sabemos, el cliente psql ofrece varias alternativas para obtener información sobre la estructura de nuestra base de datos. En la siguiente tabla se muestran algunos comandos de mucha utilidad.

Comando Descripción
\1 Lista las bases de datos
\d Describe las tablas de la base de datos en uso
\ds Lista las secuencias
\di Lista los índices
\dv Lista las vistas
\dp \z Lista los privilegios sobre las tablas
\da Lista las funciones de agregados
\df Lista las funciones
\g archivo Ejecuta los comandos de archivo
\H Cambia el modo de salida HTML
\! comando Ejecuta un comando del sistema operativo

Para obtener la lista de tablas de la base de datos demo hacemos lo siguiente:

 

demo=# \d
List of relations
Name                 |Type      | Owner
---------------------+----------+--------
            ganancia |    table | postgres
             precios |    table | postgres
           productos |    table | postgres
productos_clave_seq | sequence | postgres
         proveedores |    table | postgres
(5 rows)

 

La estructura de la tabla productos se solicita de la siguiente manera.

 

demo=# \d productos
Table "productos"
Column        |Type                 | Modifiers
--------------+---------------------+-------------------------------------------            
        parte |character varying(20)|
         tipo |character varying(20)|
especificación|character varying(20)|
    psugerido |                real |
        clave |             integer |not null default nextval 
                                     (`"productos_clave_seq"´::text)
Primary key: productos_pkey
Triggers: RI_ConstraintTrigger_17342,
RI_ConstraintTrigger_17344

 

En el ejemplo anterior podemos observar que la columna clave contiene dos modificadores:

•    El primero especifica que no pueden asignarse valores nulos.

•    El segundo especifica el valor por omisión que deberá asignarse a la columna.
 

* Una secuencia es un nombre          especial que permite la producción   de series numéricas.                           

En este caso, el valor será automáticamente calculado por la función nextval(), que toma como argumento la secuencia* productos_clave_seq.

El siguiente comando muestra las secuencias creadas en una base de datos:

demo=# \ds
List of relations
Name                 |Type      | Owner
---------------------+----------+--------
productos_clave_seq | sequence | quiron
(1 row)

Las  secuencias  se  crean  automáticamente  cuando  se  declaran  columnas  de tipo serial.

 

En la estructura de la tabla productos encontramos también una clave primaria. PostgreSQL generará siempre un índice para cada tabla utilizando la clave primaria. La lista de los índices de la base de datos se obtiene de la siguiente forma:

demo=# \di
List of relations
Name              | Type  | Owner
------------------+-------+--------
productos_pkey    | index | quiron
proveedores_pkey  | index | quiron
(2 rows)

El  conjunto  de  comandos  proporcionados  por  psql  que  hemos  presentado permite obtener información sobre la estructura de nuestra base de datos de una manera directa y sencilla y, también, es útil para explorar bases de datos que no conozcamos.

4.7. Tipos de datos

4.7. Tipos de datos Dataprix 23 Octubre, 2009 - 13:48

4.7.1. Tipos logicos

4.7.1. Tipos logicos Dataprix 23 Octubre, 2009 - 13:54

PostgreSQL incorpora el tipo lógico boolean, también llamado bool. Ocupa un byte de espacio de almacenamiento y puede almacenar los valores falso y verdadero.

Valor Nombre
Falso false, ‘f’, ‘n’, ‘no’, 0
Verdadero true, ‘t’, ‘y’, ‘yes’, 1

PostgreSQL soporta los operadores lógicos siguientes: and, or y not.

Aunque los operadores de comparación se aplican sobre prácticamente todos los tipos de datos proporcionados por PostgreSQL, dado que su resultado es un valor lógico, describiremos su comportamiento en la siguiente tabla:

Operador Descripción
> Mayor que
<    Menor que   
<= Menor o igual que
>= Mayor o igual que

<>

!=

Distinto de

 

4.7.2. Tipos numericos

4.7.2. Tipos numericos Dataprix 23 Octubre, 2009 - 14:08

PostgreSQL dispone de los tipos enteros smallint, int y bigint que se comportan como lo hacen los enteros en muchos lenguajes de programación.

Los números con punto flotante real y double precisión almacenan cantidades con decimales. Una característica de los números de punto flotante es que pierden exactitud conforme crecen o decrecen los valores.

Aunque esta pérdida de exactitud no suele tener importancia en la mayoría de las  ocasiones,  PostgreSQL  incluye  el  tipo  numeric,  que  permite  almacenar cantidades muy grandes o muy pequeñas sin pérdida de información. Por supuesto, esta ventaja tiene un coste, los valores de tipo numeric ocupan un espacio  de  almacenamiento  considerablemente  grande  y  las  operaciones  se ejecutan sobre ellos muy lentamente. Por lo tanto, no es aconsejable utilizar el tipo numeric si no se necesita una alta precisión o se prima la velocidad de procesamiento.

 

Nombre Tamaño Otros nombres Comentario
smallint 2 bytes int2
int 4 bytes int4, integer
bigint 8 bytes int8
numeric(p,e) 11 + (p/2) ‘p’ es la precisión, ‘e’ es la escala
real 4 bytes float, float4
double precision 8 bytes float8
serial No es un tipo, es un entero autoincrementable

Serial

La declaración serial es un caso especial, ya que no se trata de un nuevo tipo. Cuando se utiliza como nombre de tipo de una columna, ésta tomará automáticamente valores consecutivos en cada nuevo registro.

Ejemplo de una tabla que define la columna folio como tipo serial.

create table Factura(
folio serial,
cliente varchar(30),
monto real
);

PostgreSQL respondería esta instrucción con dos mensajes:

•  En el primero avisa que se ha creado una secuencia de nombre factura_folio_seq:

NOTICE: CREATE TABLE will create implicit sequence `factura_folio_seq´ for SERIAL column `

•  En el segundo avisa de la creación de un índice único en la tabla utilizando la columna folio:

 

NOTICE: CREATE TABLE / UNIQUE will create implicit index `factura_folio_key´ for table `factura´ CREATE

Si se declaran varias columnas con serial en una tabla, se creará una secuencia y un índice para cada una de ellas.

 

4.7.3. Operadores numericos

4.7.3. Operadores numericos Dataprix 23 Octubre, 2009 - 14:12

PostgreSQL ofrece un conjunto predefinido de operadores numéricos, que presentamos en la siguiente tabla:

 

Ejemplo

select |/ 9;
select 43 % 5;
select !! 7;
select 7!;

 Símbolo  Operador
 +    Adición   
 -  Substracción
 *  Multiplicación
 /  División
 %  Módulo   
 ^  Exponenciación   
 |/   Raíz cuadrada
 ||/   Raíz cúbica
 !  Factorial
 !!   Factorial como operador fijo
 @    Valor absoluto   
 &    AND binario   
 |      OR binario   
 #    XOR binario   
 ~   Negación binaria
<<   Corrimiento binario a la izquierda
 >>   Corrimiento binario a la derecha

 

4.7.4. Tipos de caracteres

4.7.4. Tipos de caracteres Dataprix 23 Octubre, 2009 - 15:46
Recordad
Las comillas dobles delimitan identificadores que contienen caracteres especiales.

Los valores de cadena en PostgreSQL se delimitan por comillas simples.

demo=# select `Hola mundo´;
?column?
------------
Hola mundo
(1 row)

Se puede incluir una comilla simple dentro de una cadena con \’ o ‘ ‘:

demo=# select `Él dijo: `"Hola"´
?column?
------------------
Él dijo: `Hola´
(1 row)

Las cadenas pueden contener caracteres especiales utilizando las llamadas secuencias de escape que inician con el caracter ‘\’:

 

\n nueva línea
\r retorno de carro
\t tabulador
\b retroceso
\f cambio de página
\r retorno de carro
\\ el caracter \

 

Las secuencias de escape se sustituyen por el carácter correspondiente:

demo=# select `Esto está en \n dos renglones´;
?column?
------------------------------
Esto está en
dos renglones
(1 row)

PostgreSQL ofrece los tipos siguientes para cadenas de caracteres:

Tipo Otros nombres Descripción
char(n) character(n) Reserva n espacios para almacenar la cadena
varchar(n) character var-ying(n) Utiliza los espacios necesarios para almacenar una cadena menor o igual que n
text Almacena cadenas de cualquier magnitud

4.7.5. Operadores

4.7.5. Operadores Dataprix 23 Octubre, 2009 - 16:03

En la siguiente tabla se describen los operadores para cadenas de caracteres:

Operador Descripción ¿Distingue mayúsculas y minúsculas?
|| Concatenación -
~ Correspondencia a expresión regular
~* Correspondencia a expresión regular No
!~ No correspondencia a expresión regular
!~* No correspondencia a expresión regular -

 

Bibliografía
Es recomendable consultar el             manual para obtener la referencia      completa de funciones.                      

En la siguiente tabla se muestran algunas funciones de uso común sobre cadenas de caracteres:

 

Función Descripción
Length(cadena) Devuelve la longitud de la cadena
lower(cadena) Convierte la cadena a minúsculas
ltrim(cadena,caracteres) Elimina de la izquierda los caracteres specificados
substring(cadena from patrón) Extrae la subcadena que cumple el patrón especificado

Sobre las cadenas también podemos utilizar los operadores de comparación que ya conocemos.

 

Ejemplo

En este caso, el resultado de la comparación menor que es VERDADERO:

demo=# select `HOLA´ &lt; `hola´;
?column?
----------
(1 row)

4.7.6. Fechas y horas

4.7.6. Fechas y horas Dataprix 26 Octubre, 2009 - 10:46

En la siguiente tabla se muestran los tipos de datos referentes al tiempo que ofrece PostgreSQL:

 

Tipo de dato Unidades Tamaño Descripción Precisión
date día-mes-año 4 bytes Fecha Día
time hrs:min:seg:micro 4 bytes Hora Microsegundo
timestamp día-mes-año hrs:min:seg:micro 8 bytes Fecha más hora Microsegundo
interval second, minute, hour, day, week, month, year, decade, century, millennium* 12 bytes Intervalo de tiempo Microsegundo

                                                                                                                                                                            

* También admite abreviaturas.

Existe un tipo de dato timez que incluye los datos del tipo time y, además, la zona horaria. Su sintaxis es la siguiente:

hh:mm[:ss[.mmm]][am|pm][zzz]

El tipo de datos date almacena el día, mes y año de una fecha dada y se muestra por omisión con el formato siguiente: YYYY-MM-DD:

demo=# set datestyle = `german´;
SET VARIABLE
demo=# select * from persona;
nacimiento
------------
22.05.2004
(1 row)

Para cambiar el formato de presentación, debemos modificar la variable de entorno datestyle:

 

demo=# create table Persona ( nacimiento date );
CREATE
demo=# insert into persona values ( `2004-05-22´ );
INSERT 17397 1
demo=# select * from persona;
nacimiento
------------
2004-05-22
(1 row)

Nombre
del
formato

Formato Ejemplo
ISO Año-mes -día 2004-05-22
GERMAN Día-mes-año 22-05-2004
PORTUGUES día-mes-año 22-05-2004
SQL mes/día/año 05/22/2004

 

4.7.7. Arrays

4.7.7. Arrays Dataprix 26 Octubre, 2009 - 11:18

El tipo de datos array es una de las características especiales de PostgreSQL, permite el almacenamiento de más de un valor del mismo tipo en la misma columna.

Definición
Los arrays no cumplen la pri-   mera forma normal de Cood,     por lo que muchos los               consideran inaceptables en el  modelo relacional.                     

 

demo=# create table Estudiante (
demo(# nombre varchar(30),
demo(# parciales int [3]
demo(# );
CREATE

 

La columna parciales acepta tres calificaciones de los estudiantes.

 

También es posible asignar un solo valor del array:

demo=# insert into Estudiante( nombre, parciales[2]) values ( `Pedro´ ,`{90}´); INSERT 17418 1
demo=# select * from Estudiante ;
nombre      | parciales
------------+------------
John Lennon |
Juan        | {90,95,97}
Pedro       | {90}
(3 rows)

Los arrays, al igual que cualquier columna cuando no se especifica lo contrario, aceptan valores nulos:

demo=# insert into Estudiante values ( `John Lennon´ );
INSERT 17416 1
demo=# insert into Estudiante values ( `Juan´ , `{90,95,97}´ );
INSERT 17417 1

Los valores del array se escriben siempre entre llaves.

 

demo=# select * from Estudiante;
nombre        | parciales
--------------+------------
John Lennon   |
Juan          | {90,95,97}
(2 rows)

Para seleccionar un valor de un array en una consulta se especifica entre corchetes la celda que se va a desplegar:

 

Sólo Juan tiene calificación en el tercer parcial.                                 

demo=# select nombre, parciales[3] from Estudiante;
nombre        | parciales
--------------+-----------
John Lennon   |
Juan          | 97
Pedro         |
(3 rows)

 

La columna parciales del registro       Pablo incluye cuatro celdas y sólo    la última tiene valor.                            

En muchos lenguajes de programación, los array se implementan con longitud fija, PostgreSQL permite aumentar su tamaño dinámicamente:
 

 

demo=# insert into Estudiante( nombre, parciales[4]) values ( `Pablo´ , `{70}´); INSERT 17419 1
demo=# select * from Estudiante;
nombre        | parciales
--------------+------------
John Lennon   |
Juan          | {90,95,97}
Pedro         | {90}
Pablo         | {70}
(4 rows)

Mediante la función array_dims() podemos conocer las dimensiones de un array:

demo=# select nombre, array_dims(parciales) from Estudiante;
nombre        | array_dims
--------------+------------
John Lennon   |
Juan          | [1:3]
Pedro         | [1:1]
Pablo         | [1:1]
(4 rows)

 

4.7.8. BLOB

4.7.8. BLOB Dataprix 26 Octubre, 2009 - 11:44

El tipo de datos BLOB (Binary Large OBject) permite almacenar en una columna un objeto de gran tamaño. PostgreSQL no conoce nada sobre el tipo de información que se almacena en una columna BLOB, simplemente lo considera como una secuencia de bytes. Por este motivo, no se tienen operaciones sobre los tipos BLOB, con la excepción del operador de concatenación, que simplemente une el contenido de dos BLOB en uno.

Veamos cómo almacenar una fotografía en una tabla de personas mediante tipos BLOB.

Una primera manera de hacerlo es importando el contenido del archivo que contiene la imagen mediante la función lo_import():

demo=# select lo_import(`/home/quiron/mi-foto.jpg´);
lo_import
-----------
17425
(1 row)

 

Esta función devuelve como resultado el OID del objeto insertado.¿Dónde se ha almacenado la fotografía si no hemos utilizado el comando insert? Post- greSQL mantiene una tabla de nombre pg_largeobject con el objetivo de almacenar BLOB. Podemos utilizar el OID para hacer referenciar al objeto en una tabla:

demo=# create table persona (
demo(# nombre varchar(30),
demo(# direccion varchar(30),
demo(# fotografia oid
demo(# );
CREATE

Los registros insertados en esta tabla llevan un número entero como OID que, en el siguiente caso, se ha obtenido solicitándolo a la función lo_import() anterior.

demo=# insert into persona values (`Julio´ , `Cedro 54´, 17425);

La inserción anterior pudo haberse realizado en un solo paso:

 

demo=# insert into persona
values ( `Julio´ , `Cedro 54´, lo_import(`/home/quiron/mi-foto.jpg´));

Para extraer el contenido de la columna, se utiliza la función lo_export()

demo=# select lo_export(17425,`/tmp/mi-foto.jpg´);
lo_export
-----------
1
(1 row)

La función lo_unlink() permite borrar un BLOB almacenado en pg_largeobject:

select lo_unlink(17425);

 

Veamos el formato que utiliza PostgreSQL para visualizar BLOB.

Se ha recortado la salida para hacer más comprensible la tabla.

loid  | pageno | data
------+--------+------------------------------------------------------------------
17425 | 0      | \377\330\377\340\000\020JFIF\000\001\001\001\000H\000H\000\000\37
17425 | 1      | \256-}\306\267\032s[\336)\245\231\370|L\206\275\364\224\321\237\2
17425 | 2      | \341\226;\015l\232\033f\\\371\251\0323\003t\307\207~\035GB\271\17
(3 rows)

La fotografía se ha dividido en tres registros, que son las páginas 0, 1 y 2 del BLOB. Los tres registros tienen el mismo loid, lo que significa que son el mismo objeto. Obsérvese también, que los bytes son desplegados como caracteres de la forma ‘\ddd’, donde ddd son tres dígitos octales.

Para almacenar un BLOB en una tabla de forma directa; es decir, sin utilizar la tabla del sistema pg_largeobject utilizamos el tipo de dato bytea:

 

En el primer caso se está insertando un BLOB de un solo byte, el carácter ASCII cero.

En el segundo caso se están insertando 4 bytes, los tres primeros están representados directamente por los caracteres imprimibles ASCII y el tercero, el caracter ASCII 30 octal, como no es imprimible, se escribe
en notación ‘\\ddd’.

 

demo=# create table persona (
demo(# nombre varchar(30),
demo(# direccion varchar(30),
demo(# fotografia bytea
demo(# );
CREATE

 La columna fotografía es de tipo bytea, lo que permite almacenar objetos de gran tamaño, cerca de 1GB. Para insertar valores en estas columnas, hacemos lo siguiente:

demo=# insert into persona values ( `Jorge´ , `Cerezo 55´, `\\000´);
INSERT 17436 1
demo=# insert into persona values ( `Luis´ , `Encino 67´, `abc\\030´);
INSERT 17437 1

La consulta se visualiza como sigue:

demo=# select * from persona;
nombre  | direccion | fotografia
--------+-----------+------------
Jorge   | Cerezo 55 | \000
Luis    | Encino 67 | abc\030
(2 rows)

 

Los caracteres en notación octal se muestran con una barra invertida y con dos tal como se escribieron. Esto es debido a que, en realidad, sólo llevan una barra invertida, pero por cuestiones de diseño PostgreSQL, las literales BLOB deben escribirse con doble barra invertida.

4.8. Modificacion de la estructura de una tabla

4.8. Modificacion de la estructura de una tabla Dataprix 26 Octubre, 2009 - 15:58

Para modificar la estructura de una tabla una vez construida, disponemos de la sentencia SQL alter table.

Mediante esta sentencia, podemos llevar a cabo las operaciones siguientes:

•    Agregar una columna.

demo=# alter table persona add edad int ;
ALTER

•    Eliminar una columna.

demo=# ALTER TABLE products DROP COLUMN description;

•    Fijar el valor por omisión de una columna.

demo=# alter table persona alter edad set default 15;
ALTER

•    Eliminar el valor por omisión de una columna.

demo=# alter table persona alter edad drop default;
ALTER

•    Renombrar una columna.

demo=# alter table persona rename direccion to dir;
ALTER

•    Renombrar una tabla.

demo=# alter table persona rename to personal;
ALTER