GeODin zu PostGIS, aber wie?

Hoi!

Für einen Trigger such ich morgen mal ein Beispiel zusammen, jetzt mach ich erst mal Feierabend. Ansonsten geht die Performance in die Knie wenn du sehr schnell viel einfügen willst. Ist aber für diesen Anwendungsfall so nicht gegeben glaube ich, es sei den ihr habt sehr schnelle Finger und bohrt wie die Raketenwürmer :wink:

Grüßle

Uwe

Nein, also bei uns wird jedes Projekt von Hand in Ruhe eingegeben… Und das sind maximal 10-20 Rammkernsondierungen am Tag… Unsere bisherige mdb hat das auch gerade so verkraftet :wink:

Aber im Ernst: Ich bin immer wieder erstaunt wie gut die Performance der Postgre-DB ist. Einmal in GeODin geladen und es gibt quasi keine Verzögerung mehr beim Anzeigen, Aufrufen oder Editieren. Ich bin gespannt wie sich die Performance in Zukunft mit einem Firmeninternen GIS ist.

Ich bin gespannt auf den Trigger ^^

Bis dahin

Guten Morgen!

Mal ein Beispiel:
Zuerst bauen wir eine Stammtabelle, dies entspricht deiner GeoDyn-Tabelle:

create table if not exists koordinaten(
  id integer,
  xcoord numeric,
  ycoord numeric,
  srid integer)

Jetzt wird eine neue Datenbank erstellt, darin muß als extension der postgres_fdw aktiviert sein, Dann führen wir folgendes aus:

CREATE SERVER demo
   FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (host 'localhost',port '5432',dbname 'GeoDyn-DB');
ALTER SERVER demo
  OWNER TO postgres;
GRANT USAGE ON FOREIGN SERVER demo TO postgres;
GRANT USAGE ON FOREIGN SERVER demo TO "public";
 
--Hier muß der lokale Nutzer auf einen Nutzer in der Fremddatenbank gemappt werden
create user mapping for postgres server demo options (user 'postgres', password 'xxxxxx');

--Hier können afair auch Aliase für die Felder verwendet werden, näheres im AHndbuch
create foreign table if not exists koordinaten(
  id integer,
  xcoord numeric,
  ycoord numeric,
  srid integer)
  server demo;
ALTER FOREIGN TABLE koordinaten
  OWNER TO postgres;

Und das wars vorerst auch schon, die Namen etc mußt du an deine Umgebung anpassen. Daten, die in der Geodyntabelle eingefügt werden, erscheinen jetzt auch in der anderen Datenbank.

Man kann auch einfach Daten an die Fremdtabelle anfügen:

insert into koordinaten(id, xcoord, ycoord, srid) values(3,2567986, 5567892,31466);

Ein Update überlasse ich dem Kandidaten zur Übung :wink:.
Hier stehen also erstmal nur Koordinaten, die in verschiedenen Systemen dargestellt sein können. Diese sollen jedoch in einem einheitlichen Bezug hier UTM32N) dargestellt werden. Dazu benötigen wir einen View:

create or replace view koordinaten_geom as
  select id, xcoord, ycoord, srid, st_transform(st_setsrid(st_makepoint(xcoord, ycoord), srid), 25832) as geom
    from koordinaten

Diesen können wir jetzt z.B. in QGIS anzeigen.
Soweit erstmal, wie man Daten z.B. über QGIS an den View abfügt probiere ich nach dem Kaffee :wink:

Gruß Uwe

Noch zu Trigger: Auf den hab ich heir verzichtet, weil er nicht nötig ist. In meiner Umgebung hab ich einen gebaut der mir beim Anlegen oder Ändern von Stammdaten bestimmte Felder z.B. tk25 oder die Gemeinde füllen soll oder die IDs hochzählt. Da ich die Geometrie in der Stammdatentabelle mitführe wird auch getestet ob sich die Koordinaten oder Geometrie geändert haben und das entsprechende nachgeführt. Da hier ein View genutzt wird ist das nicht notwendig.

