Tuesday 12 November 2013

Verwendung von TB_SQL

Im Beitrag gestern hatte ich erwähnt, dass es bei der Auswertung von Datumsangaben innerhalb von "Ausdrücken" ein Problem gibt.

Mit Map ist man recht flexible und hat so den Vorteil, dass man oft auf unterschiedlichen Wegen zum gleichen Ergebnis gelangen kann. Um das Problem bei der Datumsauswertung zu umgehen hatte ich einen View angelegt, der die erforderlichen Berechnungen vornimmt. Ein Vorteil ist hier, dass ich mehrere Layer haben - im Augenblick 6 - die diesen View nutzen. Muss ich die Datumsberechnung ändern, dann lässt sich das einfacher in einem View vornehmen als in 6 unterschiedlichen Layern.

Der Datumsauswertung im View sieht ungefähr so aus:
...
t2t_fid,
    CASE
      WHEN erfassungsdatum BETWEEN to_date('31.08.2007','DD.MM.YYYY') AND to_date('31.08.2008','DD.MM.YYYY')
      THEN 2007
      ...
      ELSE NULL
    END ER_DATUM_JAHR


Für die thematische Darstellung wird nun die neue Spalte "ER_DATUM_JAHR" ausgewertet, die die Jahresangabe enthält.

Man kann die Problematik aber auch ohne View lösen - allein mit Konfiguration im Layer. Dazu erstellt man eine Berechnung und verwendet dann die Funktion "TB_SQL". Über TB_SQL können die Daten aus der Tabelle während der Abfrage modifiziert werden. Die Datumsauswertung erfolgt dabei mit der gleichen Syntax wie die Auswertung im View. Die einzelnen Schritte:

1. Funktion "Berechnung erstellen" im Kontextmenü des Layers auswählen
2. Namen für die neue Spalte vergeben
2. in das Eingabefeld: TB_SQL('') eingeben
3. Die gewünschte SQL Abfrage zwischen die Hochkomma setzen, z.B.:

 TB_SQL(' select  CASE
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2007'',''DD.MM.YYYY'') AND to_date(''31.08.2008'',''DD.MM.YYYY'')
      THEN ''2007''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2008'',''DD.MM.YYYY'') AND to_date(''31.08.2009'',''DD.MM.YYYY'')
      THEN ''2008''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2009'',''DD.MM.YYYY'') AND to_date(''31.08.2010'',''DD.MM.YYYY'')
      THEN ''2009''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2010'',''DD.MM.YYYY'') AND to_date(''31.08.2011'',''DD.MM.YYYY'')
      THEN ''2010''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2011'',''DD.MM.YYYY'') AND to_date(''31.08.2012'',''DD.MM.YYYY'')
      THEN ''2011''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2012'',''DD.MM.YYYY'') AND to_date(''31.08.2013'',''DD.MM.YYYY'')
      THEN ''2012''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2013'',''DD.MM.YYYY'') AND to_date(''31.08.2014'',''DD.MM.YYYY'')
      THEN ''2013''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2014'',''DD.MM.YYYY'') AND to_date(''31.08.2015'',''DD.MM.YYYY'')
      THEN ''2014''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2015'',''DD.MM.YYYY'') AND to_date(''31.08.2016'',''DD.MM.YYYY'')
      THEN ''2015''
      WHEN erfassungsdatum BETWEEN to_date(''31.08.2016'',''DD.MM.YYYY'') AND to_date(''31.08.2017'',''DD.MM.YYYY'')
      THEN ''2016''
      ELSE NULL
    END ER_DATUM_JAHR  from WPO_V_EB_STANDORT where fid = g.fid' )


Hinweise:
- das Ergebnis der Abfrage darf nur eine Spalte zurückliefern (im Beispiel wird nur das Erfassungsdatum ausgewertet)
- das Ergebnis der Abfrage darf nur eine Zeile zurückliefern (im Beispiel über WHERE Bedingung gewährleistet: where fid = g.fid)
- das Ergebnis der Abfrage muss vom Datentyp "Text" sein (im Beispiel ist das Ergebnis (Jahreszahl) innerhalb von Hochkomma gesetzt und damit als Text definiert).
- das Hochkomma muss zweimal gesetzt werden falls es im SQL Ausdruck erforderlich ist (Maskierung: to_date(''31.08.2016'',''DD.MM.YYYY'') anstelle to_date('31.08.2007','DD.MM.YYYY') im View).

Um den Bezug zu der Datentabelle zu erstellen verwendet man immer den Alias "g". Im Beispiel wird keine weitere Tabelle abgefragt sondern nur eine Spalte der Tabelle ausgewertet. Man kann aber ohne weiteres auf andere Tabellen - z.B. Domaintabellen – zugreifen und so z.B. eine ID mit dem zugehörigen Wert ersetzen.

Die Berechnung sollte man vor dem Anwenden in die Zwischenablage kopieren. Enthält die Berechnung ein Fehler lässt sich anschliessend der Dialog zum Erstellen der Berechnung nicht mehr öffnen und man muss von vorne beginnen. Bei einem Fehler erhält man den Oracle Fehlercode und den gesamtem SQL Ausdruck zurück, den Map bei der Abfrage der Datenquelle verwendet, z.B.:

Speichern der Objekte im Cache fehlgeschlagen.
FDO-Befehl konnte nicht ausgeführt werden.
ORA-00913: Zu viele Werte  'SELECT g.GEOM.SDO_POINT.X, g.GEOM.SDO....



Die Map Hilfe enthält noch weitere Hinweise und Beispiele.

Zu beachten ist: verwendet man TB_SQL im Layer dann ist man später auf den Topobase FDO Datenprovider festgelegt. Man kann dann nicht mehr zum FDO Oracle Provider wechseln (z.B. für die Web-Auskunft). TB_SQL ist keine allgemeine FDO Funktion sondern spezifisch für den Topobase – Provider.

Im nächsten Beitrag werde ich kurz zu Performance-Auswirkungen schreiben.

2 comments:

  1. das beispiel ist kompliziert wenn man nur mal schnell nachschauen will wie der Syntax war. Hier ein einfacheres Beispiel:

    tb_sql('select to_char(max(id_function)) from wa_pipe where fid = g.fid_parent')
    - tb_sql() - innerhalb alles in Hochkomma
    - ergebnis in "CHAR" umwandeln
    - sicherstellen, dass nur ein Ergebnis zurückgeliefert wird (max())
    - g als alias auf die featuretabelle, an die die Berechnung angehängt wird

    robert

    ReplyDelete
  2. Habe bisher die Jahreszahl wie folgt ermittelt:

    select to_char(sysdate,'yyyy') as Jahr from dual

    Anstelle des Systemdatums kann natürlich auch jedes andere Datum verwendet werden.

    Stelli

    ReplyDelete