Sei sulla pagina 1di 7

PostGIS, PostgreSQL y triggers: Georreferenciar es fcil

Los triggers o disparadores de PostgreSQL son una de sus funcionalidades ms tractivas.Ante una determinada operacin (INSERT, UPDATE O DELETE) provocan la ejecucin de una funcin en nuestra base de datos. Si esto lo usamos en conjuncin con PostGIS, nos permite tener tablas en las que el manejo de datos espaciales sea sencillo. La documentacin sobre los triggers es prolija y yo, sobre todo por falta de conocimiento profundo, no quisiera extenderme demasiado e ir al grano.

Y para qu quiero Postgis, PostgreSQL y los triggers?


A menudo, en nuestro trabajo, tenemos que elaborar mapas y por lo tanto precisamos de herramientas que nos permitan posicionar correctamente nuestra informacin. O nos puede interesar establecer relaciones entre nuestros datos teniendo en cuenta su distribucin o posicin geogrfica. Estas herramientas no tienen que ser necesariamente Sistemas de Informacin Geogrfica. Hay personas que elaboran mapas de primera con herramientas no necesariamente pensadas para esto (por ejemplo, con Excel). En todo caso, tendremos que proporcionar de una manera u otra nuestros datos a la aplicacin que empleemos. Para ese fin algunos Sistemas de Gestin de Bases de Datos proporcionan, de alguna manera, soporte para almacenar y manipular datos espaciales. En el caso de PostgreSQL esta funcionalidad se logra mediante la extensin PostGIS, que no hace sino incorporar a nuestra base de datos un conjunto de funciones, tablas y tipos de datos que nos permitirn almacenar y manipular datos espaciales. La instalacin de PostGIS es bastante sencilla, aunque no tanto la actualizacin de las bases de datos que incorporen PostGIS, pero eso ser materia de otro post. Otras bases de datos cuentan con funcionalidades similares (OracleSpatial, SpatiaLite) pero yo me centrar en PostgreSQL + PostGIS porque es la que uso y ms o menos entiendo y porque quiz es el Sistema de Gestin de Bases de Datos que ms se entiende con el software SIG disponible y sobre todo, con QuantumGIS que es software GIS que yo utilizo. Una ventaja adicional de emplear un sistema tipo PostgreSQL + PostGIS es que no es necesario el uso de software GIS para realizar algunas tareas en las que estos softwares osn de aplicacin. As, por ejemplo, es posible consultar si un elemento espacial est dentro de otro, o qu otros elementos grficos estn contenidos en uno determinado. Una aplicacin de esto ltimo puede ser, por ejemplo, obtener los lances de pesca ubicados dentro de un determinado lugar de una cuadrcula, o en una determinada zona delimitada por unas coordenadas o, utilizando las funciones de creacin de buffers espaciales, conocer qu CTD se han efectuado a una distancia determinada de un punto dado, etc. En otras palabras, nos permiten prescindir, hasta cierto punto, de un software dedicado para realizar las consultas espaciales.

Ahora bien, existe un problema y es que que PostgreSQL + PostGIS no almacenan la informacin espacial de una manera directamente interpretable por el usuario, como unos valores numricos de latitud y longitud, por ejemplo, ni los programas leen la informacin de bases de datos PostGIS de esa manera, sino que para ello utilizan un formato descrito por el Open Geospatial Consortium denominado WKB (Well-Known Binary) que es el formato en el que las bases de datos almacenan la informacin espacial. El WKB tiene un hermano mellizo que es el WKT (Well-Known Text) que es la representacin digamos humanamente entendible del objeto que almacenamos como WKB. He hecho mencin al objeto porque hay diferentes tipos de objetos espaciales. Los ms habituales y que en los que pensaremos inmediatamente son el punto y la lnea pero tenemos tambin multilneas, polgonos, multipolgonos, multipuntos y cada uno de ellos con su SRID o sistema de coordenadas asociado. Por eso, una tabla que almacene un objeto de tipo punto no tiene una columna para latitud y otra para longitud, sino que tiene una nica columna que almacena el objeto. Para almacenarlo, PostGIS proporciona unas funciones que permiten la creacin de los objetos a partir de sus coordenadas, tipo de objeto, SRID, etc. Pero es probable que a nosotros nos interese recuperar sin mayor problema las coordenadas numricas de nuestros puntos o lneas o, simplemente, que podamos interactuar con mayor facilidad con nuestra base de datos. Es ms fcil introducir los datos numricamente, tal y como los podemos tomar en el barco que tenindonos que acordar cada vez de pasar la funcin con los parmetros adecuados.Y nos puede interesar, para facilitar luego medidas de distancia, etc o la representacin de los lances en un mapa, disponer de nuestro lance como un objeto de tipo lnea en lugar de de puntos separados. Y aqu es donde aparecen los triggers.

