Dodanie dodatkowej kolumny geometrii w PostGIS?


10

Importuję wiele zestawów danych geodezyjnych do PostGIS i mają one różne SRID. (Niektórzy mają EPSG:3857, niektórzy EPSG:4326, jeszcze coś innego).

Chciałbym stworzyć dodatkowy geometry column, np. the_geom_mercatorz SRID EPSG:3857, a także zachować oryginalną geomkolumnę we wszystkim SRID, co się pojawiło.

Jak mogę to zrobić za pomocą funkcji PostGIS?

Odpowiedzi:


18

Aby dodać kolumnę do istniejącej tabeli, użyj ALTER TABLE DDL , np .:

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

które można wypełnić w innej kolumnie (the_geom), używając:

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

(trzecia linia FROM spatial_ref_sys ...nie jest konieczna, ale chroni próby transformacji z nieznanymi lub nieprawidłowymi projekcjami, które powodują błędy).

A jeśli ta tabela ma być utrzymana (dodana / zaktualizowana), możesz użyć funkcji wyzwalacza, aby zaktualizować the_geom_mercator, np .:

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();

Pamiętaj, że ST_Transform powinien wychwytywać błędy i wyświetlać ostrzeżenie, np .:

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

Dzięki za świetną odpowiedź. Używanie wyzwalaczy jest naprawdę fajne, zacznę to robić. Czy zamiast tego mogę dodać ten wyzwalacz do bazy danych, aby nie musiałem dodawać tego wyzwalacza dla każdej nowej tabeli?
knutole

Dodam dane do postgis za pomocą, shp2psqla tabela jest tworzona po przepuszczeniu psql. Więc nie mogę naprawdę dodać wyzwalacza, zanim tabela będzie istnieć?
knutole

1
Jeśli używasz shp2pgsql, użyj instrukcji aktualizacji, patrz wyżej. Wyzwalacz jest przydatny, jeśli musisz utrzymywać tabelę, ale nie do ładowania.
Mike T

2

Najpierw utwórz normalny nieprzestrzenny stół, który już masz. Następnie dodaj kolumnę przestrzenną do tabeli za pomocą funkcji „AddGeometryColumn” OpenGIS.

Przykład:

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

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

1

Możesz utworzyć nieograniczoną kolumnę geometrii SRID do przechowywania formy natywnej, a następnie przekształcić ją w istniejącą. Oto wymyślony przykład, zakładając, że masz wielokąty, które kopiujesz z tabeli pomostowej (jeśli wymieszałeś, możesz ustawić typ na geometrię, np. Geometrię (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;

Dzięki za odpowiedź. Czy można to zrobić na już istniejących tabelach (tj. Bez użycia tabel pomostowych)? Powiedzmy, że mam już tabelę z geomkolumną i chcę po prostu dodać kolejną the_geom_webmercatorkolumnę. Jak mam to zrobić?
knutole
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.