Hier der Trigger zur Ansicht (das Aktualisieren von tk25 funktioniert hier im Moment noch nicht so wie es soll):

CREATE OR REPLACE FUNCTION sep3.sync_geometry()
  RETURNS trigger AS
$BODY$
  declare
    srid integer := 25832;
  begin
  --check operation
  if TG_OP = 'INSERT' then
    raise notice 'insert';
    --check if names set
    if new.shortname is null then
      new.shortname := coalesce(new.longname, 'NEU');
    end if;
    if new.longname is null then
      new.longname := new.bver||'-'||coalesce(new.shortname, 'NEU');
    end if; 

    --check keys
    raise notice 'prj: %s, loc: %s, rec: %s', new.prjid, new.locid, new.recid;
    if new.prjid is null then
      new.prjid := 1;
    end if;
    if new.locid is null then
      select coalesce(max(locid), 0) + 1 into new.locid from sep3.s3stamm where prjid = new.prjid;
    end if;
    if new.recid is null then
      select coalesce(max(recid), 0) + 1 into new.recid from sep3.s3stamm where prjid = new.prjid and locid = new.locid;
    end if;
    raise notice 'prj: %s, loc: %s, rec: %s', new.prjid, new.locid, new.recid;
    -- check if a geometry can be made
    if new.geom is null and -500 = any(array[new.xcoord, new.ycoord, new.ksys]) is not null then
      new.geom := st_transform(st_setsrid(st_makepoint(new.xcoord, new.ycoord), new.ksys), srid);
    elsif new.geom is not null and st_srid(new.geom) > 0 then
      new.xcoord := st_x(new.geom);
      new.ycoord := st_y(new.geom);
      new.ksys := st_srid(new.geom);
      new.geom := st_transform(new.geom, srid);
    else
      raise notice 'no geometry possible!';
      return null;   
    end if;
  else 
    raise notice 'update';
    if (new.shortname <> old.shortname or new.bver <> old.bver) and old.longname is null then
      new.longname := new.bver||'-'||coalesce(new.shortname, 'NEU');
    end if; 
    if not new.geom = old.geom then
      raise notice 'geometry altered';
      new.xcoord := st_x(st_transform(new.geom, new.ksys));
      new.ycoord := st_y(st_transform(new.geom, new.ksys));
    elsif new.xcoord <> old.xcoord 
       or new.ycoord <> old.ycoord 
       or new.zcoordb <> old.zcoordb 
       or new.ksys <> old.ksys then
      raise notice 'coords altered';
      new.geom := st_transform(st_setsrid(st_makepoint(new.xcoord, new.ycoord),new.ksys), srid);
    end if;
  end if;
  -- get the tk
--   select dtknr 
--     into new.tk25 
--     from public.tk_tiles t1
--     where t1.m_id = '25' 
--       and t1.type = 'TK' 
--       and new.geom @ st_transform(t1.geom, srid);
  return new;     
  end; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Noch zum Erstellen von Geometrien z.B. in QGIS. Bei uns trat die Anwendung auf von georeferenzierten Plänen direkt die Punkte in das Datenmodell zu digitalisieren. Hierzu kann man in dem obigen Beispiel, das kein dezidiertes Geometriefeld enthält eine Rule erstellen, die ein Insert auf den View in ein Insert auf die Foreigntable und damit auf die Stammdatentabelle in de anderen Datenbank auslöst.

create or replace rule insert_geom as 
  on insert to koordinaten_geom do instead
  insert into koordinaten (id, xcoord, ycoord, srid)
    values ((select max(id) from koordinaten)+1, st_x(new.geom), st_y(new.geom), st_srid(new.geom));

Man bindet den View als Layer in QGIS oder einem anderen GIS ein und startet die Bearbeitung. Beim speichern der erfassten Punkte wird ein Insert ausgelöst der anschliessend über die Rule modifiziert und umgeleitet wird. So kann man ohne real vorhandenes Geometriefeld im GIS digitalisieren.

