1

I'm fairly new to SQL and have a set of existing PostGIS layers in our country coordinate system (EPSG: 2193).

I would like to create a view (or materialised view...but initially a simple view until I become better versed in SQL to generate a trigger) which simply re-projects this layer to EPSG 4326 (WGS84) for use in external software which only accepts geographic coordinate system data/4326.

I've not been able to find any examples to do this (most are related to re-projecting one geometry or geography. How can I do this?

CREATE OR REPLACE VIEW testview AS
FROM "Forests" 
SELECT st_transform("Forests".geom,4326) as geom
WHERE "Forests".forest_id = 'F_1'
1
  • 1
    What happened when you ran the SQL code that you have presented?
    – PolyGeo
    Sep 2, 2022 at 2:54

2 Answers 2

3

From my experience it's better to create new table with reprojected geometry, than every time you open view call reprojection function. Add trigger to syncronize data in both tables and don't edit new table manualy.

Create table:

create table "Forest_wgs84"
(  forest_id varchar not null,
   geom geometry(Polygon, 4326)
)

Create trigger function:

CREATE OR REPLACE FUNCTION forest_to_wgs84()
  RETURNS trigger AS
$BODY$
begin
  if (TG_OP = 'UPDATE') then
    UPDATE "Forest_wgs84" 
    SET geom = ST_Transform(NEW.geom, 4326)
    WHERE forest_id = NEW.forest_id;
    RETURN NEW;
  elsif (TG_OP = 'DELETE') then
    DELETE from "Forest_wgs84" 
    WHERE forest_id = OLD.forest_id;
    RETURN OLD;
  elsif (TG_OP = 'INSERT') then
    insert into "Forest_wgs84" (forest_id, geom)
    values (forest_id, ST_Transform(NEW.geom, 4326));
    RETURN NEW;
  end if;
END;
$BODY$

Create trigger on main table:

CREATE TRIGGER "Sync_Forest"
  AFTER INSERT OR UPDATE OR DELETE
  ON "Forest"
  FOR EACH ROW
  EXECUTE PROCEDURE forest_to_wgs84();
2
  • Fair enough - everything neatly automated and normalized; fire-and-forget - however, while transformations aren't for free, so aren't JOINs. For <100k rows you wouldn't notice the difference even without a separate table, especially if the View gets a BBOX filter pushed down (i.e. only the result set geometries are transformed). In fact, with further increasing row counts I suspect that performance may actually stay equal to the relational approach. The only real difference would be to either create a MATERIALIZED VIEW or simply adding a 2nd geom column to the table, each indexed.
    – geozelot
    Sep 2, 2022 at 8:10
  • Thank you for the useful answer. On views vs Materialized view vs new table with triggers, has your experience been that a new table with triggers is better than a materialised view?
    – Tim
    Sep 4, 2022 at 23:32
2

Make sure the FROM comes after the SELECT.

Also, while not mandatory, you should cast the output geometry to its specific type/projection so the column is not of the "simple" type geometry but rather geometry(polygon, 4326) which can speed up many software consuming the view.

CREATE OR REPLACE VIEW testview AS
  SELECT uid,
         st_transform("Forests".geom,4326)::geometry(polygon, 4326) as geom
  FROM "Forests" 
  WHERE "Forests".forest_id = 'F_1';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.