Добавление дополнительного столбца геометрии в PostGIS?

10

Я импортирую множество наборов геоданных в PostGIS, и они имеют разные SRID. (У некоторых есть EPSG:3857, у EPSG:4326некоторых что-то еще).

Я хотел бы создать дополнительный geometry column, например. the_geom_mercatorс SRID EPSG:3857, а также сохраните исходную geomколонку в том виде, в каком SRIDона была.

Как я могу сделать это с помощью функции PostGIS?

knutole
источник

Ответы:

18

Чтобы добавить столбец в существующую таблицу, используйте ALTER TABLE DDL , например:

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

который может быть заполнен из другого столбца (the_geom) с помощью:

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

(третья строка FROM spatial_ref_sys ...не обязательна, но она защищает попытки преобразования с неизвестными или недействительными проекциями, которые вызывают ошибки).

И если эта таблица должна поддерживаться (добавляться / обновляться), вы можете использовать функцию триггера для обновления the_geom_mercator, например:

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

Обратите внимание, что ST_Transform должен перехватывать ошибки и отображать предупреждение, например:

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
Майк Т
источник
Спасибо за отличный ответ. Очень удобно использовать триггеры, я начну это делать. Могу ли я добавить этот триггер в базу данных, чтобы мне не пришлось добавлять этот триггер для каждой новой таблицы?
Кнутоль
Я добавляю данные в postgis с помощью shp2psqlи таблица создается при прокачке psql. Так что я не могу добавить триггер, пока таблица не существует?
Кнутоль
1
Если вы используете shp2pgsql, используйте оператор обновления, см. Выше. Триггер полезен, если вам нужно вести таблицу, но не для загрузки.
Майк Т
2

Сначала создайте обычную непространственную таблицу, которая у вас уже есть. Затем добавьте пространственный столбец в таблицу, используя функцию OpenGIS «AddGeometryColumn».

Пример:

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

SELECT AddGeometryColumn('terrain_points', 'wkb_geometry', 3725, 'POINT', 3 );
hoogw
источник
1

Вы можете создать столбец геометрии SRID без ограничений для хранения собственной формы, а затем преобразовать ее в существующую. Вот надуманный пример, предполагающий, что у вас есть полигоны, которые вы копируете из промежуточной таблицы (если вы смешали, вы можете установить тип для геометрии, например, геометрия (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
источник
Спасибо за Ваш ответ. Есть ли способ сделать это на уже существующих таблицах (т.е. без использования промежуточных таблиц)? Допустим, у меня уже есть таблица со geomстолбцом, и я просто хочу добавить еще один the_geom_webmercatorстолбец. Как бы я это сделал?
Кнутоль