Grüßle Uwe

Oha… ich habe gerade leider mal wieder andersweitig viel zu tun und bin nächste Woche im Urlaub.

Ich habe es mal kurz überflogen und äh habe keine Ahnung! =D das schau ich mir nach meinem Urlaub mal genauer an und danke dir an dieser Stelle schon einmal für deine Mühe.

Eine kleine Bemerkung/Frage habe ich aber schon nach dem Überfliegen, sorry also falls doch schon irgendwo drin steht ^^:

Mir ist es wichtig, dass unsere 2. DB (also die, in welche aus der Geodin-DB reinkopiert werden soll) eine wirklich bestehende DB mit Tabelle und drumherum ist. Das heißt ich möchte keine Schattenkopie oder eine Tabelle die mir Daten aus der originalen Geodin-DB anzeigt, ohne das die Daten wirklich in der neuen DB sind… Ich brauche quasi eine neue DB die physisch real auf dem Server existiert mit Daten die quasi geklont und transformiert sind ^^ Die Frage wäre nun: Macht dies dein Beispiel mit dem view und dem mapping? ^^

Ich habe nämlich vor aus einer zweiten zukünftigen DB (Laborversuche) zusätzliche Daten in die neu erstellte DB den einzelnen Projekten zu zuordnen ^^

Also soweit schon mal danke und bis nach meinem Urlaub ^^

Grüße

Hallo!

Dann mache aus der Fremdtabelle einen Materialized View statt eines normalen Views in der 2. Datenbank. Das funktioniert im wesentlichen wie eine Tabelle, ist physikalisch vorhanden und kann mit indices etc. versehen werden. Nur das Update ist deutlich einfacher und kann ab Postgres 9.5 auch ohne Unterbrechung während des Refreshs stattfinden. Vorteil ist hier, das du die Berechtigungen auf den MV individuell und unterschiedlich zur Originaltabelle erzeugen kannst während der View immer die Berechtigungen der Originaltabelle voraussetzt. Ist nur zu beachten wie mit gelöschten Einträgen der Originaltabelle umgegangen werden soll bzw. ob das vorkommen kann.
Wie auch immer, ich wünsch dir einen schönen Urlaub. Bei mir ist es übernächste Woche soweit :wink:

Gruß Uwe

Hi Gisman,

ich habe mich gerade mal wieder an diese Geschichte gesetzt. Nachdem ich versucht habe bestimmte Spalten unserer Ur-Datenbank mit einem Insert Befehl in eine ander Datenbank zu kopieren und mit dem Fehler der nicht implementierten Funktion zwischen zwei Datenbanken zu kopieren gescheitert bin, habe ich einfach ein neues Schema in der selben DB erstellt und konnte mit hilfe des Inserts-Befehl zwischen diesen beiden kopieren.
Die Tabelle in dem neuen Schema sieht folgendermaßen aus:

CREATE TABLE "Kopie"."Stammdaten"
(
  prj_id character varying(6) NOT NULL,
  xcoord double precision,
  ycoord double precision,
  zcoordb double precision,
  longname character varying(40),
  projekt character varying(40)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "Kopie"."Stammdaten"
  OWNER TO postgres;
GRANT ALL ON TABLE "Kopie"."Stammdaten" TO public;
GRANT ALL ON TABLE "Kopie"."Stammdaten" TO postgres;

So und nun hänge ich wieder… Ich habe auch schon einen entsprechenden Matrialized View erstellt, aber komme genauso wenig weiter.

  1. Ich habe mir nochmal deinen Code vom Beginn der Konversation angeschaut und bin über etwa gestolpert dass mich stutzig macht.
    Du hast da irgendwoher die Spalte SRID bekommen. Wo kommt die her oder ist das der Bestandteil der PostGIS Erweiterung und wird einfach hinten dran gehangen? Aber woher weiß die DB welche SRID passt? Ich kann ja nicht 60000 Zeilen durchgehen und das entsprechend zuordnen!?

  2. Mir gefällt die Lösung mit dem FWD am besten, jedoch verstehe ich den Hintergrund nicht ganz. Wird die geklonte DB ständig aktualisiert?
    Ich bin auch offen für den MV. Wird dieser ständig aktualisiert wenn etwas in die Urtabelle hinzu kommt oder gelöscht wird? Oder doch lieber ein Trigger?

  3. Gehen wir davon aus ich benutze einen MV. Kann ich im Prinzip den MV um die Spalte geom erweitern, diese mit der Transform-Funktion versehen und habe am Ende immer eine aktuelle geom-Spalte? Oder ist das zu einfach gedacht?

Ich würde mich sehr über deine und alle anderen Antworten freuen.

Gruß Schweitzer

UPDATE:

Ich habe es heute geschafft einen Trigger zu bauen der mir die Daten aus bestimmte Spalten aus der Urdatenbank in eine Tabelle in ein anderes Schema kopiert sobald sich irgendetwas an der Urdatenbank ändert.

Dies habe ich wie folgt gelöst:

CREATE OR REPLACE FUNCTION insert()
	RETURNS trigger AS
  $BODY$
      BEGIN
        insert into "Kopie"."Stammdaten" (prj_id,xcoord,ycoord,zcoordb,longname,projekt)
	select prj_id,xcoord,ycoord,zcoordb,longname,projekt
	from public.geodin_loc_ssgkrzt1;
	RETURN NULL;
      END;
  $BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100000;
  
  CREATE TRIGGER sync 
AFTER 
INSERT OR UPDATE OR DELETE 
ON public.geodin_loc_ssgkrzt1 
FOR EACH ROW
EXECUTE PROCEDURE insert();

Sooooo… nun zum eigentlichen Problem:

Ich möchte nun dass in der Zieltabelle (Stammdaten) die Koordinaten in eine geom-Spalte im Postgis-Format automatisch überführt werden.

Ich setze also eine Spalte geom hinten an die Tabelle dran.

Wie bekomme ich es nun hin, dass die geom-Spalte automatisch herausfindet um welches Koordinatensystem es sich in der jeweiligen Zeile handelt und diese in UTM umrechnet und im postgis format speichert!? Und das alles schon sobald diese Tabelle durch den Trigger erneuert wird!?

Hier brauche ich echt grundlegende Hilfe.

Danke schon mal.

Gruß Schweitzer

Need Help Gisman ^^

Sorry, aber ich bin/war grad mit unserer neuen Drohne beschäfigt :slight_smile:

Du musst entweder die srid mit geben oder halt anderweitig feststellen was da für Koordinaten angeflogen kommen. Das ist aber immer mit Einschränkungen verbunden oder mißverständlich. Die Wahl wäre dann, ob du mit dem Trigger gleich eine entsprechende Geometrie in die Zieltabelle schreibst oder ob du das mit eine Trigger auf der Zieltabelle erledigst. Beides mal wäre der Befehl so was wie st_transform(st_setsrid(st_makepoint(xcoord, ycoord, zcoord), koord_srid), utm_srid). Ich würde das gleich mit dem hier aufgeführten Trigger erledigen, es sei denn es kämen noch Geometrien aus anderen Tabellen in die Kopie-Tabelle.

Ist es korrekt, das Daten in die Kopie geschrieben werden, wenn du im Original welche löschst? Macht jedenfalls der Trigger…
Du schreibst im übrigen bei jedem Insert etc die ganze Tabelle in die Kopie. Du kannst auch auf die jeweils gerade geschriebenen oder veränderten Daten einer Row mit dem Präfix ‘new.’ oder ‘old.’ zugreifen. Dann schreibt er nur eine Zeile in die Kopie und du brauchst kein Select.

Soweit erstmal,

Grüßle
UWe

Hi Gisman,

das mit der SRID wird wohl das größte Problem, denn diese ist für alte Projekte, die ebenfalls mit in die Kopie übernommen werden, einfach nicht vorhanden.
GeODin hat auch keine Möglichkeit der EIngabe einer SRID.
Das heißt ich muss dies irgendwie DB-intern lösen.
Mein Gedanke war folgender: Ich lege in der Kopie Tabelle eine weitere Spalte mit SRID an. Nun bräuchte ich wahrscheinlich einen Trigger (oder ich baue das auch gleich noch in den vorhandenen Trigger ein) der mir die erste Ziffer der ankommenden X-Koordinate auswertet. In etwa so:
Ist die erste Zahl der X-Koordinate eine 3 dann schreibe mir 31586 in die entsprechende Zeile in der SRID Spalte. Genauso mit 4 an erster Stelle.
Im Prinzip haben wir nur GK3 oder GK4. Alles andere ist mir im Moment sowieso erstmal egal ^^. Das Problem an der ganzen SAche ist, ich habe keine Ahnung wie so eine IF klausel aussieht und wie ich sowas in den Trigger baue… Da wäre in ANsatz sehr hilfreich.

Das mit dem old und new versteh ich nicht. Aber das mit der row stört mich auch etwas. habe schon überlegt ob ich es auf Statement reduziere. Aber keine Ahnung ob das sinnvoll ist. Das DELETE war eigentlich so gedacht, dass wenn ich etwas in der Urtabelle lösche, es auch in der Kopietabelle gelöscht wird, oder ist das ein Denkfehler? Es kommt oft vor das wir unsere Daten von alten Projekten ändern oder ganz löschen (vorallem Koordinaten ^^).


Eventuell wäre die SRID GEschichte der erste Schritt ^^

Ich danke dir schonmal und übrigens: Wieso hast du jetzt ne Drohne??? Fotogrammetrie oder wie? =P =D

Gruß

UPDATE:

Ich habe gerade überlegt überhaupt nur die Zeilen zu nehmen in der eine 3 oder 4 am anfang steht… die anderen brauch ich gar nicht in der Kopietabelle… Das bedeutet ich muss die Funktion komplett umschreiben auf diese beide Fälle… aaaaahhhhhhhhhhh -.- und ich habe keine AHnung wie ^^

P.S: Mein Shift klemmt =P

So ich habe jetzt mal ein paar dinge probiert.

Vorallem das mit dem gesamten Kopieren der TAbelle ist tatsächlich blöd.
Ich habe jetzt einfach in den trigger ein delete vorne dran geschrieben und eine where klausel für die x-Koordinate eingefügt.
das funktioniert auch gut. Er schreibt mir jetzt nur die Zeilen rüber die koordinaten haben und auch jeweils nur den aktuellen stand…
ABER: das problem ist die gid-spalte mit dem serial… diese wird bei jedem anfassen weiter gezählt… das ist schlecht (weil ja jedesmal trotzdem wieder alle 4000 Zeilen mit Koordianten rüber kopiert werden :,( xD).

Ergo muss ich dies alles doch mit dem old und new machen. dazu bräuchte ich aber mal eine erklärung wie das funktioniert.

Desweiteren habe ich das Problem der SRID mit einem einfachen UPDATE WHERE behoben. Dies muss ich dann noch in einen eigenen Trigger in der Zieltabelle bauen. Und dann kann ich endlich die eigentliche Geschichte mit der Transformation angehen ^^ xD

Gruß

Hallo!

Drohne:
Ja, wie planen Ad-Hoc-Befliegungen für einige Monitoring- und Erkundungsprojekte :slight_smile:
Vielleicht schreib ich mal ein paar Zeilen dazu, wenn wir das Ganze im Griff haben.

SRID:
Für alte Daten kann man in der Tat den Ansatz verfolgen nach der ersten Ziffer zu unterscheiden. Für neuere und ganz neue Daten ist das aber nicht mehr eindeutig, da UTM-Koordinaten auch 7-stellig mit einer 3 vorkommen können.

old/new:
Das sind Präfixe, mit denen du innerhalb eines Triggers auf die jeweils übergebenen Werte zugreifen kannst. Damit kannst du z.B, Dinge mache wie

if new.xcoord <> old.xcoord or new.ycoord <> old.ycoord then new.geom = st_makepoint(new.xcoord, new.ycoord)

Das erzeugt eine neue Geometri, wenn sich die Koordinatenfelder ändern, sonst nicht.

if und Trigger:
Ich empfehle dir, das mal im Postgres-Handbuch nachzulesen. Da sind auch Beispiele dabei, damit kommt man schon weiter.

Soviel erstmal, Schönes Wochenende!

Uwe

Hi Uwe,

also ich hab jetzt mal ewig umher probiert mit dem old und new…
Ich habe aber nix hinbekommen. Es geht immernoch darum die bestimmten Spalten aus der Urtabelle in die neue Tabelle in dem anderen Schema automatisch zu “überführen” sobald etwas an der Urtabelle geändert wird (sei es Insert, Update oder Delete).

Ich habe folgende Funktion zusammengbastelt die zumindest keine Fehlermeldung zurückgibt und einen entsprechenden Trigger der auch keine Fehlermeldung zurück gibt. Füge ich aber etwas in die Urtabelle ein bekomme ich eine Fehlermeldung:

CREATE OR REPLACE FUNCTION public.insert()
  RETURNS trigger AS
$BODY$ 
      BEGIN
	if new.prj_id <> old.prj_id
	or new.xcoord <> old.xcoord 
	or new.ycoord <> old.ycoord
	or new.zcoordb <> old.zcoordb
	or new.longname <> old.longname
	or new.projekt <> old.projekt
	then 
		update "kopie"."stammdaten"
			set 	
			(old.prj_id, old.xcoord, old.ycoord, old.zcoordb, old.longname, old.projekt) 
			= (new.prj_id, new.xcoord, new.ycoord, new.zcoordb, new.longname, new.projekt);
	RETURN NULL;
	END if;
      END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.insert()
  OWNER TO postgres;
  
  CREATE TRIGGER replication
	AFTER INSERT OR UPDATE OR DELETE 
	ON public.geodin_loc_ssgkrzt1
	FOR EACH ROW 
	EXECUTE PROCEDURE insert();
	
insert into public.geodin_loc_ssgkrzt1 
VALUES
('940000','0','1','4555474','5555556');

FEHLER:  Record „old“ hat noch keinen Wert
DETAIL:  Die Tupelstruktur eines Records ohne Wert ist unbestimmt.
CONTEXT:  PL/pgSQL-Funktion insert() Zeile 3 bei IF
********** Fehler **********

FEHLER: Record „old“ hat noch keinen Wert
SQL Status:55000
Detail:Die Tupelstruktur eines Records ohne Wert ist unbestimmt.
Kontext:PL/pgSQL-Funktion insert() Zeile 3 bei IF

ich hab keine Ahnugn von old und new… muss ich das vorher irgendwo declaren oder setten?
Langsam nervts ^^

Danke schonmal für deine Hilfe

Gruß Stefan

bei einem Insert gibt es kein OLD, du wirst also auch prüfen müssen, ob die aktuelle Aktion ein Insert, Update oder Delete ist.

Was genau hast Du denn genau vor? Was soll bei einem Insert, bei einem Update und bei einem Delete passieren? OLD und NEW sind Records, die bei den einzelnen Operationen unterschiedlich gesetzt sind:

NEW : Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers and for DELETE operations.
OLD : Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is NULL in statement-level triggers and for INSERT operations.


Bis jetzt sehe ich da nur ein Update auf kopie.stammdaten, aber was soll bei einem DELETE / UPDATE passieren? TG_OP sagt Dir, ob es Insert/Update oder Delete ist, was den Trigger ausgelöst hat.

Davon abgesehen:warum der Aufwand? Du kannst doch auch immer sehen, was in der eigentlichen Tabelle drinsteht? Wenn das eine Replikation werden soll (so der Name des Triggers), dann gäbe es da möglicherweise generell sinnvollere Möglichkeiten. Wenn es eine Art Logging werden soll, und Du anhand der Logtabelle nachvollziehen können willst, wann sich was und wie geändert hat, auch.

Im Prinzip möchte ich nur eine Automatik die mir bestimmte Spalten aus der Urtabelle (im Schema public) in die neue Tabelle in meinem eigenen Schema “Kopie”, welches den Postgis-Aufsatz hat, “rüber geschoben” haben. Dabei wird die Urtabelle durch ein externes Programm (GeODin) geändert. Die Änderungen können eben Inserts, Deletes oder Updates irgend einer Zeile sein. DAs Problem ist, dass die Urtabelle viel mehr SPalten hat als die 5 Spalten die ich ausschließlich haben will. Die anderen Spalten können ebenfalls gelöscht oder geupdatet werden ohne das sich was an den 5 Spalten ändert die mich interessieren. Somit soll der Trigger dann dort nicht auslösen obwohl etwas in der ROW bzw Spalte geändert wird. Ich weiß nicht mal ob das möglich ist… Deshalb dachtre ich die OLD/NEW GEschichte wäre eine Lösung.

Etwaige Feinheiten wie das ausschließliche Kopieren bzw Löschen von Zeilen in die neue Tabelle die Koordinaten haben wären ein Bonus.
Für mich stellt sich erstmal die Grundfrage wie ich die Daten in das andere Schema bekomme OHNE VIEW oder FDW (also ganz und gar andere Datenbank).

Ich möchte die neue Tabelle ungern im selben Schema anlegen wie die GeODin-Tabellen (das sind 97). GeODin hat die Struktur automatisch angelegt und ist relativ schmerzfrei. Dennoch wäre mir die neue Tabelle lieber in einem anderen Schema, da ich dort auch den PostGIS Aufsatz hinlegen kann und dort alle Berechnungen die ich mit den Koordinaten vor habe ausführen kann ohne die Struktur der originalen Tabellen zu nötigen.

Achso: Das Ziel der neuen Tabelle sollen PostGIS-DAten sein die ich aus den orignalen Daten zusammenbaue und berechne um diese über ein WebGIS einzubinden. Das wichtigste daran: Es muss up to DAte sein… Das heißt wenn ich was in GeODin eingebe oder lösche oder update, soll dieses dann automatisch in den DAten für das WebGIS widergespiegelt werden. Deshalb fällt ein View oder ein MV aus. Das FWD möchte ich nur ungern machen weil ich davon gleich mal null Ahnung habe. Es sei denn mir erklärt dass jemand, was ich nicht glaube.

So ich hoffe ich hab es halbwegs sinnvoll erklärt.

Gruß Stefan

PS.: Ich hatte schon eine Lösung über einen Insert-Trigger mit vorlaufendem Delete der neuen Tabelle. Jedoch gab es Probleme mit einer Serial-Spalte und dem delete…

So langsam bin ich etwas ratlos.

Du meinst sicher FDW, nicht FWD?

In der Quelldatenbank:

Ich erstelle eine Tabelle mit 4 Spalten und einen VIEW, der nur 2 dieser Spalten hat. Ungefähr das, was Du also auch hast.
Dieser View soll dann als externe Tabelle dienen.

fdw_demo_source=# create table schweizerili(id serial primary key, col1 int, col2 int, col3 int, col4 int);
CREATE TABLE
fdw_demo_source=*# create view view_schweizerili as select id, col1, col4 from schweizerili;
CREATE VIEW
fdw_demo_source=*# commit;
COMMIT

In der Zieldatenbank:
Ich erstelle einen entfernten Server, eine entfernte Tabelle (die auf den oben erstellen View zeigt) und ein User-Mapping.

fdw_demo_destination=# create server server_schweizerili foreign data wrapper postgres_fdw options(host '127.0.0.1', port '5432', dbname 'fdw_demo_source');
CREATE SERVER
fdw_demo_destination=*# create foreign table kopie_schweizerili (id int, col1 int, col4 int) server server_schweizerili options(table_name 'view_schweizerili');
CREATE FOREIGN TABLE
fdw_demo_destination=*# create user mapping for akretschmer server server_schweizerili options (user 'akretschmer', password 'akretschmer');
CREATE USER MAPPING

That’s all. Du kannst nun in Deiner Quelltabelle “schweizerili” Daten eingeben, im View “view_schweizerili” siehst Du nur das, was exportiert werden soll, und in der anderen Datenbank, Tabelle “kopie_schweizerili” 1:1 das, was im View steht, und damit auch aktuell den Inhalt der Quelltabelle, begrenzt auf das, was Du sehen willst.


Das geht so nun auch über wirklich Remote Server, Du kannst das aber auch auf einem lokalen Server mit 2 DB’s so machen (mache ich ja auch)

Andere Lösungen wären triggerbasierte Replikationen wie Slony oder Londiste oder ab PostgreSQL 9.4 logical Streaming Replication. (etwas, was Kollegen aus meiner Firma entwickelt haben)

Du vermischt einige Begriffe, daher ist nicht ganz klar, was Du genacht hast/willst. Ein Schema ist was anderes als eine Datenbank. Ein TRIGGER und ein VIEW kann schemaübergreifend arbeiten, nicht aber Datenbank- oder gar Serverübergreifend. Wenn Du innerhalb einer DB bist und ‘nur’ schemaübergreifend arbeiten willst wäre das allereinfachste für Dich ein VIEW.

Ok, etwas konfus.
Du möchtest 5 Felder deiner GeoDIN-Tabelle in eine andere Tabelle in einem anderen Schema der gleichen Datenbank ablegen. Dazu verwendet man einen Trigger, der auf INSERT/UPDATE/DELETE reagiert. Ob an an dieser Stelle bereits nach den geänderten Felder filtern kann weiß ich nicht: bei Oracle geht das , Postgres bin ich mir nicht sicher. Du rufst den Trigger am Besten nach deiner Aktion auf als AFTER auf.
Innerhalb des Triggers kannst du mit der Systemvariablen (Kap. 40.9.1 in der Doku) unterscheiden, welche Operation deinen Trigger ausgelöst hat und nach Änderungen in den von dir ausgesuchten Felder suchen Hier kannst du mit einer einfachen IF-Abfrage entscheiden, welche Aktionen in der Kopie-Tabelle ausgeführt wird. Also z.B. Einfügen, wenn neue Daten hinzukommen, Ändern, wenn sich an deinen Feldern etwas geändert hat oder z.B. ignorieren, wenn ein Datensatz gelöscht wird (hier ist aber darauf zu achten, das im Original die ID nicht wieder vergeben wird).
Die suche nach Änderungen würde ich mit einer OR- Bedingung machen etwa so also:

if old.Feld1 <> new.Feld1 or old.Feld2 <> new.Feld2 ... then update kopie.kopie_tabelle (Feld1, Feld2,...) set (Feld1, Feld2,...) = (new.Feld1, new.Feld2,...) where original.id = kopie.kopie_tabelle.id

Zusatz: Wenn du das in einer anderen Lokalen Datenbank haben möchtest, lege dir in der Kopiedatenbank eine Foreign-Table mit fdw an, akretscher hat das ja beschrieben. Ich mache das im Übrigen auch gerne so. Mit der Foreign-Table kannst du dann nach belieben andere Views etc. füttern und Berechnungen vornehmen. Das wäre IMHO das einfachste und ist ohne externe Tools und Konfiguration zu erledigen.

Gruß Uwe