Qu queremos hacer con el trigger?


Lo que queremos hacer es sencillo. Simplemente, que cuando demos de alta un registro o cambiemos sus coordenadas el objeto espacial correspondiente almacenado en la base de datos se cree o se actualice convenientemente. Lo que ocurre es que esto requiere de unos pasos previos. Lo primero que tenemos que hacer es tener una tabla con columnas espaciales del tipo de dato que nos convenga. En el ejemplo que os describo, voy a suponer que queremos disponer de una tabla donde almacenamos los lances de pesca de una campaa. Esta tabla constar de un nombre de campaa, un nmero de lance, una posicin de largado, otra de firmes, otra de virado y otra de arte a bordo. Adems, queremos almacenar, por las razones que hemos comentado antes, una lnea que una los puntos de firme y virado.

Creando la tabla en PostgreSQL


Para trabajar con datos espaciales en PostgreSQL + PostGIS no es posible crear mediante una sola sentencia CREATE TABLE la tabla con soporte espacial. Es preciso hacerlo en dos fases, primero creando la tabla normal sin las columnas espaciales y posteriormente

aadindoles stas mediante una funcin de PostGIS llamada (muy original no es, pero s prctico y lgico, como debe ser) AddGeometryColumn(), La creacin de la tabla es trivial, ahora bien hemos de tener en cuenta que necesitaremos, para cada uno de los puntos involucrados en la creacin de nuestro objeto espacial (uno si es un punto, dos si es una lnea) , dos columnas; una almacenar la longitud y la otra la latitud.
DROP TABLE IF EXISTS lances; CREATE TABLE lances( campana varchar(20), lance int,

1 DROP TABLE IF EXISTS lances; 2 CREATE TABLE lances( 3 campana varchar(20), 4 lance int, 5 lar_lat numeric(12,8), 6 lar_lon numeric(12,8), 7 fir_lat numeric(12,8), 8 fir_lon numeric(12,8), 9 vir_lat numeric(12,8), 10 vir_lon numeric(12,8), 11 fin_lat numeric(12,8), 12 fin_lon numeric(12,8), 13 );

Aadiendo las columnas espaciales


Ahora tendremos que hacer uso de las funciones que PostGIS pone a nuestra disposicin para dotar a una tabla de capacidades de almacenamiento de datos espaciales. Esta funcin se llama AddGeometryColumn y su sintaxis es:
AddGeometryColumn(varchar ta

1 AddGeometryColumn(varchar tabla, varchar columna, int srid, int tipo, int dimension) Donde:

tabla es el nombre de la tabla a la que vamos a aadir la columna, columna es el nombre de la columna a aadir,

srid es el sistema de referecia de coordenadas del elemento que vamos a aadir. Para los que usamos el sistema WGS84 (que es el SRID de las coordenadas que proporcionan los GPS habitualmente, o al menos las sentencias NMEA a las que tenemos acceso), este valor es 4326. Para otros SRID es buena idea buscar en www.spatialreference.org. tipo es el tipo de elemento a insertar (linea, punto) dimension es el numero de dimensiones del mismo (en nuestro caso, 2)

Con esto y un poquito de ganas, creamos nuestras columnas para los puntos y la lnea:
2);

1 SELECT AddGeometryColumn( 'lances', 'lar_punto', 4326, 'POINT', 2); 2 SELECT AddGeometryColumn( 'lances', 'fir_punto', 4326, 'POINT', 2); 3 SELECT AddGeometryColumn( 'lances', 'vir_punto', 4326, 'POINT', 2); 4 SELECT AddGeometryColumn( 'lances', 'fin_punto', 4326, 'POINT', 2); 5 SELECT AddGeometryColumn( 'lances', 'lance_linea', 4326, 'LINESTRING', 2); Notacion Actual
SELECT AddGeometryColumn('ch01', 'fastfoods','geom', 2163, 'POINT',2); Consulta inserter datos

insert into ch01.lances (campana,lance,lar_lat,lar_lon,fir_lat,fir_lon,vir_lat,vir_lon,fin_lat,fin_lon) values ('Uno',4,100.35,200.4,305.2,401.3,500.4,600.2,700.1,800.2); Ahora ya viene la parte ms delicada y es la creacin del trigger.

Creando el trigger en PostgreSQL


La creacin del trigger es un proceso que se realiza en dos fases. Puedes obtener informacin detallada sobre triggers y funciones en las pginas de documentacin de PostgreSQL sobre programacin del servidor. En la primera, programaremos la funcin que dar, valga la redundancia, funcionalidad a nuestro trigger. Las funciones para los trigger son especiales, en tanto en cuanto no tienen valor de retorno, sino que devuelven un objeto de tipo trigger. Lo que har nuestra funcin es tomar cada uno de los pares de coordenadas que introdujimos en nuestra tabla (un par por cada uno de los puntos que vamos a almacenar) y construir un dato geomtrico que almacenar en la columna correspondiente. Adems, una vez construidos los puntos, crear un objeto de tipo lnea que almacenar la lnea del lance de pesca.

En la segunda fase, asociaremos ese trigger a nuestra tabla en la base de datos. Esta es, al menos lxicamente, la verdadera creacin del trigger. El cdigo para crear la funcin es el siguiente:
CREATE OR REPLACE FUNCTIO $posiciones_lance$ DECLARE BEGIN

1 CREATE OR REPLACE FUNCTION posiciones_lance() RETURNS TRIGGER AS 2 $posiciones_lance$ 3 DECLARE 4 BEGIN 5 NEW.ini_punto:=ST_SetSRID(ST_MakePoint(NEW.ini_lon,NEW.lar_lat),4326); 6 NEW.lar_punto:=ST_SetSRID(ST_MakePoint(NEW.lar_lon,NEW.lar_lat),4326); 7 NEW.vir_punto:=ST_SetSRID(ST_MakePoint(NEW.vir_lon,NEW.vir_lat),4326); 8 NEW.fin_punto:=ST_SetSRID(ST_MakePoint(NEW.fin_lon,NEW.lar_lat),4326); 9 NEW.lance_linea:=ST_Makeline(NEW.lar_punto,NEW.vir_punto); 10 RETURN NEW; 11 END; 12 $posicion_lance$ LANGUAGE plpgsql; Aparte de las lneas que crean formalmente la sentencia, las que nos interesa conocer cmo funcionan son las del tipo
NEW.XXX_punto:=ST_SetSRID(

NEW.XXX_punto:=ST_SetSRID(ST_MakePoint(NEW.XXX_lon,NEW.XXX_lat),4326 );

Bsicamente, lo que le decimos a nuestro servidor es que cuando al ejecutar el trigger se le pase a la funcin que vamos a crear el registro que se inserta o actualiza, el NUEVO valor de la columna XXX_punto ser el resultado de:

Crear un punto mediante la funcin ST_MakePoint() de PostGIS. Asignar un SRID a ese punto, en nuestro caso el 4326 (WGS84)

Fijaos en lo de NEW, porque volveremos sobre ello ms adelante. Una vez creado los puntos y aprovechando que stos tienen ya asignado su SRID, mediante la sentencia

NEW.lance_linea:=ST_Makeline(

1 NEW.lance_linea:=ST_Makeline(NEW.lar_punto,NEW.vir_punto); Creamos la lnea que unir los puntos de largado y virada. Ahora, lo que hace el resto de la funcin
RETURN NEW; END; $posicion_lance$ LANGUAGE p

1 RETURN NEW; 2 END; 3 $posicion_lance$ LANGUAGE plpgsql; es retornar el registro NUEVO , indicar que la funcin termina y cerrar la declaracin de la funcin. Ahora, como dijimos antes, viene la segunda fase y es la declaracin del trigger. Esto lo hacemos mediante las siguientes sentencias:
CREATE TRIGGER posicion_lanc BEFORE INSERT OR UPDATE ON FOR EACH ROW EXECUTE PR

1 CREATE TRIGGER posicion_lance 2 BEFORE INSERT OR UPDATE ON lances 3 FOR EACH ROW EXECUTE PROCEDURE posicion_lance(); Os acordis de lo que os dije antes acerca de los registros NUEVOS? Pues bien, si os fijis en la parte de BEFORE INSERT OR UPDATE IN lances , lo que decimos aqu es que antes de que se inserte o actualice el nuevo registro ejecute la funcin que hemos creado sobre cada tupla que se inserte. Por tanto, las variables sobre las que operamos son las columnas de cada tupla, y nos referimos a ellas con NEW.nombre_de_columna, con lo cual, para que quede insertada correctamente la columna de geometra nos referimos a ella en la funcin como NEW igualmente. Ahora ya tenemos nuestra tabla lances habilitada para los datos espaciales y, lo que es mejor an, podemos introducir las coordenadas de los mismos sin necesidad de

emplear funciones de PostGIS en cada una de nuestras consultas de insercin o actualizacin de datos. Espero que el artculo os sea de utilidad!!!

Potrebbero piacerti anche