Adicionando coluna de geometria adicional no PostGIS?

10

Estou importando muitos conjuntos de dados geográficos para o PostGIS, e eles têm diferentes SRID. (Alguns têm EPSG:3857, alguns EPSG:4326, alguns algo mais).

Eu gostaria de criar um adicional geometry column, por exemplo. the_geom_mercatorcom SRID EPSG:3857e também mantenha a geomcoluna original no local em que SRIDfoi inserida.

Como posso fazer isso com uma função PostGIS?

knutole
fonte

Respostas:

18

Para adicionar uma coluna a uma tabela existente, use o ALTER TABLE DDL , por exemplo:

ALTER TABLE my_table
  ADD COLUMN the_geom_mercator
    geometry(Geometry,3857);

que pode ser preenchido de outra coluna (the_geom) usando:

UPDATE my_table SET
  the_geom_mercator = ST_Transform(the_geom, 3857)
FROM spatial_ref_sys
WHERE ST_SRID(the_geom) = srid;

(a terceira linha FROM spatial_ref_sys ...não é necessária, mas protege as tentativas de transformação com projeções desconhecidas ou inválidas, o que gera erros).

E se essa tabela for mantida (adicionada / atualizada), você pode usar uma função de gatilho para atualizar o the_geom_mercator, por exemplo:

CREATE OR REPLACE FUNCTION my_table_tg_fn() RETURNS trigger AS
$BODY$BEGIN
  IF TG_OP = 'INSERT' AND NEW.the_geom ISNULL THEN
    RETURN NEW; -- no new geometry
  ELSIF TG_OP = 'UPDATE' THEN
    IF NEW.the_geom IS NOT DISTINCT FROM OLD.the_geom THEN
      RETURN NEW; -- same old geometry
    END IF;
  END IF;
  -- Attempt to transform a geometry
  BEGIN
    NEW.the_geom_mercator := ST_Transform(NEW.the_geom, 3857);
  EXCEPTION WHEN SQLSTATE 'XX000' THEN
    RAISE WARNING 'the_geom_mercator not updated: %', SQLERRM;
  END;
  RETURN NEW;
END;$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER my_table_tg BEFORE INSERT OR UPDATE
   ON my_table FOR EACH ROW
   EXECUTE PROCEDURE my_table_tg_fn();

Observe que ST_Transform deve capturar erros e mostrar um aviso, por exemplo:

postgis=# INSERT INTO my_table(the_geom)
postgis-# VALUES (ST_SetSRID(ST_MakePoint(0,1), 123))
postgis-# RETURNING the_geom, the_geom_mercator;
WARNING:  the_geom_mercator not updated: GetProj4StringSPI: Cannot find SRID (123) in spatial_ref_sys
-[ RECORD 1 ]-----+---------------------------------------------------
the_geom          | 01010000207B0000000000000000000000000000000000F03F
the_geom_mercator |

INSERT 0 1
Mike T
fonte
Obrigado por uma ótima resposta. É muito legal usar gatilhos, vou começar a fazê-lo. Em vez disso, eu poderia adicionar esse gatilho ao banco de dados, para não precisar adicionar esse gatilho para cada nova tabela?
knutole
Estou adicionando dados ao postgis shp2psqle a tabela é criada quando transmitida psql. Então, eu realmente não posso adicionar um gatilho antes da tabela existir?
knutole
1
Se você estiver usando shp2pgsql, use uma instrução de atualização, veja acima. Um acionador é útil se você precisar manter uma tabela, mas não para carregar.
Mike T
2

Primeiro, crie uma tabela não espacial normal, que você já possui. Segundo, adicione uma coluna espacial à tabela usando a função "AddGeometryColumn" do OpenGIS.

Exemplo:

CREATE TABLE terrain_points ( 
ogc_fid serial NOT NULL, 
elevation double precision,
);

SELECT AddGeometryColumn('terrain_points', 'wkb_geometry', 3725, 'POINT', 3 );
hoogw
fonte
1

Você pode criar uma coluna de geometria SRID irrestrita para manter o formulário nativo e depois transformar em existente. Aqui está um exemplo artificial, supondo que você tenha polígonos que você está copiando de uma tabela de preparo (se você tiver mixado, poderá definir o tipo como geometry, por exemplo, geometry (Geometry, 3857):

CREATE TABLE poi(gid serial primary key, 
   geom_native geometry(POLYGON),  
   geom_mercator geometry(POLYGON,3857) );

INSERT INTO TABLE poi(geom_native, geom_mercator)
SELECT geom, ST_Transform(geom, 3857)
   FROM staging.imported_poly;
LR1234567
fonte
Obrigado pela sua resposta. Existe alguma maneira de fazer isso em tabelas já existentes (ou seja, sem usar tabelas intermediárias)? Digamos que eu já tenho uma tabela, com uma geomcoluna, e simplesmente quero adicionar outra the_geom_webmercatorcoluna. Como eu faria isso?
Knutole